所以我工作的一个极小实现了跳棋类游戏,以帮助自己学习哈斯克尔更好。我遇到的麻烦该函数用于游戏状态的列表,并产生直接后继游戏状态的列表。像跳棋,如果跳可用,玩家必须把它。如果有一个以上的,玩家可以选择。

在大多数情况下,这个工程很好地与列表单子:遍历所有输入的游戏状态,遍历可能再涨所有弹珠,环比那个大理石的所有跳跃。此列表单子很好地变平所有列表伸到在结束状态的简单列表。

巧妙之处在于,如果没有跳转被发现对于给定的游戏状态,我需要返回当前的游戏状态,而不是空列表。下面的代码是我想出了这样做的最好的方式,但它似乎真的丑到我。如何把它清理干净有什么建议?

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”等),因为它们真的降低我的经验代码的大小。

请注意,代码没有测试,并且可以不进行编译。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top