哈斯克尔井字游戏

时间:2018-09-29 17:11:25

标签: function haskell tic-tac-toe

我正在尝试在Haskell中构建井字游戏,而我在使用功能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)) )

代码如下:

[((1,1),1), ((1,2),1), ((2,1),2), ((2,2),2), ((3,1),1), ((3,2),1), ((3,3),2)]

能否请您告诉我如何对大于3个元素的输入列表进行概括? 例如,输入可以是:{{1}}。 谢谢。

1 个答案:

答案 0 :(得分:0)

  

代码如下:

这是我的看法:

让我们首先定义 proper 数据类型:

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实例进行定位,并且仅考虑了“排序三元组”)

当然,这不是唯一的方法。一个值得注意的替代方法是将其放置在原位数组中,然后迭代找到解决方案。我认为Prolog风格的声明式样式更适合Haskell。