所以我正在为一个类似跳棋的游戏编写minimax实现,以帮助我更好地学习Haskell。我遇到麻烦的函数需要接受游戏状态列表,并生成立即后继游戏状态列表。就像跳棋一样,如果有可以跳的棋子,玩家必须跳。如果有多个选择,玩家可以自行选择。
对于大部分情况,这在列表单子上工作得很好:循环所有输入的游戏状态,循环所有可能被跳的棋子,循环该棋子的所有跳跃。此列表单子将所有列表都漂亮地展平成最后的简单状态列表。
问题在于,如果没有找到给定游戏状态的任何跳跃,则需要返回当前游戏状态而不是空列表。下面的代码是我想出来的最佳方法,但它看起来对我来说真的很丑陋。有什么建议可以使其更清晰?
对于大部分情况,这在列表单子上工作得很好:循环所有输入的游戏状态,循环所有可能被跳的棋子,循环该棋子的所有跳跃。此列表单子将所有列表都漂亮地展平成最后的简单状态列表。
问题在于,如果没有找到给定游戏状态的任何跳跃,则需要返回当前游戏状态而不是空列表。下面的代码是我想出来的最佳方法,但它看起来对我来说真的很丑陋。有什么建议可以使其更清晰?
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函数提供示例类型签名。