没有死角的迷宫生成算法?

时间:2011-09-10 05:57:43

标签: algorithm maze

我正在寻找一种迷宫生成算法,可以生成没有死角但只有开始和结束的迷宫。像这样:

maze

来自http://www.astrolog.org/labyrnth/maze/unicursl.gif

的图片

我在哪里可以找到或开始构建这样的迷宫生成算法?

8 个答案:

答案 0 :(得分:15)

听起来你想要一个伪随机空间填充曲线(例如,参见 Context-based Space Filling Curves -EUROGRAPHICS ’2000 (PDF格式,1.1 MB))

看看 Space-filling curve

我怀疑你可以将一些随机性用于构建其中一个以实现你想要的东西。

答案 1 :(得分:5)

我会从完全黑色(全)方块开始,并尝试挖掘路径。在挖掘过程中,您可以轻松确保没有死角,只需坚持下去。使用回溯,深度优先搜索算法。做一个“随机游走” - 在每个步骤中,随机决定是保持方向还是改变方向。检查死胡同状态 - 如果你遇到困难,你可以说“好吧,我已经完成了,我已经完成了”,或者,如果你认为迷宫还没有挖到足够的东西,那就回去吧。永远记住你以前做过的事情,并随机尝试其他一些动作。可能会使用一些启发式方法来选择某些方向,例如,在躲避墙壁之前始终保留一些自由空间,首先尝试在墙壁周围走动等等 - 这样您就可以找到所需的解决方案,更快地填满所有方块。 / p>

答案 2 :(得分:4)

我想我已经找到了另一种方法,但是我还没有对它进行过广泛的测试。

请参阅https://twitter.com/tdhooper/status/340853820584230915/photo/1

从左到右:

答案 3 :(得分:2)

我没有想到这一点,只是一个想法:

  • 不要集中在路上,而是在墙上
  • 从黑色外部广场开始
  • 逐步在现有墙块附近的任意位置添加墙块,保持从始至终保留路径的条件
  • 当没有路径单元格有两个以上的路径邻居时,就完成了

墙壁新位的“任意”选择过程可以开始试图“生长”垂直于外墙的直线部分,然后在某个阶段切换到尽可能填充。

如果它被卡住,它可能需要回溯的能力。

可能效率不高。

答案 4 :(得分:2)

在您给出的示例中,从开始到结束只有一条实际路径。如果这就是你想要的全部,我想你可以随意散步!

概念很简单:给定迷宫的外边界,起点和终点,编写一个函数,从起点开始随机行走,最终在终点结束。条件是我们的“随机漫步者”只能从前一个方块向上,向下,向右或向左移动,并且不能进入先前遍历的方块的一个方格内(这会产生墙壁)。

正如我所看到的,这里有两个算法挑战。第一个是确定我们是否在先前遍历的正方形(碰撞)的一个平方内。也许我们可以维护一个遍历的正方形(它们的坐标)和迷宫边界的列表,并且对于每个新的正方形评估距离列表中每个正方形的距离。但这听起来效率不高。

另一个挑战实际上是通过随机游走达到终点。如果与先前遍历的方格碰撞不是问题,我们最终必然会达到我们的终点,但是对于它们,我们遇到的问题是我们可能会从终点开始。避免这种情况的方法是检查并避免进入循环。如果我们避免进入由遍历路径和/或迷宫边界形成的循环,那么我们保持到终点的可能路径。至于实际想知道我们是否处于循环中......呃,这有点难。

如果您已经有迷宫解决算法,只要有可能的碰撞就可以运行它,看看从当前方块到端点是否存在路径。当你运行它时,让它认为所有先前遍历的正方形都是墙壁,以及它们的边界。

答案 5 :(得分:2)

啊 - 我发现了一种更容易产生单一迷宫的方法。

从空白网格开始,并用小的2x2循环填充它。如果网格是偶数奇数,你需要混合一些2x3循环,如果它是奇数,你将不得不留下一个正方形 - 我通常留下一个角落未填充。

接下来,任意地将循环连接在一起以形成更大的循环 - 因此(例如)2个2x2循环变为单个4x2循环。继续这样做,确保你没有加入循环回到自身。

最终你会得到一个单循环,它会占用原始循环场所占用的所有单元格。在任何位置打破这个循环,你就会有一个单一的迷宫,其中起点和终点位置彼此相邻。

现在你可以通过形成和打破小环来移动网格周围的端点 - 将端部钩到迷宫中的另一个点,然后打破对面的T形接头以重新形成单个字符串有一个新的结束位置。

如果你正在制作奇怪的迷宫,请使用最后一种技术将你的一端瞄准未填充的角落以完成你的迷宫。

答案 6 :(得分:1)

当“行走”时,保持对堆叠中每个步骤所做的更改,这样你可以向前看x步,然后在每个阶段,这样你就可以不采取进一步的步骤(走进角落或像螺旋一样步行)弹出堆栈,直到你有一个可行的步行路径并继续从那里走,直到堆栈为空(即你一直弹回堆栈,因为在前一步没有可行的邻居)。然后将转换应用于迷宫数据结构。

答案 7 :(得分:1)

我正在研究这个问题......从一个边缘开始,我随机地走过一个正方形阵列,当我通过它们时,标记具有路径长度的单元格。

当你遇到困难(并且你会)时,创建一个T型交叉点,形成一个环路,其中最近的路径与你相邻(但见下文)。然后我沿着现有的路径追溯到丁字路口的另一侧,并在那里打破了循环。这个悬垂的尾巴然后形成随机行走的新“头”(记得从路径源重新计算路径长度),你可以继续。

实验表明,通过这样做,它(或者还没有 - 见下文)进入创建新尾巴的循环,只要你的新“尾巴”被困,你不只是无脑地如果它是最新的,那么重新形成一个你刚刚离开的单元格的链接 - 在这种情况下选择最近的第二个。

终止的情况是当你在边缘元素上“卡住”,并且你已经填充了数组(你的路径长度与数组的区域相同) - 你就完成了。您的起点将导致您的终点。

这似乎有两种可能的低效率和潜在的打嗝(我现在正在使用算法) - 有时你会走进一个角落,唯一的方法就是重新形成循环链接与你刚破坏的那个。然后,序列回溯到您之前所做的所有循环到您最初卡住的点。如果 不能去任何其他地方(它是另一个角落),那么你只会在两者之间反弹。有办法解决这个问题,但这意味着保留一些循环单元格列表,只有当你真正放下一条新路径时才清除它。

另一个是它似乎容易留下一个奇数方形未填充,特别是当你的数组是奇数时。我没有完全调查为什么会这样,而且当发生这种情况时,前一个角落问题似乎特别普遍。工作继续......

相关问题