【问题标题】:Maze generation algorithm design (Recursive Division)迷宫生成算法设计(递归除法)
【发布时间】:2020-12-14 02:10:05
【问题描述】:

我正在尝试在我的寻路可视化解决方案中包含一个迷宫生成,以便生成当前应用程序可以处理的迷宫。

我找到了一个结构很好的网站,里面有一堆迷宫生成算法,但我主要关注一个:http://weblog.jamisbuck.org/2011/1/12/maze-generation-recursive-division-algorithm

我的编程语言知识主要是 C++,我拥有的应用程序是用 C++ + SDL2.0 构建的。

我的“网格”(2D 矩阵)由“单元/节点”组成,这些“单元/节点”由窗口表面上呈现的框纹理表示。每个“细胞”可以处于不同的状态 - 障碍 == 它是一堵墙 - 白色状态 == 它是通道。

我面临的一个问题是我的“通道”有时会被随机生成的下一堵墙挡住 - 这会导致无法解决的迷宫。

问题是如何避免生成的墙不会阻塞之前打开的通道?

代码:

void RecursiveDivision::divide(NodesMap* map, int x, int y, int width, int 

height, Orientation orientation, SDL_Renderer* renderer)
{
    if (width < 2|| height < 2)
    {
        return;
    }

    bool wallIsHorizontal = orientation == Orientation::Horizontal ? true : false;

    //Where the wall is
    int wX = x  + (wallIsHorizontal ? 0 : rand() % (width-1));
    int wY = y + (wallIsHorizontal ? rand() % (height-1): 0);
    //Where the passage is
    int pX = wX + (wallIsHorizontal ? (rand() % width) : 0);
    int pY = wY + (wallIsHorizontal ? 0 : (rand() % height));
    //How long is the wall
    int wallLenght = (wallIsHorizontal ? width : height);
    //On whitch axis will the wall be drawn
    int dX = wallIsHorizontal ? 1 : 0;
    int dY = wallIsHorizontal ? 0 : 1;
    //Draw the wall
    for (int i = 0; i < wallLenght; ++i)
    {
        if (wX != pX || wY != pY)
        {
            map->getNode(wX, wY)->hardChangeState(NodeState::OBSTACLE);
        }
        
        wX += dX;
        wY += dY;
    }

    //Render the current state
    map->render(renderer, nullptr);
    SDL_RenderPresent(renderer);
    
    int nX = x; int nY = y;
    int w = wallIsHorizontal ? width : (wX - x);
    int h = wallIsHorizontal ? (wY - y ) : height;
    divide(map, nX, nY, w, h, chooseOrientation(w, h), renderer);

    nX = wallIsHorizontal ? x : (wX + 1);
    nY = wallIsHorizontal ? (wY + 1) : y;
    w = wallIsHorizontal ? width : (x + width - wX -1);
    h = wallIsHorizontal ? (y + height - wY-1 ) : height;
    divide(map, nX, nY, w, h, chooseOrientation(w, h),renderer);
}

示例:

2 step from the start of algorithm

示例 - 20x20 平铺地图上的“完成的迷宫”:

Finished algorithm

注意

您看到的屏幕截图来自程序的单独运行,因此它们有所不同。我希望你能明白这一点。

【问题讨论】:

  • 问题是什么?如何随机生成迷宫以便有可能的解决方案?
  • 是的,这就是问题所在。如何避免这种方式可能产生的对隔壁墙的通道的堵塞?
  • edit澄清您的问题
  • “我面临的一个问题是我的“通道”有时会被随机生成的下一堵墙挡住 - 这会导致无法解决的迷宫。”您能否展示一个由您的代码生成的无效迷宫的示例?实际上,您能否展示一个通过添加墙壁的算法构建的一系列迷宫的示例?
  • 已编辑。添加了一般问题和完成的算法执行的屏幕截图。

标签: c++ algorithm recursion matrix maze


【解决方案1】:

与您获得灵感的链接相比,您的墙占据了一个单元格的空间。避免您的问题的最简单方法是您的墙壁只能放置在两列/行中的一列/行上。

这就是“薄壁”迷宫会产生的结果

这是厚壁的等价物(你正在使用的)

如您所见,它们的网格大小不同,第一个是 3x3,最后一个是 5x5,没有边框(编辑因为您的没有边框)。

  • 您需要有一个奇数边的网格。如果它基于薄迷宫,则将边 2 * n - 1 变大,其中 n 为薄迷宫边的长度*
  • 仅在奇数行和列上放置墙(从索引 0 开始)
  • 在偶数行和列的墙上放置开口
To resume, you can place walls

o o o o o
o o o o o <- here
o o o o o
o o o o o <- here
o o o o o
  ^   ^
here  here

(*) 2n - 1 没有边界,否则使用 2n + 1


如何在您的代码中实现这一点:

    const int truewidth = (width-1)/2;
    const int trueheight = (height-1)/2;
    //Where the wall is
    int wX = x  + (wallIsHorizontal ? 0 : 2 * (rand() % (truewidth)) + 1);
    int wY = y + (wallIsHorizontal ? 2 * (rand() % (trueheight)) + 1: 0);
    //Where the passage is
    int pX = wX + (wallIsHorizontal ? 2 * (rand() % (truewidth)) : 0);
    int pY = wY + (wallIsHorizontal ? 0 : 2 * (rand() % (trueheight)));

/!\ 尚未测试

【讨论】:

  • 抱歉,我已经第 10 次阅读您的答案,我无法理解您提出的解决方案。 “你的墙只能放在两列/一排”是什么意思?谢谢
  • @l000p 我意识到我太努力了一些无用的东西,我只会为您提供修改后的函数版本,以解决您的问题。请注意,您的迷宫必须有奇数边,所以 20x20 不会。你可以测试一下就知道为什么了^^
  • 感谢您的支持。现在算法正在运行 - Maze Generated
  • @l000p 很高兴知道它有效!我不太确定,因为我只是快速查看了您的代码。我希望它没有让您感到困惑,并且您必须了解它如何解决您的问题
  • @l000p 也是不错的迷宫解决算法:)
猜你喜欢
  • 1970-01-01
  • 2014-06-25
  • 1970-01-01
  • 1970-01-01
  • 2020-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多