深读优先寻路算法原文:https://blog.csdn.net/qq_42476927/article/details/81868068
本文是基于之前的深度优先寻路算法改进而来,参考了许多广度遍历的代码结合自己代码改进成为现在的样子,基本上优化了之前的所有缺点,相较于之前寻路的速度快了N倍,当然深度优先本来就不是用于遍历出最短路径,广度优先的寻路算法才是真正适合用于寻找最短路径,刚开始思路没那么清晰所以才有了深度遍历最短路径。
void game() //走迷宫游戏,包含时间统计,以及对老鼠的移动控制,游戏模块
void create_plat() //新建地图,并存入文件的模块 地图文件是plat.txt
void show_plat() //地图展示模块
void alter_plat() //修改地图模块
void read_plat() //读取文件里的地图模块
//广度优先寻路算法
int NextPos(int *i,int *j,int count) //i行 j列,count为遍历上下左右的条件
void En_stack(int i,int j,int k) //将通路的i,j计入栈中
void De_stack(int *i,int *j,int *k) //读取栈中的元素
void Path_BFS() //广度算法遍历,寻找最短路径核心
void path_best() //标记最短路径模块并显示
void path_find(int p,int q) //寻找通关路径的模块,深度算法
新增元素:
typedef struct
{
int x;
int y;
}Axis;
//用于存放路径结构体
typedef struct
{
int parent;
int child;
Axis childpos;
}Stack;
Stack S[M*N]; //用于储存的栈
int top=0,bottom=0; //标记栈的两个定位元素
经过n次调试,改代码,才调试出来,去掉了原先深度寻找最短路径的部分代码,新增的visit数组是用来广度遍历标记的,然后配合S栈找出返回的路径,返回路径是由parent和child标记定位栈中元素返回的,并不是一个一个出栈,然后标记出路径再输出,当然这个程序还是有一点小瑕疵,就是一旦使用20x20空地图,再用寻找全部路径这个功能,就会出现bug,因为寻找全部路径使用的是深度遍历,空地图如果大了,就需要更多的运算,花费很多时间,但是9x9地图是没有问题的,有兴趣的话可以自己改着试一下。
以下是源代码:
大家可以改一下试试,编程软件vc6.0
#include
#include
#include
#include
#define M 9
#define N 9
int maze[M][N] = {2,2,2,2,2,2,2,2,2,
2,0,0,0,2,0,0,0,2,
2,0,2,0,0,0,2,2,2,
2,0,0,2,2,0,0,0,2,
2,0,2,0,1,2,2,0,2,
2,0,2,0,2,0,0,0,2,
2,0,2,0,2,2,0,2,2,
2,0,0,0,0,2,0,3,2,
2,2,2,2,2,2,2,2,2}; //初始默认地图
int visit[M][N]={ 2,2,2,2,2,2,2,2,2,
2,0,0,0,2,0,0,0,2,
2,0,2,0,0,0,2,2,2,
2,0,0,2,2,0,0,0,2,
2,0,2,0,1,2,2,0,2,
2,0,2,0,2,0,0,0,2,
2,0,2,0,2,2,0,2,2,
2,0,0,0,0,2,0,3,2,
2,2,2,2,2,2,2,2,2}; //用于广度遍历的数组
typedef struct
{
int x;
int y;
}Axis;
//用于存放路径结构体
typedef struct
{
int parent;
int child;
Axis childpos;
}Stack;
Stack S[M*N]; //用于储存的栈
//全局定义的变量
int m=4,n=4; //老鼠的初始位置
int p=4,q=4; //老鼠位置二次定位
int x=7,y=7; //粮仓初始位置
int g; //g:统计有效路径,防止路径过多,造成循环过度;
int top=0,bottom=0; //标记栈的两个定位元素
void game() //走迷宫游戏,包含时间统计,以及对老鼠的移动控制,游戏模块
{
int i,j,v,t=0; //t为初始时间
char str;
time_t start,end;
start=time(NULL);
maze[x][y]=3;
m=p;
n=q;
maze[m][n]=1; //重新定位老鼠位置
printf("显示迷宫:\n"); //地图初始化
for (i = 0 ; i < M ; i++)
{
for (j = 0 ; j < N ; j++)
{
if(maze[i][j] == 2){
printf("▉");
}
else if(maze[i][j]==1)
{
printf("鼠");
}
else if(maze[i][j]==3)
{
printf("粮");
}
else
{
printf(" ");
}
}
printf("\n");
}
printf("(按w↑s↓a← d→移动)\n请在15秒内通关☆(-o⌒)\n"); //初始化地图
while(1)
{
printf("时间:%d\r",t);
if(kbhit()) //输入控制
{
str=getch();
if(str=='w') //上
{
if(maze[m-1][n]==0)
{
maze[m-1][n]=1;
maze[m][n]=0;
m=m-1;
}
else if(maze[m-1][n]==3)
{
maze[m][n]=0;
v=1;
}
}
else if(str=='s') //下
{
if(maze[m+1][n]==0)
{
maze[m+1][n]=1;
maze[m][n]=0;
m=m+1;
}
else if(maze[m+1][n]==3)
{
maze[m][n]=0;
v=1;
}
}
else if(str=='a') //左
{
if(maze[m][n-1]==0)
{
maze[m][n-1]=1;
maze[m][n]=0;
n=n-1;
}
else if(maze[m][n-1]==3)
{
maze[m][n]=0;
v=1;
}
}
else if(str=='d') //右
{
if(maze[m][n+1]==0)
{
maze[m][n+1]=1;
maze[m][n]=0;
n=n+1;
}
else if(maze[m][n+1]==3)
{
maze[m][n]=0;
v=1;
}
}
else;
system("cls");
printf("显示迷宫:\n"); //显示游戏地图
for (i = 0 ; i < M ; i++)
{
for (j = 0 ; j < N ; j++)
{
if(maze[i][j] == 2)
{
printf("▉");
}
else if(maze[i][j]==1)
{
printf("鼠");
}
else if(maze[i][j]==3)
{
printf("粮");
}
else
{
printf(" ");
}
}
printf("\n");
}
printf("(按w↑s↓a← d→移动)\n请在15秒内通关☆(-o⌒) \n");
}
else;
if(v==1) //判断是否通关
{
printf("\n恭喜通关!( ̄▽ ̄)~*\n");
system("pause");
break;
}
if(t>15) //规定时间到后结束游戏
{
printf("\n未在规定时间内通关,游戏失败。(╯︵╰)\n");
maze[m][n]=0; //清除最后所在位置
system("pause");
break;
}
end=time(NULL);
t=difftime(end,start);
}
}
void create_plat() //新建地图,并存入文件的模块
{
int i,j,s;
cc: printf("请输入0和2,0代表通路,2代表墙体(数字用空格隔开),输入规格是%dx%d,有边缘墙体无需再次输入( ̄▽ ̄)/\n",M-2,M-2);
for(i=1;i<=M-2;i++)
{
printf("第%d行:",i);
for(j=1;j<=N-2;j++)
{
scanf("%d",&s);
if(s==0||s==2)
maze[i][j]=s;
else
{
system("cls");
printf("输入错误请重新输入╮(╯﹏╰)╭\n");
goto cc;
}
}
}
aa: printf("请设置老鼠的初始位置x,y即行列(1~%d,1~%d):\n",M-2,N-2);
p=q=NULL;
m=n=NULL;
//清除来自键盘的30多个缓存字符,防止死循环bug
for(i=0;i<30;i++)
fflush(stdin);
scanf("%d,%d",&p,&q);
if(p<=(M-2)&&q<=(M-2)&&p>0&&q>0)
maze[p][q]=1;
else
{
system("cls");
printf("输入错误,请重新输入,在%dx%d的范围内。(;′⌒`)\n",M-2,N-2);
goto aa;
}
bb: printf("请设置粮仓的位置x,y:\n");
//清除来自键盘的30多个缓存字符,防止死循环bug
for(i=0;i<30;i++)
fflush(stdin);
scanf("%d,%d",&x,&y);
if(x<=(M-2)&&y<=(N-2)&&x>0&&y>0&&(x!=p||y!=q))
maze[x][y]=3;
else
{
system("cls");
printf("输入错误,请重新输入,在%dx%d的范围内。(;′⌒`)\n",M-2,N-2);
goto bb;
}
//文件保存地图
FILE *fp;
fp=fopen("plat.txt","w");
for(i=0;i=0)
{
switch(select)
{
case 1: printf("围墙内为修改范围,范围是%dx%d\n",M-2,N-2);
printf("请输入坐标x,y(行,列)修改地图:\n");
//清除来自键盘的30多个缓存字符,防止死循环bug
for(i=0;i<30;i++)
fflush(stdin);
scanf("%d,%d",&a,&b);
if(a<=(M-2)&&b<=(N-2)&&a>0&&b>0&&maze[a][b]!=1&&maze[a][b]!=3)
maze[a][b]=2;
else
{
printf("输入错误请重新输入,不能在围墙、粮仓和老鼠的位置修改哦(*/ω\*)\n");
system("pause");
}
break;
case 2: printf("围墙内为修改范围,范围是%dx%d\n",M-2,N-2);
printf("请输入坐标x,y(行,列)修改地图:\n");
//清除来自键盘的30多个缓存字符,防止死循环bug
for(i=0;i<30;i++)
fflush(stdin);
scanf("%d,%d",&a,&b);
if(a<=(M-2)&&b<=(N-2)&&a>0&&b>0&&maze[a][b]!=1&&maze[a][b]!=3)
maze[a][b]=0;
else
{
printf("输入错误请重新输入,不能在围墙、粮仓和老鼠的位置修改哦(*/ω\*)\n");
system("pause");
}
break;
case 3:
{ //文件形式保存修改后地图
fp=fopen("plat.txt","w");
for(i=0;i=0 && select<8) //键盘输入检错
{
switch(select)
{
case 0: exit(0);
case 1: system("cls"); //清除菜单
game(); //开始游戏
break;
case 2: create_plat(); //新建地图
break;
case 3: show_plat(); //显示地图
break;
case 4: alter_plat(); //修改地图
break;
case 5: read_plat(); //在文件里读取地图
break;
case 6: Path_BFS(); //广度优先寻路算法核心
path_best(); //显示及恢复地图
system("pause");
break;
case 7: g=0;
path_find(p,q); //寻找所有通关路径
printf("已显示所有路径!(~ ̄▽ ̄)~ \n");
system("pause");
break;
default:
break;
}
}
else
{
printf("请按规定输入哦 ̄ω ̄=\n");
system("pause");
}
}
}
/*2018.8.22 14:33 作者:zero丶0 广度寻路算法的最后一个版本,n次调试,应该沒什么问题了*/