数据结构课设-迷宫寻路系统

数据结构-迷宫寻路系统的设计

简介

这是一个迷宫寻路系统,它的功能是

  1. 创建迷宫
  2. 判断迷宫是否有出口
  3. 输出走出迷宫最少的步数
  4. 输出走出迷宫的轨迹

在该课题中,我们主要使用了BFS(广度优先搜索)和队列的概念,队列我们使用的是链队列,

下面我先简单介绍一下该队列的结构

c 复制代码
typedef struct QNode//创建队列节点元素
{
	QElemType date;//坐标
	struct QNode *next;
}QNode ,*queue; 
typedef struct//创建双端队列类型 
{
	queue front;//队头指针 
	queue rear;//队尾指针 
}Linkqueue;

front为队头,rear为队尾,date域储存坐标信息,而next指针域储存队头和队尾元素的下一个元素地址

在这里我们对链式队列进行了初始化,让队头和队尾元素为new QNode,指针指空

c 复制代码
int Init(Linkqueue &q)//对链队列进行初始化 
{
	q.front=q.rear=new QNode;
	q.front->next=NULL;
	return  OK;
}

创建队列和初始化

下面是创建队列的一系列基本操作,增删,获取对头元素

c 复制代码
int push(Linkqueue &q,QElemType t)
{//向队列中添加元素 
	queue p;
	p=new QNode;
	p->date=t;
	p->next=NULL;
	q.rear->next=p;
	q.rear=p;
	return OK;
}
int pop(Linkqueue &q,QElemType &t)
{//向队列中删除元素 
	if(q.front==q.rear) return ERROR;
	queue p=q.front->next;
	t=p->date;
	q.front->next=p->next;
	if(q.rear==p) q.rear=q.front;
	delete p;
	return OK;
}
QElemType Get(Linkqueue q)
{//get方法取对头元素 
	if(q.front!=q.rear)
	return q.front->next->date;
}

做完了这些工作,我们就可以创建迷宫了,我们定义g数组储存迷宫,d数组储存距离,这是创建迷宫的函数

c 复制代码
void Createmigong(int x,int y)//输入地图 
{
	for (int i = 0; i < x; i++)
        for (int j = 0; j < y; j++)
            cin >> g[i][j];
}

用bfs实现的三种方法

剩下是用bfs实现的三个方法,他们大致相同,但是在某些细节又不太一样

memset函数将d数组初始化为-1,判断是否已经走过该路径

c 复制代码
void Judge_key(int nx,int my)
{//bfs求得是否可以走出迷宫 
	Linkqueue q;
	Init(q);//定义一个队列 
	QElemType t0;
	t0.x=0;
	t0.y=0;
	int tmp1=push(q,t0);//队尾插入起点(0,0)
	memset(d, -1, sizeof(d));//将d[][]初始化为-1,代表没走过 
	d[0][0]=0;//起点(0,0)已走
	int dx[4] ={0,0,-1,1},dy[4] = {1,-1,0,0};//设置偏移量 
	while(q.front!=q.rear)//队列不为空
	{
		QElemType t;
		t=Get(q);//取队头元素
		int t1,t2;
		QElemType t3;
	int tmp2=pop(q,t3);//出队
		for(int i=0;i<4;i++)
		{
			int x1=t.x+dx[i],y1=t.y+dy[i];//队头元素移动后的坐标 
			
			if(x1>=0&&x1<nx&&y1>=0&&y1<my&&g[x1][y1]==0&&d[x1][y1]==-1)//在边界内 并且是0可以走 且之前没有走过
			{
				
				d[x1][y1]=d[t.x][t.y]+1;//当前点到起点的距离
				QElemType t4;
				t4.x=x1;
				t4.y=y1;
			    int tmp3=push(q,t4);
				
			}
			
		}
	}
	if(d[nx-1][my-1]==-1){
		//出口到入口的距离为-1,那么表示没有通路,
		cout<<"该迷宫不存在通路"<<endl; 
	}
	else{
		cout<<"该迷宫存在通路,请找到走出迷宫的最佳路线"<<endl; 
	}
}
int bfs(int nx,int my)
{//bfs求得走出迷宫最小步数 
	Linkqueue q;
	Init(q);//定义一个队列 
	QElemType t0;
	t0.x=0;
	t0.y=0;
	int tmp1=push(q,t0);//队尾插入起点(0,0)
	memset(d, -1, sizeof(d));//将d[][]初始化为-1,代表没走过 
	d[0][0]=0;//起点(0,0)已走
	int dx[4] ={0,0,-1,1},dy[4] = {1,-1,0,0};//设置偏移量 
	while(q.front!=q.rear)//队列不为空
	{
		QElemType t;
		t=Get(q);//取队头元素
		int t1,t2;
		QElemType t3;
	int tmp2=pop(q,t3);//出队
		for(int i=0;i<4;i++)
		{
			int x1=t.x+dx[i],y1=t.y+dy[i];//队头元素移动后的坐标 
			
			if(x1>=0&&x1<nx&&y1>=0&&y1<my&&g[x1][y1]==0&&d[x1][y1]==-1)//在边界内 并且是0可以走 且之前没有走过
			{
				
				d[x1][y1]=d[t.x][t.y]+1;//当前点到起点的距离
				QElemType t4;
				t4.x=x1;
				t4.y=y1;
			    int tmp3=push(q,t4);
				
			}
			
		}
	}
	return d[nx-1][my-1];//返回点(n,m)的距离 
}
void bfs1(int nx,int my)
{//bfs1求得走出迷宫轨迹 
	
	Linkqueue q;
	Init(q);//定义一个队列 
	QElemType t0;
	t0.x=0;
	t0.y=0;
	int tmp1=push(q,t0);//队尾插入起点(0,0)
	memset(d, -1, sizeof(d));//将d[][]初始化为-1,代表没走过 
	d[0][0]=0;//起点(0,0)已走
	 int dx[4] ={0,0,-1,1},dy[4] = {1,-1,0,0};//设置偏移量 
	while(q.front!=q.rear)//队列不为空
	{
		QElemType t;
		t=Get(q);//取队头元素
		int t1,t2;
		QElemType t3;
	int tmp2=pop(q,t3);//出队
		for(int i=0;i<4;i++)
		{
			int x1=t.x+dx[i],y1=t.y+dy[i];//队头元素移动后的坐标 
			
			if(x1>=0&&x1<nx&&y1>=0&&y1<my&&g[x1][y1]==0&&d[x1][y1]==-1)//在边界内 并且是0可以走 且之前没有走过
			{
				
				d[x1][y1]=d[t.x][t.y]+1;//当前点到起点的距离
			prev1[x1][y1]=t;
				QElemType t4;
				t4.x=x1;
				t4.y=y1;
			    int tmp3=push(q,t4);//把这个没有走过的路径 
				
			}
			
		}
	}
	int x=nx-1,y=my-1;
	while(x||y)//有一个不d等于0
	{
		cout<<"("<<x+1<<" "<<y+1<<")"<<"->";
		QElemType t=prev1[x][y];
		x=t.x,y=t.y;
	}
	cout<<"end"<<endl;
}

下面我们通过一张图来描绘一下该迷宫使用bfs的求解流程

其中,关键的是这样一段代码,以此用bfs来寻找它的其他路径

c 复制代码
int dx[4] ={0,0,-1,1},dy[4] = {1,-1,0,0};//设置偏移量 
for(int i=0;i<4;i++)

这里设置了两个数组进行四个方向的遍历,后来循环尽心遍历

以下是该项目源码

项目源码

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <cstring>//使用memset函数
#define MAXSIZE 100
#define OK 1
#define ERROR -1
using namespace std;
const int N = 110;
int nx,my;//迷宫的行数和列数 全局变量
int g[N][N];//存储地图  全局变量
int d[N][N];//存储距离 全局变量
pair<int,int> prev2[N];
struct QElemType//存储坐标
{
	int x;
	int y;
};
QElemType prev1[N][N];//prve1储存路径 全局变量
typedef struct QNode//创建队列节点元素
{
	QElemType date;//坐标
	struct QNode *next;
}QNode ,*queue; 
typedef struct//创建双端队列类型 
{
	queue front;//队头指针 
	queue rear;//队尾指针 
}Linkqueue;
int Init(Linkqueue &q)//对链队列进行初始化 
{
	q.front=q.rear=new QNode;
	q.front->next=NULL;
	return  OK;
}
int push(Linkqueue &q,QElemType t)
{//向队列中添加元素 
	queue p;
	p=new QNode;
	p->date=t;
	p->next=NULL;
	q.rear->next=p;
	q.rear=p;
	return OK;
}
int pop(Linkqueue &q,QElemType &t)
{//向队列中删除元素 
	if(q.front==q.rear) return ERROR;
	queue p=q.front->next;
	t=p->date;
	q.front->next=p->next;
	if(q.rear==p) q.rear=q.front;
	delete p;
	return OK;
}
QElemType Get(Linkqueue q)
{//get方法取对头元素 
	if(q.front!=q.rear)
	return q.front->next->date;
}
void Createmigong(int x,int y)//输入地图 
{
	for (int i = 0; i < x; i++)
        for (int j = 0; j < y; j++)
            cin >> g[i][j];
}
void Judge_key(int nx,int my)
{//bfs求得是否可以走出迷宫 
	Linkqueue q;
	Init(q);//定义一个队列 
	QElemType t0;
	t0.x=0;
	t0.y=0;
	int tmp1=push(q,t0);//队尾插入起点(0,0)
	memset(d, -1, sizeof(d));//将d[][]初始化为-1,代表没走过 
	d[0][0]=0;//起点(0,0)已走
	int dx[4] ={0,0,-1,1},dy[4] = {1,-1,0,0};//设置偏移量 
	while(q.front!=q.rear)//队列不为空
	{
		QElemType t;
		t=Get(q);//取队头元素
		int t1,t2;
		QElemType t3;
	int tmp2=pop(q,t3);//出队
		for(int i=0;i<4;i++)
		{
			int x1=t.x+dx[i],y1=t.y+dy[i];//队头元素移动后的坐标 
			
			if(x1>=0&&x1<nx&&y1>=0&&y1<my&&g[x1][y1]==0&&d[x1][y1]==-1)//在边界内 并且是0可以走 且之前没有走过
			{
				
				d[x1][y1]=d[t.x][t.y]+1;//当前点到起点的距离
				QElemType t4;
				t4.x=x1;
				t4.y=y1;
			    int tmp3=push(q,t4);
				
			}
			
		}
	}
	if(d[nx-1][my-1]==-1){
		//出口到入口的距离为-1,那么表示没有通路,
		cout<<"该迷宫不存在通路"<<endl; 
	}
	else{
		cout<<"该迷宫存在通路,请找到走出迷宫的最佳路线"<<endl; 
	}
}
int bfs(int nx,int my)
{//bfs求得走出迷宫最小步数 
	Linkqueue q;
	Init(q);//定义一个队列 
	QElemType t0;
	t0.x=0;
	t0.y=0;
	int tmp1=push(q,t0);//队尾插入起点(0,0)
	memset(d, -1, sizeof(d));//将d[][]初始化为-1,代表没走过 
	d[0][0]=0;//起点(0,0)已走
	int dx[4] ={0,0,-1,1},dy[4] = {1,-1,0,0};//设置偏移量 
	while(q.front!=q.rear)//队列不为空
	{
		QElemType t;
		t=Get(q);//取队头元素
		int t1,t2;
		QElemType t3;
	int tmp2=pop(q,t3);//出队
		for(int i=0;i<4;i++)
		{
			int x1=t.x+dx[i],y1=t.y+dy[i];//队头元素移动后的坐标 
			
			if(x1>=0&&x1<nx&&y1>=0&&y1<my&&g[x1][y1]==0&&d[x1][y1]==-1)//在边界内 并且是0可以走 且之前没有走过
			{
				
				d[x1][y1]=d[t.x][t.y]+1;//当前点到起点的距离
				QElemType t4;
				t4.x=x1;
				t4.y=y1;
			    int tmp3=push(q,t4);
				
			}
			
		}
	}
	return d[nx-1][my-1];//返回点(n,m)的距离 
}
void bfs1(int nx,int my)
{//bfs1求得走出迷宫轨迹 
	
	Linkqueue q;
	Init(q);//定义一个队列 
	QElemType t0;
	t0.x=0;
	t0.y=0;
	int tmp1=push(q,t0);//队尾插入起点(0,0)
	memset(d, -1, sizeof(d));//将d[][]初始化为-1,代表没走过 
	d[0][0]=0;//起点(0,0)已走
	 int dx[4] ={0,0,-1,1},dy[4] = {1,-1,0,0};//设置偏移量 
	while(q.front!=q.rear)//队列不为空
	{
		QElemType t;
		t=Get(q);//取队头元素
		int t1,t2;
		QElemType t3;
	int tmp2=pop(q,t3);//出队
		for(int i=0;i<4;i++)
		{
			int x1=t.x+dx[i],y1=t.y+dy[i];//队头元素移动后的坐标 
			
			if(x1>=0&&x1<nx&&y1>=0&&y1<my&&g[x1][y1]==0&&d[x1][y1]==-1)//在边界内 并且是0可以走 且之前没有走过
			{
				
				d[x1][y1]=d[t.x][t.y]+1;//当前点到起点的距离
			prev1[x1][y1]=t;
				QElemType t4;
				t4.x=x1;
				t4.y=y1;
			    int tmp3=push(q,t4);//把这个没有走过的路径 
				
			}
			
		}
	}
	int x=nx-1,y=my-1;
	int cnt=1;
	while(x||y)//有一个不d等于0
	{
		prev2[cnt++]={x+1,y+1};
		QElemType t=prev1[x][y];
		x=t.x,y=t.y;
	}
	prev2[cnt]={1,1};
	for(int i=cnt;i>=0;i--){
		cout<<"("<<prev2[i].first<<" "<<prev2[i].second<<")"<<"->";
	}
	cout<<"end"<<endl;
}
int main()
{
	int p=1;
	while(p)
	{
		
		printf("       欢迎使用谜宫系统       \n");
		printf("------------------------------\n");
		printf("1          创建迷宫           \n");
		printf("2     判断迷宫是否有出口      \n");
		printf("3    输出走出迷宫最少的步数   \n");
		printf("4     输出走出迷宫的轨迹      \n");
		printf("5            退出             \n");
				printf("请输入:\n");
		int n;
		cin>>n;
		if(n==1)
		{
			printf("0代表可以走,1代表不可以走\n请输入迷宫的行数和列数\n");
		    		cin>>nx>>my;
					printf("\n请输入迷宫\n");
					Createmigong(nx,my);
		} 
		
		else if(n==2)
		{
			Judge_key(nx,my);
		}
		else if(n==3)
		{
		    printf("走出迷宫最少的步数:%d\n", bfs(nx,my)); 
		}
		else if(n==4)
		{
		    	printf("出迷宫的轨迹\n");
		    	bfs1(nx,my);
		}
		else if(n==5)
		{
			p=0;
			cout<<"程序安全退出"<<endl;
		
		}
		else
		{
			printf("非法输入,请重新输入\n");
		}
		
    }
	return 0;
}
相关推荐
乐悠小码5 分钟前
数据结构------队列(Java语言描述)
java·开发语言·数据结构·链表·队列
2的n次方_9 分钟前
二维费用背包问题
java·算法·动态规划
simple_ssn38 分钟前
【C语言刷力扣】1502.判断能否形成等差数列
c语言·算法·leetcode
寂静山林1 小时前
UVa 11855 Buzzwords
算法
Curry_Math1 小时前
LeetCode 热题100之技巧关卡
算法·leetcode
ahadee1 小时前
蓝桥杯每日真题 - 第10天
c语言·vscode·算法·蓝桥杯
军训猫猫头2 小时前
35.矩阵格式的一到一百数字 C语言
c语言·算法
Mr_Xuhhh3 小时前
递归搜索与回溯算法
c语言·开发语言·c++·算法·github
SoraLuna3 小时前
「Mac玩转仓颉内测版12」PTA刷题篇3 - L1-003 个位数统计
算法·macos·cangjie
爱吃生蚝的于勒5 小时前
C语言内存函数
c语言·开发语言·数据结构·c++·学习·算法