题
所以我工作的一个极小实现了跳棋类游戏,以帮助自己学习哈斯克尔更好。我遇到的麻烦该函数用于游戏状态的列表,并产生直接后继游戏状态的列表。像跳棋,如果跳可用,玩家必须把它。如果有一个以上的,玩家可以选择。
在大多数情况下,这个工程很好地与列表单子:遍历所有输入的游戏状态,遍历可能再涨所有弹珠,环比那个大理石的所有跳跃。此列表单子很好地变平所有列表伸到在结束状态的简单列表。
巧妙之处在于,如果没有跳转被发现对于给定的游戏状态,我需要返回当前的游戏状态,而不是空列表。下面的代码是我想出了这样做的最好的方式,但它似乎真的丑到我。如何把它清理干净有什么建议?
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 []
编辑:提供示例类型签名为*六角功能
解决方案
巧妙之处在于,如果没有跳转被发现对于给定的游戏状态,我需要返回当前的游戏状态,而不是空表。
为什么呢?我已经写了极大极小几次,我无法想象这样一个功能的使用。难道你会更好与类型的函数
nextStates :: [ZertzState] -> [Maybe [ZertzState]]
或
nextStates :: [ZertzState] -> [[ZertzState]]
不过,如果你真的想回到“下一个状态的任一列表,或者如果该列表是空的,原来的状态”,那么你想要的类型为
nextStates :: [ZertzState] -> [Either ZertzState [ZertzState]]
,然后可以很容易地压平足够。
至于如何实现,我推荐定义类型的辅助功能
[ZertzState] -> [(ZertzState, [ZertzState])]
和比可以映射
(\(start, succs) -> if null succs then Left start else Right succs)
以上的结果,加上各种其它的东西。
由于弗雷德·布鲁克斯说(意译),一旦你的类型权,实际上代码写入本身。
其他提示
不要滥用单子记法列表中,它是没有这么重。此外,您可以使用列表中理解以同样的方式:
do x <- [1..3]
y <- [2..5] <=> [ x + y | x <- [1..3], y <- [2..5] ]
return x + y
现在为 '简化'
listOfHex :: [(Coord -> Coord,Coord -> Coord)]
listOfHex = [ (eHex, wHex), (wHex, eHex), (swHex, neHex)
, (neHex, swHex), (nwHex, seHex), (seHex, nwHex)]
generateJumpsIter :: [ZertzState] -> [ZertzState]
generateJumpsIter states =
[if null ws then ws else children ws | ws <- states]
where -- I named it foo because I don t know what it do....
foo True 1 = ZertzState (scoreMarble s1 color) s2
(jumpMarble (start c) c (end c) b) p
foo True (-1) = ZertzState s1 (scoreMarble s2 color)
(jumpMarble (start c) c (end c) b) p
foo False _ = []
foo _ _ = error "Bleh"
children ws@(ZertzState s1 s2 b p) =
[ foo (valid c hex) p | (c, _) <- occupiedCoords ws, hex <- listOfHex ]
where valid c (start, end) =
(hexOccupied b $ start c) && (hexOpen b $ end c)
在顶部列表commprehension的让咱们打扰我了一点,但我不知道所有的代码,我真的不知道如何做到这一点在其他的方式。如果你能在深度修改更多,我建议你使用更多组合子(地图,foldr相似,与foldl”等),因为它们真的降低我的经验代码的大小。
请注意,代码没有测试,并且可以不进行编译。
不隶属于 StackOverflow