C语言-老鼠走迷宫(广度寻路算法)

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

深读优先寻路算法原文:https://blog.csdn.net/qq_42476927/article/details/81868068 

本文是基于之前的深度优先寻路算法改进而来,参考了许多广度遍历的代码结合自己代码改进成为现在的样子,基本上优化了之前的所有缺点,相较于之前寻路的速度快了N倍,当然深度优先本来就不是用于遍历出最短路径,广度优先的寻路算法才是真正适合用于寻找最短路径,刚开始思路没那么清晰所以才有了深度遍历最短路径。

  • 以下是全部的函数和部分变量:

  1. void game()  //走迷宫游戏,包含时间统计,以及对老鼠的移动控制,游戏模块

  2. void create_plat()   //新建地图,并存入文件的模块   地图文件是plat.txt

  3. void show_plat()   //地图展示模块

  4. void alter_plat()    //修改地图模块

  5. void read_plat()  //读取文件里的地图模块

  6. //广度优先寻路算法 

    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()                          //标记最短路径模块并显示

  7. void path_find(int p,int q)  //寻找通关路径的模块,深度算法

  8. 新增元素:

    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次调试,应该沒什么问题了*/

 

你可能感兴趣的:(深度算法,c语言,广度算法)