【问题标题】:maze generation algorithm in c with DFS带有DFS的c中的迷宫生成算法
【发布时间】:2018-12-31 18:10:54
【问题描述】:

最近我读到了这个关于在 c 中生成迷宫的主题。看这里https://www.algosome.com/articles/maze-generation-depth-first.html 我想用 c 写它。这是我的代码,但它不能正常工作。

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int check[5][5];
int v[5][5];
int border(int x , int y ){
    if(x> -1 && x< 6 && y > -1 && y<6)
        return 1;
    else
        return 0 ;
}
int wall[6][6][6][6];
void dfs ( int x , int y){
    srand(time(NULL));
    int s = 1/*rand() % 4 ;*/ ;
    if(s=1 ){
        if(border(x ,y-1)&& check[x][y-1]==0){
            check[x][y]=1;
            wall[x][y][x+1][y]=1;
            dfs(x , y-1);
        }
        else
            return ;
    }
    else if(s=2){
        if(border(x+1 ,y)&&check[x+1][y]==0){
            check[x][y]=1;
            wall[x+1][y][x+1][y+1]=1;
            dfs(x+1 , y);
        }
        else return ;
    }
    else if(s=3){
        if(border(x ,y+1)&&check[x][y+1]==0){
            check[x][y]=1;
            wall[x][y+1][x+1][y+1]=1;
            dfs(x , y+1);
        }
        else return ;
    }
    else if(s=0){
        if(border(x-1 ,y)&&check[x-1][y]==0){
            check[x][y]=1;
            wall[x][y][x][y+1]=1;
            dfs(x-1 , y);
        }
        else return ;
    }
return ;
}

int main(){
dfs( 4, 4);
for(int i =0 ; i < 6 ; i++)
    for (int j =0 ; j < 6 ; j++)
        for ( int h =0 ; h <6 ; h++)
            for (int k =0 ; k < 6 ; k ++)
                printf("%d \n" , wall[i][j][h][k]);

return 0 ;
}

我将我的表格反转为图形,我想向我展示我的墙壁的坐标。 有什么问题?

【问题讨论】:

    标签: c maze microsoft-distributed-file-system


    【解决方案1】:

    您的代码中有几个错误——编程错误和逻辑错误:

    • 当您区分方向时,s=1 等应为s == 1。你想要一个比较,而不是一个任务。 (你的代码是合法的 C,所以没有错误。)
    • dfs 的开头调用srand,递归调用。这将使您的单个(已注释)rand 调用始终创建相同的随机数。您应该只在 main 的开头为伪随机数生成器播种一次。
    • 您可以按照自己的方式存储路径,但这很浪费。每个单元格只有四个可能的路径,因此您不需要一个允许在 (0,0) 和 (3,4) 之间创建路径的数组。
    • 您的代码将受益于使用常量或枚举值而不是硬编码的 5 和 6。这将允许您稍后轻松更改尺寸。

    但您的主要错误在于您如何实现算法。您随机选择其中一个方向,然后测试该方向是否导致有效的未访问单元格。如果是这样,你递归。如果没有,你就停下来。这将创建一条穿过细胞的无分支路径。请注意,如果您从角落单元格开始,您已经有 50% 的机会停止递归。

    但是你想要别的东西:你想要一个有许多分支的迷宫,通向迷宫中的每个单元。因此,当第一次递归返回时,您必须尝试分支到其他单元格。算法是这样的:

    • 列出所有可能的出口。
    • 如果有可能的退出:
      • 选择一个出口,创建一条通往该出口的路径并递归。
      • 更新可能的退出列表。

    请注意,您不能重复使用旧的出口列表,因为递归可能会通过访问目标单元格而使某些可能的出口无效。

    以下是使用所述算法创建迷宫的代码。我使用了两个不同的数组来描述水平和垂直路径:

    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>
    
    enum {
        W = 36,         // width of maze
        H = 25          // height of maze
    };
    
    enum {
        North,
        East,
        South,
        West,
        NDir
    };
    
    char visited[H][W];
    char horz[H][W - 1];        // horizontal E-W paths in the maze
    char vert[H - 1][W];        // veritcal N-S paths in the maze
    
    /*
     *      Fill dir with directions to unvisited cells, return count
     */
    int adjacent(int dir[], int x, int y)
    {
        int ndir = 0;
    
        if (y > 0     && visited[y - 1][x] == 0) dir[ndir++] = North;
        if (x < W - 1 && visited[y][x + 1] == 0) dir[ndir++] = East;
        if (y < H - 1 && visited[y + 1][x] == 0) dir[ndir++] = South;
        if (x > 0     && visited[y][x - 1] == 0) dir[ndir++] = West;
    
        return ndir;
    }
    
    /*
     *      Traverse cells depth first and create paths as you go
     */
    void dfs(int x, int y)
    {
        int dir[NDir];
        int ndir;
    
        visited[y][x] = 1;
    
        ndir = adjacent(dir, x, y);
    
        while (ndir) {
            int pick = rand() % ndir;
    
            switch (dir[pick]) {
            case North: vert[y - 1][x] = 1; dfs(x, y - 1); break;
            case East:  horz[y][x] = 1;     dfs(x + 1, y); break;
            case South: vert[y][x] = 1;     dfs(x, y + 1); break;
            case West:  horz[y][x - 1] = 1; dfs(x - 1, y); break;
            }
    
            ndir = adjacent(dir, x, y);
        }
    }
    
    /*
     *      Print a map of the maze
     */
    void map(void)
    {
        int i, j;
    
        for (i = 0; i < W; i++) {
            putchar('_');
            putchar('_');
        }
    
        putchar('\n');
    
        for (j = 0; j < H; j++) {
            putchar('|');
    
            for (i = 0; i < W; i++) {
                putchar(j < H - 1 && vert[j][i] ? ' ' : '_');
                putchar(i < W - 1 && horz[j][i] ? '_' : '|');
            }
    
            putchar('\n');
        }
    }
    
    int main()
    {
        srand(time(NULL));
    
        dfs(0, 0);
        map();
    
        return 0;
    }
    

    您可以测试它here。如果您将dsf 中的while 替换为简单的if,您或多或少会得到您实现的内容。请注意,这只会创建一个通常较短的路径。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多