什么是生成迷宫的好algorithm?
假设你想要一个简单的迷宫,在一个由M格子构成的N上,有一条path通过,并且有很多死路,但是看起来是“正确的”(也就是说像某人手工制作的那样,没有太多的小死胡同, )。 有没有一种已知的方法来做到这一点?
从http://www.astrolog.org/labyrnth/algrithm.htm
recursion回溯:这与下面描述的recursion回溯解决方法有些相关,需要叠加到迷宫的大小。 雕刻时要尽可能地贪婪,如果在当前的单元格旁边,总是雕刻成未制作的部分。 每次移动到一个新的单元格时,推动堆栈中的前一个单元格。 如果当前位置旁边没有未制作的单元格,请将堆叠popup到之前的位置。 当你把所有的东西都从堆栈里拿出来时,迷宫就完成了。 这种algorithm使得Mazes具有尽可能高的“河stream”因子,死亡时间更less但死亡时间更长,而且通常是一个非常长而曲折的解决scheme。 虽然Primalgorithm有点快,但运行速度相当快。 recursion回溯不能用作墙壁加法器,因为这样做往往会导致沿着外部边缘的解决schemepath,其中迷宫的整个内部通过单个杆附着到边界。
他们只生产10%的死胡同
是由该方法生成的迷宫的一个例子。
事实certificate,有12个经典的algorithm来生成“完美”的迷宫。 迷宫是完美的,如果它只有一个解决scheme。 这里是一些链接到每个algorithm,按照我的偏好粗略的顺序。
- 克鲁斯卡的
- 普里姆的
- recursionBacktracker
- 奥尔德斯-布罗德
- 生长的树
- 亨特和杀
- 威尔逊
- 埃勒的
- 细胞自动机 (简单)
- recursion分区 (非常简单)
- 响尾蛇 (可预测)
- 二叉树 (有缺陷)
有关更多信息,请查看GitHub上的mazelib ,这是一个实现所有标准迷宫生成/解决algorithm的Python库。
一个非常简单的解决scheme可能是将随机权重分配给图边,并应用Kruskalalgorithmfind最小生成树。
有关迷宫生成algorithm的最佳讨论: http : //www.jamisbuck.org/presentations/rubyconf2011/index.html (几天前在HN上)。
奇怪的是,通过稍微改变“规范”的规则,并从随机configuration开始, 康威的生命游戏似乎产生了相当不错的迷宫!
(我不记得确切的规则,但是这是一个非常简单的修改,可以使细胞群体“致密化”)。
我最喜欢的方法是使用Kruskal的algorithm,但是当随机select和删除边缘时,根据所连接的边的types加权select。
通过改变不同边缘types的权重,可以生成具有许多不同特征或“个性”的迷宫。 在这里看到我的例子:
产生迷宫的方法之一是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