隨機迷宮生成演算法——遞迴分割演算法
阿新 • • 發佈:2019-01-05
迷宮生成三大演算法,Prime演算法、深度優先演算法、遞迴分割演算法,其中遞迴分割演算法最簡單,效率也最高,不過生成的迷宮也最簡單,看圖:
原理很簡單,首先假設迷宮全是路,在裡面畫四面牆,把迷宮分割成四個新區域,如下:
隨機選擇三面牆打通,這時原本隔開的四個區域又被打通了。以此類推,在四個新區域內繼續設牆分割區域,然後把牆打通,直到不能繼續分割才結束。
好嘞,看程式碼:
#include <iostream> static const int L=42; static const int ROUTE=0; static const int WALL=1; void CreateMaze(int **maze,int x1,int y1,int x2,int y2){ //判斷是否還能繼續分割 if(x2-x1<2||y2-y1<2){ return ; } //隨機取點 int x=x1+1+rand()%(x2-x1-1); int y=y1+1+rand()%(y2-y1-1); //畫牆 for(int i=x1;i<=x2;i++) maze[i][y]=WALL; for(int i=y1;i<=y2;i++) maze[x][i]=WALL; //遞迴分割,繼續劃分區域 CreateMaze(maze,x1,y1,x-1,y-1); CreateMaze(maze, x+1, y+1, x2, y2); CreateMaze(maze,x+1,y1,x2,y-1); CreateMaze(maze, x1, y+1, x-1, y2); //隨機取其中的三面牆 int r[4]={0}; r[rand()%4]=1; //在牆上隨機取點開孔 for(int i=0;i<4;i++){ if(r[i]==0){ int rx=x; int ry=y; switch (i) { case 0: //判斷該位置是否能確保打通相鄰兩塊區域,判斷依據,上下左右位置最多隻有兩面牆,下面一樣 do{ rx=x1+rand()%(x-x1); }while(maze[rx-1][ry]+maze[rx+1][ry]+maze[rx][ry-1]+maze[rx][ry+1]>2*WALL); break; case 1: do{ ry=y+1+rand()%(y2-y); }while(maze[rx-1][ry]+maze[rx+1][ry]+maze[rx][ry-1]+maze[rx][ry+1]>2*WALL); break; case 2: do{ rx=x+1+rand()%(x2-x); }while(maze[rx-1][ry]+maze[rx+1][ry]+maze[rx][ry-1]+maze[rx][ry+1]>2*WALL); break; case 3: do{ ry=y1+rand()%(y-y1); }while(maze[rx-1][ry]+maze[rx+1][ry]+maze[rx][ry-1]+maze[rx][ry+1]>2*WALL); break; default: break; } maze[rx][ry]=ROUTE; } } } int main(int argc, const char * argv[]) { srand((unsigned)time(NULL)); int **Maze=(int**)malloc(L*sizeof(int*)); for(int i=0;i<L;i++){ Maze[i]=(int*)calloc(L,sizeof(int)); } //外側一圈為牆 for(int i=0;i<L;i++){ Maze[0][i]=WALL; Maze[i][0]=WALL; Maze[L-1][i]=WALL; Maze[i][L-1]=WALL; } //生成迷宮 CreateMaze(Maze, 1,1, L-2, L-2); //設定出口 Maze[1][0]=ROUTE; Maze[L-2][L-1]=ROUTE; //畫迷宮 for(int i=0;i<L;i++){ for(int j=0;j<L;j++){ if(Maze[i][j]==WALL){ printf("XX"); }else{ printf(" "); } } printf("\n"); } for(int i=0;i<L;i++) free(Maze[i]); free(Maze); return 0; }