一段迷宫生成算法,有一处不理解,求讲解
- C/C++ code
#include <stdio.h>#include <stdlib.h>#include <time.h>#define MAZE_MAX 50char map[MAZE_MAX+2][MAZE_MAX+2];int search(int x,int y){ static int d[4][2]={0,1,1,0,0,-1,-1,0}; int zx=x*2,zy=y*2,next,turn,i; map[zx][zy]=0; turn=rand()%2? 1:3; for(i=0,next=rand()%4;i<4;i++,next=(next+turn)%4) if(map[zx+2*d[next][0]][zy+2*d[next][1]]==1) //这里是zx + 2*d[next][0]... map[zx+d[next][0]][zy+d[next][1]]=0, // 这里是zx + d[next][0]... search(x+d[next][0],y+d[next][1]); // 这里是x + d[next][0] // 以上不太明白,那个乘以2,不乘以2,都是干嘛的? return 0;}void Make_Maze(int x,int y){ int z1,z2; for(z1=0,z2=2*y+2;z1<=2*x+2;z1++) // 数组最外围置0,表示无墙 map[z1][0]=0,map[z1][z2]=0; for(z1=0,z2=2*x+2;z1<=2*y+2;z1++) map[0][z1]=0,map[z2][z1]=0; map[1][2]=0;map[2*x+1][2*y]=0; //入口和出口 srand((unsigned)time(NULL)); search(rand()%x+1,rand()%y+1);}int main(void{ int x=2,y=2,z1,z2; //x和y的值指定了这个要生成的迷宫的大小 for(int i=0; i<=x*2+2; ++i) for(int j=0; j<=y*2+2; ++j) map[i][j] = 1; Make_Maze(x, y); for(z2=1; z2<=y*2+1; z2++) { for(z1=1;z1<=x*2+1;z1++) fputs(map[z2][z1]==0?" ":"",stdout); putchar(10); } return 0;}
在search函数中有这么一段代码
for(i=0,next=rand()%4;i<4;i++,next=(next+turn)%4)
if(map[zx+2*d[next][0]][zy+2*d[next][1]]==1) //这里是zx + 2*d[next][0]...
map[zx+d[next][0]][zy+d[next][1]]=0, // 这里是zx + d[next][0]...
search(x+d[next][0],y+d[next][1]); // 这里是x + d[next][0]
// 以上不太明白,那个乘以2,不乘以2,都是干嘛的?
[解决办法]
额,我问了一下,种子函数放在主函数里,别放在递归调用里,这样就完美了.
- C/C++ code
#include <cstdio>#include <cstdlib>#include <ctime>static int direct[4][2]={ {0,1},{1,0},{0,-1},{-1,0}};const int SIZE = 100;bool maze[SIZE][SIZE];int h,w,sx,sy,ex,ey;bool checkAround(int fX,int fY,int toX,int toY){ for(int i=0;i<4;++i) { int x=toX+direct[i][0]; int y=toY+direct[i][1]; if(maze[x][y]==false && x!=fX && y!=fY) { return false; } } return true;}bool dfs(int x,int y){ maze[x][y]=false; if(x==ex && y==ey) { return true; } bool flag[4]={0,0,0,0}; for(int i=rand()%4,cnt=0;cnt<4;i=rand()%4) { if(!flag[i]) { flag[i]=true; ++cnt; int toX=x+direct[i][0]; int toY=y+direct[i][1]; if(0<toX && toX<h+1 && 0<toY && toY<w+1 && maze[toX][toY]==true && checkAround(x,y,toX,toY)==true) { if(dfs(toX,toY)) { return true; } } } } maze[x][y]=true; return false;}int main(){ scanf("%d%d%d%d%d%d",&h,&w,&sx,&sy,&ex,&ey); //输入高,宽 /* 深搜起点到终点 */ while(getchar()) { srand( (unsigned int ) time(0) ); for(int i=0;i<=h+1;++i) { for(int j=0;j<=w+1;++j) { maze[i][j]=true; } } dfs(sx,sy); printf("\n"); for(int i=0;i<=h+1;++i) { for(int j=0;j<=w+1;++j) { printf("%c",maze[i][j]==true ? '#':' '); } printf("\n"); } } return 0;}
------解决方案--------------------
你这个程序我运行了下,随机性不错,生成的迷宫也挺好看。
这个迷宫可以看成是路和墙都占一个格子,然后行数和列数均为偶数的视为路,其余格子视为墙。
调试了几步,我感觉这几个乘2应该是如下含义:
- C/C++ code
int search(int x,int y){ static int d[4][2]={0,1,1,0,0,-1,-1,0}; //这个不用说了吧,四个方向 int zx=x*2,zy=y*2,next,turn,i; map[zx][zy]=0; //这一步是在打通当前格子,默认该格子为路,因为该格子的行数和列数均为偶数。 turn=rand()%2? 1:3; for(i=0,next=rand()%4;i<4;i++,next=(next+turn)%4) //不得不说这个turn和next的随机很好,turn表示可以顺时针递归,也可以逆时针递归,而next则正好是随机了转圈的起点 if(map[zx+2*d[next][0]][zy+2*d[next][1]]==1) //判断下一个应该为路的格子是否还是1,如果是1的话应该打通才对 map[zx+d[next][0]][zy+d[next][1]]=0, //所以此时这句话的作用相当于打掉墙,打掉的是(zx,zy)和(zx+2*d[next][0],zy+2*d[next][1])之间的墙,为下一步打通路做准备。 search(x+d[next][0],y+d[next][1]); //然后,进入递归,即进入下一个路径 return 0;}