什么是生成迷宫的好algorithm?

假设你想要一个简单的迷宫,在一个由M格子构成的N上,有一条path通过,并且有很多死路,但是看起来是“正确的”(也就是说像某人手工制作的那样,没有太多的小死胡同, )。 有没有一种已知的方法来做到这一点?

http://www.astrolog.org/labyrnth/algrithm.htm

recursion回溯:这与下面描述的recursion回溯解决方法有些相关,需要叠加到迷宫的大小。 雕刻时要尽可能地贪婪,如果在当前的单元格旁边,总是雕刻成未制作的部分。 每次移动到一个新的单元格时,推动堆栈中的前一个单元格。 如果当前位置旁边没有未制作的单元格,请将堆叠popup到之前的位置。 当你把所有的东西都从堆栈里拿出来时,迷宫就完成了。 这种algorithm使得Mazes具有尽可能高的“河stream”因子,死亡时间更less但死亡时间更长,而且通常是一个非常长而曲折的解决scheme。 虽然Primalgorithm有点快,但运行速度相当快。 recursion回溯不能用作墙壁加法器,因为这样做往往会导致沿着外部边缘的解决schemepath,其中迷宫的整个内部通过单个杆附着到边界。

他们只生产10%的死胡同

labyrnth/sample/recursiv.gif

是由该方法生成的迷宫的一个例子。

事实certificate,有12个经典的algorithm来生成“完美”的迷宫。 迷宫是完美的,如果它只有一个解决scheme。 这里是一些链接到每个algorithm,按照我的偏好粗略的顺序。

  1. 克鲁斯卡的
  2. 普里姆的
  3. recursionBacktracker
  4. 奥尔德斯-布罗德
  5. 生长的树
  6. 亨特和杀
  7. 威尔逊
  8. 埃勒的
  9. 细胞自动机 (简单)
  10. recursion分区 (非常简单)
  11. 响尾蛇 (可预测)
  12. 二叉树 (有缺陷)

有关更多信息,请查看GitHub上的mazelib ,这是一个实现所有标准迷宫生成/解决algorithm的Python库。

一个非常简单的解决scheme可能是将随机权重分配给图边,并应用Kruskalalgorithmfind最小生成树。

有关迷宫生成algorithm的最佳讨论: http : //www.jamisbuck.org/presentations/rubyconf2011/index.html (几天前在HN上)。

奇怪的是,通过稍微改变“规范”的规则,并从随机configuration开始, 康威的生命游戏似乎产生了相当不错的迷宫!

(我不记得确切的规则,但是这是一个非常简单的修改,可以使细胞群体“致密化”)。

我最喜欢的方法是使用Kruskal的algorithm,但是当随机select和删除边缘时,根据所连接的边的types加权select。

通过改变不同边缘types的权重,可以生成具有许多不同特征或“个性”的迷宫。 在这里看到我的例子:

https://mtimmerm.github.io/webStuff/maze.html

产生迷宫的方法之一是Primalgorithm的随机化版本。

从一个充满了墙壁的网格开始。 select一个单元格,将其标记为迷宫的一部分。 将单元格的墙添加到墙列表中。 列表中有墙:

从列表中select一个随机墙。 如果对面的细胞还没有进入迷宫,

(i)把墙壁作为通道,将相对侧的单元格标记为迷宫的一部分。

(ii)将单元格的相邻墙添加到墙列表中。

如果对面的单元格已经在迷宫中,请从列表中移除墙。

欲了解更多的理解请点击

下面是DFSalgorithm写成伪代码:

创build一个CellStack(LIFO)来保存单元格位置列表
设置TotalCells =网格中的单元格数量
随机select一个单元并将其称为CurrentCell
设置VisitedCells = 1

而VisitedCells <TotalCells查找所有墙的完整CurrentCell的所有邻居
如果一个或多个发现随机select一个
击倒它和CurrentCell之间的墙壁
推CellStack上的CurrentCell位置
使新的单元格CurrentCell
向VisitedCells添加1,否则从CellStackpopup最近的单元入口
使它成为CurrentCell endIf endWhile