【问题标题】:prim's algorithm generated maze missing wallsprim 算法生成迷宫缺失的墙壁
【发布时间】: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 语句后,它仍然会弄乱边界。

标签: c# wpf algorithm maze


【解决方案1】:

我尝试了您的代码,如果您将方法外的 new Random 移动到成员变量(因此它只创建一次),那么它似乎工作得很好。

没有代码可以确保整个迷宫的边缘有边界:迷宫会愉快地一直游荡到任何边缘。您看到的是每次重置 Random 导致的非随机性伪影。

如果在该方法中一遍又一遍地将 Random 设置为相同的种子,我会看到两侧也有很长的运行时间。

这是 15x15 的示例输出,具有适当的随机值:

XXXXXXXXX X X X
X         X X X
X X XXXXXXXXXXX
X X X     X   X
XXXXXXXXX X X X
X X         X X
X XXX XXXXXXX X
  X   X   X   X
XXXXX X X XXX X
X     X X      
XXXXXXX X XXXXX
X X   X X X   X
X XXX XXXXXXX X
  X X X X      
XXX X X XXXXXXX

【讨论】:

  • 我现在已经将新的 Random 移到了方法之外,但是在一些关于迷宫大小的测试之后,它似乎会在迷宫大小上生成偶数的随机墙,或大于 33
【解决方案2】:

我建议更多地从基于图形的角度来解决这个问题,而不是从“迷宫”的某些特定表示。

另请参阅我对this question 的回复。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-15
    • 1970-01-01
    • 1970-01-01
    • 2012-08-02
    • 1970-01-01
    • 2019-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多