简体   繁体   English

带有DFS的c中的迷宫生成算法

[英]maze generation algorithm in c with DFS

recently i read this topic about generating mazes in c .最近我读了这个关于在 c 中生成迷宫的主题。 see here https://www.algosome.com/articles/maze-generation-depth-first.html and i want to write it in c .在这里看到https://www.algosome.com/articles/maze-generation-depth-first.html我想用 c 写它。 here is my code and it's not working right .这是我的代码,它不能正常工作。

#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 ;
}

i invert my table to graph , and i want to show me the coordinates of my walls .我将我的表格反转为图形,并且我想显示我墙壁的坐标。 what's the problem ?有什么问题 ?

You have several errors – programming errors and logic errors – in your code:您的代码中有几个错误——编程错误和逻辑错误:

  • When you distiguish between the directions the s=1 and so on should be s == 1 .当您区分方向时, s=1等应该是s == 1 You want a comparison, not an assignment.你想要一个比较,而不是一个任务。 (Your code is legal C, so there is no error.) (您的代码是合法的 C,所以没有错误。)
  • You call srand at the beginning of dfs , which you call recursively.您在dfs的开头调用srand ,您递归调用它。 This will make your single (commented) rand call always create the same random number.这将使您的单个(注释) rand调用始终创建相同的随机数。 You should seed the pseudo random number generator only once at the beginning of main .您应该只在main的开头为伪随机数生成器播种一次。
  • You can store the paths the way you do, but it is wasteful.您可以按照自己的方式存储路径,但这很浪费。 There are only four possible paths from each cell, so you don't need an array that allows to create a path between (0,0) and (3,4), for example.例如,每个单元格只有四个可能的路径,因此您不需要允许在 (0,0) 和 (3,4) 之间创建路径的数组。
  • Your code would benefit from using constants or enumerated values instead of the hard-coded 5's and 6's.您的代码将受益于使用常量或枚举值而不是硬编码的 5 和 6。 This will allow you to change the dimensions later easily.这将允许您稍后轻松更改尺寸。

But your principal error is in how you implement the algorithm.但是您的主要错误在于您如何实现算法。 You pick one of the for directions at random, then test whether that direction leads to a valid unvisited cell.您随机选择一个 for 方向,然后测试该方向是否通向有效的未访问单元格。 If so, you recurse.如果是这样,你递归。 If not, you stop.如果没有,你就停下来。 This will create a single unbranched path through the cells.这将创建一条穿过细胞的单一无分支路径。 Note that if you start in a corner cell, you have already a 50% chance of stopping the recursion short.请注意,如果您从角落单元开始,您已经有 50% 的机会停止递归。

But you want something else: You want a maze with many branches that leads to every cell in the maze.但是你想要别的东西:你想要一个有许多分支的迷宫,这些分支通向迷宫中的每个细胞。 Therefore, when the first recursion returns, you must try to branch to other cells.因此,当第一次递归返回时,您必须尝试分支到其他单元格。 The algorithm goes like this:算法是这样的:

  • Make a list of all possible exits.列出所有可能的出口。
  • If there are possible exits:如果有可能的出口:
    • Pick one exit, create a path to that exit and recurse.选择一个出口,创建一条通往该出口的路径并递归。
    • Update the list of possible exits.更新可能的退出列表。

Note that you cannot re-use the old list of exits, because the recursion may have rendered some possible exits invalid by visiting the destination cells.请注意,您不能重新使用旧的退出列表,因为递归可能通过访问目标单元格使某些可能的退出无效。

Below is code that creates a maze with the described algorithm.下面是使用所描述的算法创建迷宫的代码。 I've used two distinct arrays to describe horizontal and vertical paths:我使用了两个不同的数组来描述水平和垂直路径:

#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;
}

You can test it here .你可以在这里测试它。 If you replace the while in dsf with a simple if , you get more or less what you implemented.如果你用一个简单的if替换dsfwhile ,你会或多或少地得到你实现的东西。 Note that this creates only a single, usually short path.请注意,这只会创建一条通常较短的路径。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM