Algorithm 递归迷宫算法(迷宫内旋转件)

Algorithm 递归迷宫算法(迷宫内旋转件),algorithm,recursion,maze,Algorithm,Recursion,Maze,我的程序的目的是用递归法求解迷宫。但是,我的迷宫是一个N*N网格,因此每个正方形都有一个方向属性: 南北、东西、东北、西北、东南、西南和X(方块) 每一块都可以顺时针旋转90* 如果我正在为传统迷宫编写递归解决方案,我会: if (x,y outside maze) return false if (x,y is goal) return true if (x,y not open) return false mark x,y as part of solution path if (FIND-

我的程序的目的是用递归法求解迷宫。但是,我的迷宫是一个N*N网格,因此每个正方形都有一个方向属性:

南北、东西、东北、西北、东南、西南和X(方块)

每一块都可以顺时针旋转90*

如果我正在为传统迷宫编写递归解决方案,我会:

if (x,y outside maze) return false
if (x,y is goal) return true
if (x,y not open) return false
mark x,y as part of solution path
if (FIND-PATH(North of x,y) == true) return true
if (FIND-PATH(East of x,y) == true) return true
if (FIND-PATH(South of x,y) == true) return true
if (FIND-PATH(West of x,y) == true) return true
unmark x,y as part of solution path
return false

不幸的是,我正在与旋转件斗争。我的程序结构是一个二维数组,其中填充了方形对象,这些对象保持其当前方向值,并具有旋转功能。如果您有任何建议,我们将不胜感激。

您的问题令人困惑。不可能知道你所说的细胞的方向和旋转规则是什么意思

话虽如此,所有递归回溯算法的形式都非常相似:

solveFrom(current: State)
    if current is complete
        add current to solution set
    else
        for each possible step from state
            solveFrom(state with step added)
添加步骤的
状态通常包括添加步骤,递归调用函数,然后再次删除它

如果您只需要第一个解决方案(而不是所有可能的解决方案),那么函数可以像您的一样返回布尔值


在你的情况下,我怀疑你的问题是,可能的步骤包括移动到新单元和旋转单元。目前,你只是在尝试涉及动作的步骤。您需要尝试这些步骤的所有可能组合,才能使算法工作。

递归算法是深度优先,效率低,并且产生任意解(在您的情况下,路径使用最多的北向运动)

一个更合适的方法是广度优先,这将很容易产生最短的路径,并且没有太多无用的迭代

也就是说,增加旋转单元的可能性意味着每个单元可能有4种状态(旋转0、90、180和270°),尽管(NS、EW)组只有2种不同的状态。 出于某种原因,可能的单元格不包括4向交叉,这实际上会因旋转而保持不变,但在更一般的情况下可能会发生

因此,您需要记住(x,y,r)而不仅仅是(x,y),其中r是所访问单元的旋转状态

现在,当您选择下一个单元时,您将需要枚举其所有可能的方向(4个用于NE、ES、SW、WN组,2个用于NS、EW组),然后检查每个单元是否存在路径,如果存在,请像您之前使用(x,y,r)一样维护(x,y,r)路径信息

至于广度优先算法,虽然有点离题,但基本上如下所示:

“候选行动”是指可能导致解决方案的行动。它包含一个单元格位置和方向,以及对上一个移动的引用(以产生最终结果)。
您还需要一个状态变量来跟踪已经尝试过的移动。
它可以被看作是布尔值数组,即 Cux[x,y,r] < /Cord>,但是如果您不幸地使用C++等原始超高效语言,则可以更有效地实现它。 您可以定义候选移动列表,并按如下顺序尝试它们:

E = entry cell
candidates := singleton list containing (E.x, E.y, 0° rotation, no parent)
while candidates is not empty
    C := get first element of candidates
    if (C.x, C.Y) is the exit
        // reconstruct solution path
        path := empty list
        do forever
           path.add (C)
           if C.parent == no parent
               return path
           C := C.parent
    if C has not already been visited
        mark C already visited
        for each neighbour N of C // the 4 cells around (C.x, C.y)
            for each rotation R of N // 0 for X, 2 for NS,EW, 4 for NE,ES,SW,WN
                if there is a path from C to R
                    add (N.x, N.y, R, C) to candidates
return failure
该算法将并行检查从入口点开始的所有路径,直到到达出口、遇到已访问的单元(处于相同的旋转状态)或用完要检查的原始单元(在这种情况下,牛头怪获胜)


要重建解决方案,请遵循退出移动前导,直到第一次移动(没有父项)。

请给出这样一个网格示例,以及程序应该生成的解决方案。为什么有6个方向,而不是4个或8个方向?它们是什么意思?