【发布时间】:2020-05-10 17:14:56
【问题描述】:
所以我正在使用 prim 算法实现一个迷宫生成器。 迷宫本身生成的非常好,但是总是会缺少两堵(接触的)墙。
我正在生成的迷宫(右墙和底墙不见了):
Maze 1
这里缺少左侧和顶部的墙壁:
Maze 2
我用来生成迷宫的代码:
int _height = 50;
int _width = 50;
private bool[,] maze = new bool[_height, _width];
private void generateMaze()
{
//_height = 50
//_width = 50
List<MazeCell> walls = new List<MazeCell>();
int randX = genRand(1, _height-1);
int randY = genRand(1, _width-1);
maze[randX, randY] = true;
MazeCell start = new MazeCell(randX, randY, null);
for (int i = -1; i <= 1; i++)
{
for(int j = -1; j <= 1; j++)
{
if ((i == 0 && j == 0) || (i != 0 && j != 0))
continue;
try
{
if (maze[randX + i, randY + j])
continue;
}
catch(Exception e)
{
continue;
}
walls.Add(new MazeCell(randX + i, randY + j, start));
}
}
while (walls.Count > 0)
{
int index = genRand(0, walls.Count - 1);
MazeCell cur = walls[index];
MazeCell op = cur.opposite();
walls.RemoveAt(index);
try
{
if(!maze[cur.x, cur.y])
{
if(!maze[op.x, op.y])
{
maze[cur.x, cur.y] = true;
maze[op.x, op.y] = true;
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
if (i == 0 && j == 0 || i != 0 && j != 0)
continue;
try
{
if (maze[op.x + i, op.y + j])
continue;
}
catch (Exception e)
{
continue;
}
walls.Add(new MazeCell(op.x + i, op.y + j, op));
}
}
}
}
}
catch (Exception e) { }
}
}
private int genRand(int min, int max)
{
Random rnd = new Random();
return rnd.Next(min, max);
}
还有 mazeCell 类:
public class MazeCell
{
public int x;
public int y;
public bool passage = false;
MazeCell parent;
public MazeCell(int x, int y, MazeCell parent)
{
this.x = x;
this.y = y;
this.parent = parent;
}
public MazeCell opposite()
{
if (x.CompareTo(parent.x) != 0)
return new MazeCell(x + x.CompareTo(parent.x), y, this);
if (y.CompareTo(parent.y) != 0)
return new MazeCell(x, y + y.CompareTo(parent.y), this);
return null;
}
}
代码是我在这里找到的java代码的改编:http://jonathanzong.com/blog/2012/11/06/maze-generation-with-prims-algorithm
我找不到它突然决定拆除墙壁的地方。 非常感谢任何帮助!
【问题讨论】:
-
当您的高度和宽度为 50 时,是否包括右墙和底墙?如果索引从零开始,则 genRand(1, _height-1) 和 genRand(1, _width-1);是随机的。因此,您需要高度和宽度为 50 + 1,然后在索引 50(行和列)处放置一堵实心墙。或者将 height-1 更改为 height -2 以及将 width-1 更改为 width - 2。然后将实体墙添加到索引 50(行和列)。
-
@jdweng 50 确实包括墙壁,但是消失的墙壁也可以是左侧和顶部墙壁,这两者中的哪一个似乎完全随机发生。我已经用两者的例子更新了这个问题。
-
顺便说一句,您不应该继续创建
Random类的新实例。做一次,然后一遍又一遍地使用那个实例。这样,当您想以可重复的方式进行测试时,您也可以使用种子值创建它。 -
而不是使用异常来检测 op.x+i 和 op.y+j 在迷宫之外的情况,您应该使用与您想要使用的最小和最大界限的显式比较。这可能是您的算法泄漏到您想要维护的边界的地方。像这样捕获所有异常也是一种非常糟糕的做法,如果您要查找的是索引异常,请改用它。
-
@IanMercer 在将 random 设为全局变量并用比较替换所有 try catch 语句后,它仍然会弄乱边界。