因此,我正在为类似跳棋的游戏开发极小极大实现,以帮助自己更好地学习 Haskell。我遇到问题的函数需要一个游戏状态列表,并生成直接后继游戏状态的列表。像跳棋一样,如果可以跳,玩家必须跳。如果有多个,玩家可以选择。
在大多数情况下,这与 list monad 配合得很好:遍历所有输入游戏状态,遍历所有可以跳跃的弹珠,遍历该弹珠的所有跳跃。这个列表单子很好地将所有列表扁平化为最后的简单状态列表。
诀窍是,如果没有找到给定游戏状态的跳转,我需要返回当前游戏状态,而不是空列表。下面的代码是我想出的最好的方法,但它对我来说真的很难看。关于如何清理它的任何建议?
eHex :: Coord -> Coord -- Returns the coordinates immediately to the east on the board
nwHex :: Coord -> Coord -- Returns the coordinates immediately to the northwest on the board
generateJumpsIter :: [ZertzState] -> [ZertzState]
generateJumpsIter states = do
ws <- states
case children ws of
[] -> return ws
n@_ -> n
where
children ws@(ZertzState s1 s2 b p) = do
(c, color) <- occupiedCoords ws
(start, end) <- [(eHex, wHex), (wHex, eHex), (swHex, neHex),
(neHex, swHex), (nwHex, seHex), (seHex, nwHex)]
if (hexOccupied b $ start c) && (hexOpen b $ end c)
then case p of
1 -> return $ ZertzState (scoreMarble s1 color) s2
(jumpMarble (start c) c (end c) b) p
(-1) -> return $ ZertzState s1 (scoreMarble s2 color)
(jumpMarble (start c) c (end c) b) p
else []
编辑:为 *Hex 函数提供示例类型签名。