【问题标题】:Haskell back tracking recursionHaskell 回溯递归
【发布时间】:2023-09-03 07:56:01
【问题描述】:

我在 haskell 中实现这个。

https://www.cs.bu.edu/teaching/alg/maze/

当达到“目标”时,我能够到达获取列表,但如果无法访问目标,则不会更新列表。例如

...#@                           !!!#@
..#..                           !!#..
.##.#     it should return      !##.#
...#.                           !!!#.

我的代码如下

path maze x y
    | x >= length (head maze) = (False, maze)
    | y >= length maze = (False, maze)
    | x < 0 = (False, maze)
    | y < 0 = (False,maze)
    | check maze x y '+' = (False, maze)
    | check maze x y '#' = (False,maze)
    | check maze x y '!' = (False, maze)
    | check maze x y 'G' = (True,maze)
    | fst east = (True,snd east)
    | fst south = (True, snd south)
    | fst west = (True, snd west)
    | fst north = (True, snd north)
    | fst noWay = (True, snd noWay)
    | otherwise = (False, maze)
            where 
                    noWay = path (changeVal maze x y '!') x (y+1)
                    north = path(changeVal maze x y '+') x (y-1)
                    south = path (changeVal maze x y '+') x (y+1)
                    east = path (changeVal maze x y '+') (x+1) y
                    west = path (changeVal maze x y '+') (x-1) y

我没有得到结果。我是 Haskell 的新手,谁能帮我解决这个愚蠢的问题。

【问题讨论】:

  • NoWay/! 部分是您添加的,对吗​​?有两件事可能会出错:首先,您使用noWay失败,但您已经这样做了,并且看到使用south 这是不可能的 - 所以这种情况永远不应该匹配并且我认为您永远不会用“!”标记某些内容。为什么不在最后的otherwise 案例中标记它(删除noWay 案例) - 这应该可以解决问题。如果您在某处发布完整的代码(带有示例),我会很乐意检查这个;)
  • 这是整个代码。 changeVal 更改坐标处的值并检查坐标处的值。

标签: list haskell recursion maze


【解决方案1】:

马上,你的问题的原因似乎是那个

| otherwise = (False, maze)

使用原始的maze 而不是返回更新的。但是,即使将其替换为 snd noWay 也不会给您想要的输出。 (我认为它只会用!s 标记从您的起点向南的部分。)

还有一个更大的问题:当继续下一个递归步骤时,你的函数并没有保留上一步放置的标记,而是从原来的maze重新开始。相反,下一个递归步骤需要从前一个生成的最终迷宫标记开始。例如。 (看到你的警卫向东 -> 南 -> 西 -> 北)你需要 south 离开 east 完成的地方,类似于

south = path (snd east) x (y+1)

如果您以类似方式确定所有方向,则不需要noWay。 (到那时将没有未标记的地方需要检查。)相反,如果 north 案例失败,那么它将标记除您的初始点之外的所有内容,因此您可以这样做

| otherwise = (False, changeVal (snd north) x y '!')

【讨论】: