回溯迷宫算法似乎并没有一路走来

时间:2011-04-05 05:47:45

标签: recursion stack backtracking maze

基本上,我有这样的:首先,一堆代码生成一个不可遍历的迷宫。它基于一些参数在2D阵列的某些空间中随机设置墙壁。然后我有一个回溯算法通过它来敲除墙壁,直到整个事物是可穿越的。问题是,程序似乎并没有一直回到堆栈中。

这是非常标准的回溯代码。算法从随机位置开始,然后以伪代码进行:

move(x,y){
    如果你可以上去并且还没有去过那里:
        move(x,y - 1)
    如果你能够正确而且还没有去过那里:
        移动(x + 1,y)
...
}

等其他方向。每次移动时,在坐标处设置两个单独的二维布尔线阵列(一个临时,一个永久),以表明您已经处于某个元素中。一旦它无法继续下去,它会检查永久性2D阵列以查看它是否到处都是。如果没有,它随机选择一个在访问和非访问空间之间的边界(根据临时数组)并删除它。这整个事情是在一个while循环调用,所以一旦它穿越迷宫的一大块,临时二维数组复位,而另一个保持它在另一个随机位置再次来回移动,直到永久二维数组显示,全迷宫有被遍历了。将移动方法中的检查与临时2D阵列进行比较,而不是永久性阵列。

这几乎可行,但我一直在最终生成的迷宫中找到一些无法到达的区域。否则它正在以我想要的方式生成迷宫。问题是,我发现它的原因是它不会一直回到堆栈中。

如果我改变它来检查完成,而不是永久性的一个临时二维数组(从而使得做一个完整的遍历一次运行,以纪念它完成的,而不是做跨多个迭代一个完整的运行),它会去一直等待。我必须设置一个计数器来打破它。结果是一个“迷宫”,远远的,太多的墙被移除。检查算法采用的路线,我发现它没有正确回溯并没有返回堆栈中的近远不够在堆栈内,往往只是被卡住一个元素上几十个递归宣布自己完成无故前完全没有需要移除的墙壁。

我已经尝试过两次运行前一次,但它不断敲出不需要被击倒的墙壁并使迷宫太稀疏。我不知道为什么会发生这种情况。

1 个答案:

答案 0 :(得分:1)

在尝试创建迷宫时,我遇到了类似的问题。 制作迷宫时最重要的是尽量不要在迷宫中创造连通房的孤立“岛屿”。这是我在伪代码中的解决方案

Room r=randomRoom();

while(r!=null){
    recursivelyDigNewDoors(r);
    r=null;
    for(i=0;i<rooms.count;i++){
        if(rooms[i].doors.length == 0 && rooms[i].hasNeighborWithDoor() ){ 
        //if there is a room with no doors and that has a neighbor with doors
        Create a door between the doorless room and the one 
        connected to the rest of your maze
        r=rooms[i];
        }
   }
}

其中recursivelyDigNewDoors与你的move()函数非常相似

实际上,您可能希望

  • 将“门”描述为缺少墙壁
  • 和没有门的房间,有四面墙的房间

但一般原则是:

  1. 在某处开始递归算法
  2. 当算法停止时:找到一个有1个未访问的方块和1个访问过的地方。
  3. 将这两者联系起来,继续从之前未访问过的广场
  4. 当没有两个方格符合(2)时,您已完成并且所有方块都已连接