递归迷宫算法(在迷宫中旋转棋子)

时间:2017-03-09 21:20:05

标签: algorithm recursion maze

我的程序的目的是通过递归递归地解决迷宫。但是,我的迷宫是一个N * N网格,每个方格都有一个方向属性:

NS,EW,NE,NW,SE,SW和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

不幸的是,我正在与旋转部分挣扎。我的程序结构是一个填充方形对象的二维数组,它们保持当前的方向值和一个旋转函数。任何建议都将不胜感激。

2 个答案:

答案 0 :(得分:0)

你的问题很混乱。你不可能通过一个单元格的指示和旋转它们的规则来表达你的意思。

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

solveFrom(current: State)
    if current is complete
        add current to solution set
    else
        for each possible step from state
            solveFrom(state with step added)

state with step added通常涉及添加步骤,递归调用函数然后再次删除它。

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

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

答案 1 :(得分:0)

递归算法是深度优先的,效率很低,并产生任意解决方案(在您的情况下使用最大数量的北移动的路径)。

更合适的方法是广度优先,这将很容易产生最短的路径,并且减少无用的迭代。

话虽如此,增加旋转细胞的可能性意味着每个细胞具有潜在的4种状态(旋转0°,90°,180°和270°),尽管(NS,EW)组仅具有2种不同的状态。 由于某种原因,可能的单元格不包括4路交叉,实际上通过旋转不会改变,但在更一般的情况下可能发生。

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

现在,当您选择下一个单元格时,您需要枚举所有可能的方向(对于NE,ES,SW,WN组为4,对于NS,EW组为2),然后检查每个单元是否存在路径,如果确实如此,只需使用(x,y)维护您的(x,y,r)路径信息。

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

“候选人举动”是一个可能导致解决方案的举措。它包含一个单元格位置和方向,以及对前一个移动的引用(为了产生最终结果) 你还需要一个状态变量来跟踪已经尝试过的动作 它可以被视为一个布尔数组,即visited[x,y,r],但如果您不幸使用 primitive 这样的超高效语言,您可以使用关联内存或哈希表更有效地实现它。 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

该算法将检查从入口点并行产生的所有路径,直到它到达出口,遇到已经访问过的单元格(处于相同的旋转状态)或耗尽原始单元格进行检查(在这种情况下,牛头怪赢了)。

要重建解决方案,请按照退出移动前辈进行操作,直到第一次移动(没有父级)。