- 2016-5-12 C 迷宫寻路算法
2016年5月12日 更新
本来一直想写一个游戏,但是自己的功力又不够,正好在《数据结构》一书中看到了栈应用之迷宫寻路算法,所以打算写一个自动生成随机迷宫并可以自动解迷宫的程序。我本来打算用C写的,但是写起来却不太顺手,一方面是我对C的语法不太了解,另一方面是C在好多地方反而不够灵活。比如,当函数需要有多个返回值或者需要使用结构体指针作为函数参数的时候。所以,我先用C写了一个大概,后续我会用C++重写,并完善这个程序。
算法思路:手动生成一个迷宫保存在二维数组里面。规定,0代表墙。1-6代表通道,并分别表示通道上每个格子的不同状态。具体如下
0-墙 1-下一次将探寻这个格子上面的格子 2-下一次探寻这个格子右边的格子 3-下一次探寻这个格子下边的格子 4-下一次探寻这个格子左边的格子 5-这个格子所有方向都走过了 6-这个格子之前走过且无法走通
在定义了迷宫中每个格子的状态后,我们就可以通过遍历整个迷宫,一步一步找到迷宫出口。具体做法是从迷宫起点开始,根据当前格子的状态信息,找到下一个格子的位置,然后前往下一个格子,并且更新当前格子状态信息和把当前格子坐标压栈,作为路径信息保存起来。若下一个格子是墙,则从栈顶弹出一个坐标,这个坐标就是来时的路径坐标。接着根据其状态信息,重复之前的步骤。当下一个格子的坐标等于出口坐标时,则结束。
我们还需要注意,需要记录路径的走向信息,比如,我们从左向右走到底了,那么最后一个靠墙的格子就不能再继续向左走回去,这样就会形成一个死循环。遇到这种情况时,我们应该记录来时的方向,在探寻新的方向的时候就必须避开来时的方向。当4个方向探索完毕都找不到出路了,那么就直接从栈中弹出上一个格子的坐标,继续找出路。
详细代码与注释如下:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define ROW 10
#define COL 10
int stus[ROW][COL]= { {0,0,0,0,0,0,0,0,0,0},
{0,1,0,0,0,1,1,1,1,0},
{0,1,0,1,0,1,0,0,0,0},
{0,1,1,1,1,1,1,1,1,0},
{0,1,0,1,0,1,0,1,0,0},
{0,1,0,1,0,1,0,1,1,0},
{0,1,0,1,0,0,0,0,1,0},
{0,1,0,1,1,1,0,1,1,0},
{0,1,0,1,0,0,1,1,0,0},
{0,0,0,0,0,0,0,1,0,0},
}; //0墙壁 1 up 2 right 3 down 4 left 5 back 6回退路径,显示用
int comefrom[ROW][COL];
int b_x=1,b_y=1; //起点
int e_x=9,e_y=7; //终点
int stack_x[ROW],stack_y[ROW]; //stack
int cur=-1; //top 指向栈顶元素
void push_(int x,int y){
cur++;
stack_x[cur] = x;
stack_y[cur] = y;
}//push
int pop_(){
return cur--;
}//pop
void print_(int stus[ROW][COL]){
int x,y;
system("cls");
for(x = 0;x<ROW;x++){
for(y = 0;y<COL;y++){
switch(stus[x][y]){
case 0: printf("# ");break; //墙用#表示
case 1: printf(" ");break; //未到过的路
case 6: printf(" ");break; //需要回退的路
default: printf("@ "); //路用空格表示
}//switch
}//y
printf("\n");
}//x
}//print
void findway_(int stus[ROW][COL],int b_x,int b_y,int e_x,int e_y){
int x=b_x,y=b_y,tem_cur;
while(x!=e_x||y!=e_y){
switch(stus[x][y]){
case 0: tem_cur=pop_();x=stack_x[tem_cur];y=stack_y[tem_cur];break;
case 1: if(comefrom[x][y]!= 1){stus[x][y]=2;push_(x,y); x-=1;comefrom[x][y]= 3;break;}
case 2: if(comefrom[x][y]!= 2){stus[x][y]=3;push_(x,y); y+=1;comefrom[x][y]= 4;break;}
case 3: if(comefrom[x][y]!= 3){stus[x][y]=4;push_(x,y); x+=1;comefrom[x][y]= 1;break;}
case 4: if(comefrom[x][y]!= 4){stus[x][y]=5;push_(x,y); y-=1;comefrom[x][y]= 2;break;}
case 5: stus[x][y]=6;tem_cur=pop_();x=stack_x[tem_cur];y=stack_y[tem_cur];break;
}//switch
print_(stus);
Sleep(100);
}//while
}//findway_
int main()
{
print_(stus);
findway_(stus,b_x,b_y,e_x,e_y);
return 0;
}
效果图
迷宫#代表墙
寻路算法运行完毕后 #代表墙 @代表走过的路径