微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么这个迷宫生成算法会产生单向道路?

如何解决为什么这个迷宫生成算法会产生单向道路?

我正在尝试编写一个算法来创建迷宫。算法 (DFS) 如下所示:

  1. 随机单元格开始。
  2. 将当前单元标记为已访问,获取邻居列表。对于每个邻居,从随机选择的邻居开始:
    如果没有访问过该邻居,请移除此邻居之间的墙 单元格和那个邻居,然后以那个邻居作为 当前单元格。

但它会产生这样的迷宫:

Maze example

而且我不知道为什么算法会创建完整的车道而不是创建死胡同,使其看起来更像迷宫而不是单向道路。

我怀疑错误随机选择、错误的回溯或算法将每个单元格标记为在递归步骤中访问过,导致没有死胡同,因为它无法返回到单元格,但我无法缩小问题的范围。 小迷宫似乎也会产生同样的问题。

代码

std::vector<std::pair<int,int>> getAdjacentCells(Cell arr[N][M],int i,int j)
{
    std::vector<std::pair<int,int>> neighbor_vec;
    if(i-2 >= 0)
        neighbor_vec.push_back(std::pair<int,int>(i-2,j));
    if(i+2 < N)
        neighbor_vec.push_back(std::pair<int,int>(i+2,j));
    if(j-2 >= 0)
        neighbor_vec.push_back(std::pair<int,int>(i,j-2));
    if(j+2 < M)
        neighbor_vec.push_back(std::pair<int,j+2));

    return neighbor_vec;
}


void genMaze(Cell arr[N][M],int j)
{
    // mark the current cell as visited
    Cell &curCell = arr[i][j];
    curCell.visited = true;
    curCell.isWall = false;

    // get a list of its neighbors
    std::vector<std::pair<int,int>> neighbors = getAdjacentCells(arr,i,j);

    // shuffle neighbor vector
    std::random_shuffle( neighbors.begin(),neighbors.end() );

    for(std::pair<int,int> coord : neighbors)
    {
        int x,y;
        x = coord.first;
        y = coord.second;

        Cell &curNeighbor = arr[x][y];

        if(!curNeighbor.visited)   // remove wall inbetween given cell and neighbor
        {

            if(!(i-x))   // on the same column
            {

                if(j-y < 0)  // right hand neighbor
                {
                    arr[i][j+1].isWall = false;
                    return genMaze(arr,x,y);
                }
                else    // left hand neighbor
                {
                    arr[i][j-1].isWall = false;
                    return genMaze(arr,y);
                }

            }
            else     // not in the same column
            {

                if(i-x < 0)  // bottom neighbor
                {
                    arr[i+1][j].isWall = false;
                    return genMaze(arr,y);
                }
                else    // top neighbor
                {
                    arr[i-1][j].isWall = false;
                    return genMaze(arr,y);
                }

            }
        }

    }

    arr[i][j].isEnd = true; // mark ending
}

元类只包含标志。 它似乎与 post 算法相同(尽管问题不同):maze problem and Recursive backtracker algorithm

如有任何想法或解释,我将不胜感激。

解决方法

该算法生成单向路径,因为包括其他路径的进一步生成。 创建第一个后需要进一步产生死胡同。在我实现的算法中,我没有考虑其他路径的进一步生成;

因此,当到达死胡同时,它需要通过路径回溯,直到到达一个有未访问邻居的单元格。然后它以新路径继续生成,直到到达死胡同。当访问完所有单元格的所有有效邻居时,这将停止。

在标记结束前添加的代码:

for(int a = 0; a < N; a++)
{
    for(int b = 0; b < M; b++)
    {
        if(arr[a][b].visited) // for every visited cell in the maze,get their neighbors
        {
            std::vector<std::pair<int,int>> neighborOfCurCell = getAdjacentCells(arr,a,b);

            int visitedNeighborCount = 0;

            // for every neighbor,count the unvisited cells
            for(auto neighbor : neighborOfCurCell)
            {
                Cell &currentNeighbor = arr[neighbor.first][neighbor.second];

                if(currentNeighbor.visited)
                    visitedNeighborCount++;
            }

            // if there is an unvisited neighbor after completing a path,backtrack with current cell
            if(visitedNeighborCount < neighborOfCurCell.size())
                return genMaze( arr,b );
        }
    }
}

示例:

Maze example fixed

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。