递归除法迷宫生成算法
Posted
技术标签:
【中文标题】递归除法迷宫生成算法【英文标题】:Recursive Division Maze Generation Algorithm 【发布时间】:2014-02-13 08:23:49 【问题描述】:我目前正在处理,我想我快到了。我目前有一个二维数组,20 个单元格宽,15 个单元格高。该数组包含单元格对象,其中包含行、列和一个布尔变量以指示它是否是一堵墙。
每当我取消评论时
generateMaze(height, maxWidth-randomColumn, 1, randomColumn+1);
我得到一个堆栈溢出。没有它,它只会向左和向上遍历,我需要让它也向右和向下遍历。我已经盯着这个看了很长时间,想弄清楚为什么,但就是看不出来。
编辑:我现在可以生成一些东西,但是迷宫经常被阻塞,即有路径被阻塞。所以如果我设置一个随机的起始位置,它可能会被墙包围。
private void generateMaze(int minColumn, int maxColumn, int minRow, int maxRow)
int width = maxColumn - minColumn;
int height = maxRow-minRow;
if (width > 2 && height > 2)
if ("VERTICAL".equals(getOrientation(height, width)))
splitVertical(minColumn, maxColumn, minRow, maxRow);
else
splitHorizontal(minColumn, maxColumn, minRow, maxRow);
private void splitVertical (int minColumn, int maxColumn, int minRow, int maxRow)
int randomColumn = getRandomNumber(minColumn, maxColumn);
for (int i= minRow; i < maxRow; i++)
maze[i][randomColumn] = new Cell (i+1, randomColumn+1, true);
maze[(getRandomNumber(minRow, maxRow))][randomColumn].setWall(false);
generateMaze(minColumn, randomColumn, minRow, maxRow);
generateMaze(randomColumn, maxColumn, minRow, maxRow);
private void splitHorizontal (int minColumn, int maxColumn, int minRow, int maxRow)
int randomRow = getRandomNumber(minRow, maxRow);
for (int i = minColumn; i < maxColumn; i++)
maze[randomRow][i] = new Cell (randomRow+1, i+1, true);
generateMaze(minColumn, maxColumn, minRow, randomRow);
generateMaze(minColumn, maxColumn, randomRow, maxRow);
private String getOrientation(int height, int width)
Random rand = new Random();
if (height > width)
return "HORIZONTAL";
else if (width > height)
return "VERTICAL";
else
int randomNumber = rand.nextInt(2);
if (randomNumber == 0)
return "HORIZONTAL";
else
return "VERTICAL";
private int getRandomNumber(int x, int y)
int minimum = x;
int maximum = y;
int randomNumber = 0;
Random rand = new Random();
randomNumber = rand.nextInt((maximum-minimum)+1)+ minimum;
return randomNumber;
【问题讨论】:
【参考方案1】:编辑:我注意到你在开始时有停止条件。我的错。
如果代码无限运行,请添加一些调试打印,以查看递归的进度。似乎宽度和高度没有正确更新。也许您计算的尺寸不正确?
我没有全面检查算法,但一般问题是没有停止条件。
在递归函数中你总是递归的。错了,你必须检查你是否需要再深入一步。
如果遇到问题,在递归函数中,您必须检查剩下的板是否仍然可整除。如果函数中还剩下 1x1 网格,那就死路一条了。
【讨论】:
当我做 width >= 10 时,它在没有 *** 的情况下运行,但从 9 开始它会开始生成 ***,依此类推。男人.. :(【参考方案2】:在您取消注释的以下行中:
generateMaze(height, maxWidth-randomColumn, 1, randomColumn+1);
您正在使用允许值内的随机值调用递归函数,因此它将无限递归,因为大小不会减小,因此您永远不会满足您的停止条件:
if (height >= 2 && width >= 2)
你为什么用随机值调用它?也许正如 jnovacho 建议的那样,您应该添加另一个条件,例如,最大递归级别或类似的东西......
作为建议,尝试在 Eclipse 中调试您的代码,如果可能,添加一些 UnitTests 来检查您测试过的配置是否仍然有效...
【讨论】:
代码已编辑,没有更多的***,只是不准确。【参考方案3】:编辑
你的新代码好多了,但还是有问题:
您没有在splitHorizontal
中创建墙缝。
您的意思可能是循环到i <= maxRow
和i <= maxColumn
,而不是严格比创建墙时少。
正如我在之前的编辑中提到的,您仍在用新墙(无论是平行还是垂直)堵住现有墙壁中的缝隙。
正如其他人所建议的,您的递归不正确。您要拆分的尺寸未正确收缩。您有时也会忽略您传递的信息。
不正确的递归
最小高度和宽度被丢弃并替换为1
,宽度被丢弃并替换为maxWidth
:
generateMaze(height, randomColumn-1, 1, 1);
//generateMaze(height, maxWidth-randomColumn, 1, randomColumn+1);
当第二次调用被注释时,宽度或高度最终会随机下降到2
以下,结束递归。然而,当取消注释时,这两个调用之一肯定会有width >= 2
(因为maxWidth == 18 > 3
)。递归提前结束的可能性很小,但这只是因为您尚未以与 "VERTICAL"
案例相同(不正确)的方式在 "HORIZONTAL"
案例中实现第二个递归调用。
您的代码中对于参数height
、width
、mHeight
和mWidth
的确切含义似乎有些混淆。一组替代的函数参数可以帮助你推理它:
private void generateMaze(int startRow, int startCol, int endRow, int endCol)
//...
忽略传递的信息
专注于"VERTICAL"
案例。您为墙选择的列不尊重分区:
int randomColumn = getRandomNumber(mWidth, maxWidth);
mWidth
始终 1,maxWidth
始终 18,即使您已经分区。同样,您可能会将间隙放置在墙外:
for (int i = minHeight; i <= height; i++)
maze[i][randomColumn] = new Cell (i+1, randomColumn+1, true);
//Make random passage in the column
maze[rand.nextInt(height)+1][randomColumn].setWall(false);
rand.nextInt(height)+1
可能小于minHeight
。
小问题
还有其他一些潜在的问题:
从风格上讲,enum
比 string
更有意义,因为 getOrientation
的返回值。
墙可以与现有墙相邻(并与之平行)放置。
即使是直角,一堵墙也可能挡住现有墙的间隙或通道。
当任一 height
或width
高于其阈值时,递归应该继续,而不仅仅是两者都
【讨论】:
@user2472706 我已经用 cmets 更新了关于新代码的信息,不过对我来说这似乎是一个不同的问题了。以上是关于递归除法迷宫生成算法的主要内容,如果未能解决你的问题,请参考以下文章