2

所以我写了一个 hexappawn 游戏,我正在尝试制作一个函数,如果棋盘处于获胜状态,则返回 True,此时它看起来像这样:

checkWin :: BoardState -> Bool
checkWin b1@(blackPieces,whitePieces,turn,size,win)
  |(length blackPieces) == 0 = True
  |(length whitePieces) == 0 = True
  |length (generateMoves b1) == 0 = True
  |otherwise = False

因此,如果没有留下黑色或白色棋子,或者没有人可以移动,但如果对方棋子到达棋盘末端(另一种在六棋子中获胜的方式),则此方法无效。变量blackPieceswhitePieces是坐标列表,即 [(1,1),(2,1),(3,1)] 这些棋子在大小为n 的棋盘上的位置(如果白棋,则转为真)

我很想将这些条件添加到方法中,但编译器不喜欢它。

  |(_,1) `elem` whitePieces = True
  |(_,size) `elem` blackPieces = True

有没有其他方式可以说“ whitePieces中是否有第二个元素是 1 的元组(即到达棋盘的另一边)。”

提前感谢您的有用评论。

4

3 回答 3

7

所以我们想要一个函数,它接收某物的列表、某物[a]的谓词(a->Bool)并返回一个Bool. 快速检查一下Hoogle,我们回来了

any :: (a -> Bool) -> [a] -> Bool
Applied to a predicate and a list, any determines if any element of
the list satisfies the predicate. For the result to be False, the list must be finite

所以

 (_,1) `elem` whitePieces 

变成

 any (\(_, x) -> x == 1) whitePieces

或(正如永恒马特提醒我的那样)

any (==1) ( map snd whitePieces )

等等


顺便说一句,检查列表是否为空的最佳方法是通过模式匹配或null函数。length == 0 方法将遍历所有链表,如果链表是无限的,甚至可能进入无限循环。

于 2011-10-23T22:32:47.930 回答
2

例如,您可以使用filter

not $ null (filter wincond whitePieces)
    where wincond x = snd x == 1

此表达式是True如果whitePieces第二个条目1的列表不是空列表 ( [])

或者你可以使用map

or (map (\x -> snd x == size) blackPieces)

这个表达式确实:首先它检查一个元素是否blackPieces有第二个条目等于size并给出一个TruesFalses( [Bool]) 的列表,然后函数or给出True它们中的任何一个是否是True

于 2011-10-23T22:23:42.540 回答
2

编译器不喜欢这样的原因是因为_仅适用于模式匹配。下划线的意思是“我可以将这部分数据绑定到一个变量名,但我不需要。”

您尝试使用它的方式不同:您基本上是说“是否存在一个x这样(x,1)的元素whitePieces?”

你能看到差别吗?另请参阅Haskell 2010 > 表达式 # 模式匹配

于 2011-10-24T03:12:25.650 回答