老鼠走迷宫-c语言(基于深度优先的寻路算法)

这个是学校的课设,刚开始有点头疼,但是感觉越做越有意思了,于是就有如下代码,可能相较于大佬还有差距,但是这是我目前所能做的最优的程序了吧!

话不多说,说一下代码的核心内容吧!

迷宫是通过二维数组构造的,二维组中的数字2代表墙体,0是通路,1是老鼠,3代表粮;

  • 以下是所有函数及全局变量:
  1. void game()  //走迷宫游戏,包含时间统计,以及对老鼠的移动控制,游戏模块;
  2. void create_plat()   //新建地图,并存入文件的模块;文件会保存在程序同目录下,地图文件名是plat.txt;
  3. void show_plat()   //地图展示模块;
  4. void alter_plat()    //修改地图模块;
  5. void read_plat()  //读取文件里的地图模块;在读取地图之前必须先含有该文件(plat.txt);
  6. void path_result(int p,int q)  //统计地图的所有可能出现的路径结果,并把次数赋给全局变量answer,并在path_result函数中引用变量,作为递归终止和显示最优解的条件;
  7. void path_best(int p,int q,int l)     //显示最优路径的模块;
  8. void path_find(int p,int q)  //寻找通关路径的模块;
  9. //全局定义的变量
    int m=4,n=4;            //老鼠的初始位置
    int p=4,q=4;           //老鼠位置二次定位
    int x=7,y=7;            //粮仓初始位置
    int g,answer;            //g:统计有效路径,防止路径过多,造成循环过度;answer:统计该地图的所有可能性;

这个代码有一定的缺陷,因为自动寻路算法是用深度遍历,所以必须要统计全部结果,而且随着地图越来越空,得到的结果越来越多,运算的复杂度提升将会浪费许多时间,我的是9x9的地图,内部7x7如果全为空,则需要计算不止5亿次,5亿次是得到的结果这么多,而且要引用变量,所以翻倍10亿次运算的结果;本人亲测花了6个小时的时间。所以该部分寻路算法,是很大的缺陷,目前已找到解决办法,深度优先是必须找到路最长的,而广度优先是找到最短的就可以停止,所以不久之后我会再更新一篇博客,用广度优先实现自动寻路,相较于深度优先,会更加快速的找出最短路径。

以下是源代码:

大家可以自己试试,编程软件vc6.0

#include <stdio.h>
#include <stdlib.h>
#include<conio.h>
#include<time.h>#define M 9
#define N 9int 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}
};struct best                  //用于记录最短路径的结构体
{int min;int b[M][N];
}Best;int m=4,n=4;            //老鼠的初始位置
int p=4,q=4;           //老鼠位置二次定位
int x=7,y=7;            //粮仓初始位置
int g,answer;           //g:统计有效路径,防止路径过多,造成循环过度;answer:统计该地图的所有可能性;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);//清除来自键盘的30多个缓存字符,防止死循环bugfor(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多个缓存字符,防止死循环bugfor(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<M;i++){for(j=0;j<N;j++)fprintf(fp,"%d\t",maze[i][j]);fprintf(fp,"%c",'\n');}fprintf(fp,"%d\t",p);fprintf(fp,"%d\t",q);fprintf(fp,"%d\t",x);fprintf(fp,"%d\t",y);fclose(fp);printf("地图新建完成,并保存成功!!!ヾ(^Д^*)/\n");system("pause");
}void show_plat()   //地图展示模块
{int i,j;system("cls");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("已显示地图☆(-o⌒)\n");system("pause");
}void alter_plat()    //修改地图模块
{int i,j,select,a,b;FILE *fp;while(1){system("cls");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("  =============----修改地图------===================\n");printf(" |请选择:                                          |\n");printf(" |              1.修改为墙体;                      |\n");printf(" |              2.修改为通路;                      |\n");printf(" |              3.保存修改地图;                    |\n");printf(" |              0.退出修改功能;                    |\n");printf("  ===========(请输入相应数字执行其功能)===========\n");fflush(stdin);  //清除键入的缓存scanf("%d",&select);if(select<4 && select>=0){switch(select){case 1:   printf("围墙内为修改范围,范围是%dx%d\n",M-2,N-2);printf("请输入坐标x,y(行,列)修改地图:\n");//清除来自键盘的30多个缓存字符,防止死循环bugfor(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多个缓存字符,防止死循环bugfor(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<M;i++){for(j=0;j<N;j++)fprintf(fp,"%d\t",maze[i][j]);fprintf(fp,"%c",'\n');}fprintf(fp,"%d\t",p);fprintf(fp,"%d\t",q);fprintf(fp,"%d\t",x);fprintf(fp,"%d\t",y);fclose(fp);printf("地图修改完成,并保存成功!!!(* ̄︶ ̄)\n");system("pause");}break;case 0: break;}}else{printf("请按规定输入哦 ̄ω ̄=\n");system("pause");}if(select==0)break;}
}void read_plat()  //读取文件里的地图模块
{int i,j;FILE *fp;fp=fopen("plat.txt","r");if(!fp){printf("文件不存在,请重新打开(╥╯^╰╥)\n");system("pause");}else{for(i=0;i<M;i++){for(j=0;j<N;j++)fscanf(fp,"%d\t",&maze[i][j]);fscanf(fp,"\n");}fscanf(fp,"%d\t",&p);fscanf(fp,"%d\t",&q);    //读取老鼠的位置fscanf(fp,"%d\t",&x);fscanf(fp,"%d\t",&y);   //读取粮仓的位置printf("读取成功,请查看新地图!( ̄▽ ̄)~*\n");system("pause");}fclose(fp);
}void path_result(int p,int q)  //统计地图的所有可能出现的路径结果,并把次数赋给全局变量answer,并在path_result函数中引用变量,作为递归终止和显示最优解的条件
{   int i,j;    maze[p][q]=1;if (maze[p][q+1]==3||maze[p][q-1]==3||maze[p+1][q]==3||maze[p-1][q]==3)   //判断当前位置上下左右是否有粮仓{++answer;    //统计一个地图的所有可能性的次数printf("已计算%d次,若超过1 h,请重启(~ ̄▽ ̄)~\r",answer);}
// 递归部分,即寻找路径的部分if(maze[p][q+1] == 0) path_result(p, q+1);  //右if(maze[p+1][q] == 0) path_result(p+1, q);  //下if(maze[p][q-1] == 0) path_result(p, q-1);  //左if(maze[p-1][q] == 0) path_result(p-1, q);  //上maze[p][q]=0;}void path_best(int p,int q,int l)     //显示最优路径的模块
{int i,j,c,k;   maze[p][q]=1;if (maze[p][q+1]==3||maze[p][q-1]==3||maze[p+1][q]==3||maze[p-1][q]==3)   //判断当前位置上下左右是否有粮仓{if(Best.min>l){Best.min=l;for (i = 0 ; i < M ; i++)for (j = 0 ; j< N ; j++) Best.b[i][j]=maze[i][j];}g++;k=((double)g/answer)/2*100+50;  //计算后面一半完成的百分比情况printf("已完成%d%%,请继续等待( ̄▽ ̄)/\r",k);c=g;if(c==answer)               //防止过度循环,比较answer条路径。   191844是检测了我自己建的地图的全部可能路径次数 文件是plat.txt{printf("已列举最优解!!!比较了前%d个方案中的最优解( ̄︶ ̄)↗\n",answer);for (i = 0 ; i < M ; i++){for (j = 0 ; j< N ; j++)if(Best.b[i][j] == 2){printf("█");}else if(Best.b[i][j] == 1)printf("の");else if(Best.b[i][j]==3)printf("粮");elseprintf("  ");printf("\n");}printf("已显示最优解,方案如上!(〃'▽'〃)\n");maze[p][q]=0;return;//  exit(0);}}++l;if(g!=answer){if(maze[p][q+1] == 0) path_best(p, q+1,l);  //右if(maze[p+1][q] == 0) path_best(p+1, q,l);  //下if(maze[p][q-1] == 0) path_best(p, q-1,l);  //左if(maze[p-1][q] == 0) path_best(p-1, q,l);  //上}maze[p][q]=0;
}void path_find(int p,int q)  //寻找通关路径的模块
{int i,j,c; maze[p][q]=1;c=g;if(c==15)               //防止过度循环,暂时只能显示15条路径,可调节。{printf("已列举10种可行方案!!方案太多可能列举不完,所以最多列举15个( ̄︶ ̄)↗\r");maze[p][q]=0;return;//  exit(0);}if (maze[p][q+1]==3||maze[p][q-1]==3||maze[p+1][q]==3||maze[p-1][q]==3)   //判断当前位置上下左右是否有粮仓{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("粮");elseprintf("  ");}printf("\n");}printf("已显示方案,如上!请稍等。。。\n");g++;}if(g!=15){if(maze[p][q+1] == 0) path_find(p, q+1);  //右if(maze[p+1][q] == 0) path_find(p+1, q);  //下if(maze[p][q-1] == 0) path_find(p, q-1);  //左if(maze[p-1][q] == 0) path_find(p-1, q);  //上}maze[p][q]=0;
}void main()   //主函数,菜单控制界面
{            //全局变量:m,n老鼠位置,p,q老鼠初始位置x,y粮仓的初始位置,g统计所有有效路径的次数,最多十次,防止因为路径过多而死循环;结构体:best Best保存最优解  局部变量:l,a,b,str,i,j,k,v,s,t,select   时间变量time_t start,end 指针fp 宏定义 M Nint select,k;time_t start,end;int hour,minute,second,t;   //时间变量while(1){system("cls");printf("  =============老鼠走迷宫游戏 n.0===================\n");printf(" |请选择:                                          |\n");printf(" |              1.开始游戏;                        |\n");printf(" |              2.新建地图;                        |\n");printf(" |              3.查看地图;                        |\n");printf(" |              4.修改地图;                        |\n");printf(" |              5.读取地图;                        |\n");printf(" |              6.显示最短路径;                    |\n");printf(" |              7.显示通关所有路径;                |\n");printf(" |              0.退出系统;                        |\n");printf("  ===========(请输入相应数字执行其功能)===========\n");printf(" 注意事项:\n 地图不要全空哦,否则不要执行6,7选项,会运算十亿次花费6个小时(本人亲测),一般\n 没耐性就别等了重启吧!然后尽量把通关所有路径设置在一亿种以内!(;≧Д≦)y\n");for(k=0;k<30;k++)fflush(stdin);  //清除键盘输入的scanf缓存,防止死循环scanf("%d",&select);if(select>=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:  g=0; Best.min=999;answer=0;start=time(NULL);path_result(p,q);    //统计地图所有解的个数path_best(p,q,1);   //寻找最短的路径end=time(NULL);t=difftime(end,start);second=t%60;     //求出秒minute=t/60;        //总分数hour=minute/60;      //求出小时minute=minute%60;   //求出分printf("花费时间:%dh %dm %ds",hour,minute,second);   //显示寻找最短路径所花费的时间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.20   作者:zero丶0   深度寻路算法的最后一个版本,n次调试,应该沒什么问题了*/

————2018年8月20日

作者:zero丶0

C语言-老鼠走迷宫(深度寻路算法)相关推荐

  1. C语言老鼠走迷宫(单路径)算法详细讲解

    最近在学习C语言的一些经典算法,其中遇到了一点困难,导致卡进度了.琢磨了很久,在绘制流程图时,突然灵感大开理解了,老鼠走迷宫算法的奇妙.所以写了这个,一来是方便以后右和我类似的同学自学时,遇到这个问题 ...

  2. C语言 老鼠走迷宫详解6,算法: Mazing-老鼠走迷宫

    说明 老鼠走迷宫是递回求解的基本题型.我们在二维阵列中使用 2 表示迷宫墙壁,使用 1 来表示老鼠的行走路径,尝试以程式求由入口至出口的路径. 解法 老鼠可走上,下,左,右四个方向.入口一般在左上,出 ...

  3. c语言老鼠走迷宫课程设计,C语言算法之老鼠走迷宫

    1.Algorithm Gossip: 老鼠走迷官(一)说明:老鼠走迷宫是递回求解的基本题型,我们在二维阵列中使用2表示迷宫墙壁,使用1来表 示老鼠的行走路径,试以程式求出由入口至出口的路径. 解法: ...

  4. c语言老鼠走迷宫原理,C语言算法(3) 老鼠走迷宫

    1.Algorithm Gossip: 老鼠走迷官(一)说明:老鼠走迷宫是递回求解的基本题型,我们在二维阵列中使用2表示迷宫墙壁,使用1来表 示老鼠的行走路径,试以程式求出由入口至出口的路径. 解法: ...

  5. c语言 老鼠乘法,c语言-老鼠走迷宫逐步理解

    c语言实现老鼠走迷宫 在没有智能手机的时代,不少人玩游戏会玩老鼠走迷宫这样的闯关游戏.每一关有着不同的地图场景,可能还会充斥着各种障碍. 老鼠走迷宫是经典的递回求解的算法题 我们用二维数组表示迷宫场景 ...

  6. 老鼠走迷宫php算法,C语言经典算法 - 老鼠走迷官(一)

    C语言经典算法 - 老鼠走迷官(一) 说明老鼠走迷宫是递回求解的基本题型,我们在二维阵列中使用2表示迷宫墙壁,使用1来表 示老鼠的行走路径,试以程式求出由入口至出口的路径. 解法老鼠的走法有上.左.下 ...

  7. c语言老鼠迷宫程序,C语言经典算法——老鼠走迷宫(二)

    说明 ​由于迷宫的设计,老鼠走迷宫的入口至出口路径可能不只一条,如何求出所有的路径呢? ​解法 ​求所有路径看起来复杂但其实更简单,只要在老鼠走至出口时显示经过的路径,然后退回上一格重新选择下一个位置 ...

  8. 算法:老鼠走迷宫问题

    算法:老鼠走迷宫问题(初) [写在前面] 老鼠走迷宫问题的递归实现,是对递归思想的一种应用. [问题描述] 给定一个二维数组,数组中2表示墙壁,0表示通路,由此数组可展示为一个迷宫图.给定入口位置和出 ...

  9. C语言实现老鼠走迷宫(附源码)

    CSDN源码下载:C语言实现老鼠走迷宫.zip 1.需求分析   利用二维数组创建一个随机迷宫或者自定义迷宫,再在迷宫中找到一条从起点到终点的路径,并用图形界面显示. 2.概要设计 3.详细设计 输入 ...

最新文章

  1. Java实用教程笔记 子类与继承2
  2. SQL实战篇:SQL基础及执行顺序
  3. 雅虎与软银构和:拟出售雅虎日本35%股份
  4. Spark入门(五)Spark SQL shell启动方式(元数据存储在derby)
  5. 7个华为关于C语言的经典面试题
  6. java实现rabbitMQ延时队列详解以及spring-rabbit整合教程
  7. ai人工智能的数据服务_从AI数据集中消除无意识的偏见
  8. IDEA搭建一个简单的Javaweb项目(二)
  9. 6.7. exists, not exists
  10. Java正则表达式判断一个字符串是否是ipv4地址
  11. hdoj1160:FatMouse's Speed(dp+最长递减子序列思想+数组巧妙记录输出)
  12. 豆瓣电影 Top 250
  13. 统计学贾俊平第六版pdf下载|贾俊平统计学第六版pdf下载电子书
  14. 常用命令之svn命令
  15. Spring boot内嵌tomcat日志配置
  16. Oracle 10g client(instantclient)环境配置
  17. 计算机excel表格教程高级筛选6,#excel如何进行高级筛选?#excle高级筛选6
  18. 【算法思路】常见岛屿数量的算法题
  19. 企业高管离职后的竟业限制义务之设定
  20. Missing artifact com.microsoft.sqlserver:sqljdbc4:jar:4.0解决方案

热门文章

  1. Facebook:拟招聘1万人,推动开发元宇宙
  2. 构建读写分离的数据库集群
  3. Python解决文本分析问题,以酒店评价数据分析为例
  4. nova 冷迁移配置nova用户互信
  5. 机器学习系列(1)SVM的公式推导
  6. ctr多少正常_亚马逊点击率多少算正常?如何提升亚马逊CTR
  7. css 蒙版_简单CSS蒙版:创建图像小插图
  8. 【★★★★★ 2023政治-马克思主义基本原理概论总结】
  9. SpringBoot入门到精通-三步整合knife4j
  10. Android - EventBus