игра haskell TicTacToe - PullRequest
       9

игра haskell TicTacToe

0 голосов
/ 29 сентября 2018

Я пытаюсь построить игру в крестики-нолики в haskell, и у меня возникают проблемы с функцией haswon.Функция должна возвращать True, если для данного игрока p и игрового поля bs он уже выиграл игру, а False в противном случае.

Вот код:

Int -> [((Int,Int),Int)] -> Bool
haswon p [((a,d), x), ((b,e), y), ((c,f), z)] = (x == y && y == z && x == p) && ( ((a == b) && (b == c)) || ((d == e) && (e == f)) || ( (a == d) && (b == e) && (c == f) && (a /= b) && (b /= c)) || ( (a == f) && (c == d) && (b==e)&&(a/=b)&&(b/=c)) )

Не могли бы вы сказать мне, как я могу обобщить это для списка ввода, который больше, чем 3 элемента?Например, ввод может быть: [((1,1),1), ((1,2),1), ((2,1),2), ((2,2),2), ((3,1),1), ((3,2),1), ((3,3),2)].Спасибо.

1 Ответ

0 голосов
/ 01 октября 2018

Вот код:

Вот мое мнение:

Давайте сначала определим правильных типов данных:

data Player = Black | White deriving (Eq, Show)
data Position = Position Int Int deriving (Eq, Show)
data Move = Move { position :: Position, player :: Player } deriving (Eq, Show)

Теперь фактическая функция просто подсчитывает количество строк, которые могут претендовать на выигрыш

hasWon :: Player -> [Move] -> Bool
hasWon p ms = (length $ winningLines p ms) > 0

Генерация выигрышных линий - это одно большое понимание:

winningLines p ms = [(x,y,z) | x <- ms,
                               y <- ms,
                               z <- ms,
                               oneLine (position x) (position y) (position z),
                               samePlayer (player x) (player y) (player z),
                               x /= y,
                               y /= z,
                               x /= z
                     ]

samePlayer px py pz = px == py && py == pz

oneLine (Position x1 y1) (Position x2 y2) (Position x3 y3) = sameRow || sameCol
    where
        sameRow = (y1 == y2 && y2 == y3)
        sameCol = (x1 == x2 && x2 == x3)

И, наконец, некоторое тестирование:

moves = [
    Move (Position 1 1) White,
    Move (Position 2 1) White,
    Move (Position 3 1) White
    ]

main :: IO ()
main = do
    print $ hasWon White moves
    print $ winningLines White moves

Решение использует только основы, поэтому вы должны быть в состоянии понять его довольно легко и добавить свои собственные исправления;в нем по-прежнему отсутствуют диагонали (их легко добавить), и он считает все строки 6 раз (потому что он учитывает все перестановки; его легко исправить с помощью экземпляра Ord для позиции и только с учетом "отсортированной тройки").

Конечно, это не единственный способ сделать это;одна из примечательных альтернатив - поместить его в массив на месте, а затем найти решение итеративно.Я думаю, что декларативный стиль в стиле Пролог просто лучше подходит для Haskell.

...