迷宫求解路径C++版

题目

1、问题描述: 
以一个m×n的长方阵表示迷宫,0和1分别表示迷宫中的道路和障碍.设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论.
2、基本要求: 
首先实现一个以链表做存储结构的栈类型,然后编写一个求解迷宫的非递归程序.求得的通路以三元组(i,j,d)的形式输出,其中:(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向.如:对于下列数据的迷宫,输出的一条通路为(1,1,1),(1,1,2),(2,2,2),(3,2,3),(3,1,2),….
3、测试数据:
迷宫测试数据如下:左上角(1,1)为入口,右下角(8,9)为出口
                    1    2    3    4    5    6    7    8
0
0	1	0	0	0	1	0
0	0	1	0	0	0	1	0
0	0	0	0	1	1	0	1
0	1	1	1	0	0	1	0
0	0	0	1	0	0	0	0
0	1	0	0	0	1	0	1
0	1	1	1	1	0	0	1
1	1	0	0	0	1	0	1
1	1	0	0 
0	0	0	0

4、实现提示:
计算机解迷宫通常用的是“穷举求解”方法,即从入口出发,顺着某一个方向进行探索,若能走通,则继续往前进;否则沿着原路退回,换一个方向继续探索,直至出口位置,求得一条通路。假如所有可能的通路都探索到而未能到达出口,则所设定的迷宫没有通路。
可以二维数组存储迷宫数据,通常设定入口的下标为(1,1),出口点的下标为(n,n)。为处理方便起见,可在迷宫的四周加一圈障碍。对于迷宫中任一位置,均可约定有东、南、西、北四个方向可通。
5、选做内容 :
(1)编写递归形式的算法,求得迷宫中所有可能的通路;
(2)以方阵形式输出迷宫及其通路。

链表结点

#include<bits/stdc++.h>
using namespace std;
template<typename Type>class LinkStack;
template<typename Type>class StackNode{
	private:
		friend class LinkStack<Type>;
		StackNode(Type dt,StackNode<Type> *next=NULL):m_data(dt),m_pnext(next){}
	private:
		Type m_data;
		StackNode<Type> *m_pnext; 
};

链表存储的栈结构实现

#include<bits/stdc++.h>
#include "StackNode.h" 
template<typename Type> class LinkStack{ 
	public: 
		LinkStack():m_ptop(NULL){}//构造 
		~LinkStack(){MakeEmpty();} //析构 
	public:
		void MakeEmpty();//make the stack empty
		void Push(const Type item); //push the data
		Type Pop();//pop the data
		Type GetTop() const;//get the data
		void Print();//print the stack
		bool IsEmpty()const{ 
			return m_ptop==NULL;
		}
		private:
			StackNode<Type> *m_ptop; 
};
template<typename Type> void LinkStack<Type>::MakeEmpty(){
	StackNode<Type> *pmove;
	while(m_ptop!=NULL){
		pmove=m_ptop;
		m_ptop=m_ptop->m_pnext;
		delete pmove;
	}
}
template<typename Type>void LinkStack<Type>::Push(const Type item){
	m_ptop=new StackNode<Type>(item,m_ptop);
}
template<typename Type>Type LinkStack<Type>::GetTop()const{
	if(IsEmpty()){
		cout<<"There is no elements\n";
		exit(1);
	}
	return m_ptop->m_data; 
}
template<typename Type>Type LinkStack<Type>::Pop(){
	if(IsEmpty()){
		cout<<"there is no element\n";
		exit(1);
	}
	StackNode<Type>*pdel=m_ptop;
	m_ptop=m_ptop->m_pnext;
	Type temp=pdel->m_data;
	delete pdel;
	return temp;
}
template<typename Type>void LinkStack<Type>::Print(){
	StackNode<Type>*pmove=m_ptop;
	printf("\n\n\t\t*****************************************\n");
	printf("\t\t*            迷宫通路输出               *\n");
	printf("\t\t*\t\t start \t\t\t*\n");
	while(pmove!=NULL){
		printf("\t\t*\t\t  ↓ \t\t\t*\n");
		printf("\t\t*\t       (%d,%d",pmove->m_data.x,pmove->m_data.y);
		switch(pmove->m_data.z){
			case 1:{
				printf(",东)                 *\n");
				break;
			}
			case 2:{
				printf(",南)                 *\n");
				break;
			}
			case 3:{
				printf(",西)                 *\n");
				break;
			}
			case 4:{
				printf(",北)                 *\n");
				break;
			}
			default:{
				printf(")                    *\n");
				break;
			}
		}
		pmove=pmove->m_pnext;
	}
	printf("\t\t*\t\t end \t\t\t*\n");
	printf("\t\t*****************************************\n");
} 

求解的代码(包括选做)

#include<iostream>
#include<cstdio> 
#include"LinkStack.h" 
#include<windows.h>
using namespace std;
const int maxn=60;
int xto[5]={0,1,0,-1,0};//东,南,西,北 
int yto[5]={0,0,1,0,-1};
int tu[65][65];
bool vis[65][65];
char maze[65][65];
int sx,sy,ex,ey,n=1,m=1,t,q,fff=1;
//x,y,方向 
struct messege{
	int x,y,z;
	//messege(int &_x,int &_y):x(_x),y(_y){}
};
LinkStack<messege>path;
//判断字符或者数值 
int panshu(){
	string c;
	int ten=1,sum=0,i=0,flag=1;
	cin>>c;
	int l=c.size();
	if(c[0]=='-'){
		flag=-1;
		i++;
	}
	while(i<l){
		if(c[i]>='0'&&c[i]<='9'){
			sum=ten*sum+(c[i]-'0');
			ten*=10; 
		}
		else return -2;
		i++; 
	}
	sum*=flag;
	//printf("sum=%d\n",sum);
	return sum;
}

//非递归找一条路并输出 
bool dfs(){
	path.MakeEmpty();
	struct messege nex,now;//走到这个点了
	now.x=sx;
	now.y=sy; 
	now.z=0;
	path.Push(now);
	//cout<<"hell0\n";
	while(!path.IsEmpty()){
		now=path.GetTop();
		int i; 
		for(i=1;i<=4;i++){	
			nex.x=now.x+xto[i];
			nex.y=now.y+yto[i];//下一个点 
			//下一个可以走 
			if(nex.x>0&&nex.x<=n&&nex.y>0&&nex.y<=m&&!vis[nex.x][nex.y]){
				path.Pop();
				now.z=i;
				path.Push(now);//确定now这个点
				//printf("get(%d,%d,%d)\n",now.x,now.y,now.z);
				vis[now.x][now.y]=1;
				nex.z=0;
				path.Push(nex);
				if(nex.x==ex&&nex.y==ey)return true;
				break;
			}
		}
		//下一个不可以走,且绕了一周,证明now这个点不行的 
		if(i>4){
			vis[now.x][now.y]=1;
			path.Pop();
			//printf("return \n");
		}
	}
	return 0;
}

//输出路径 
void pri(){
printf("\n\n\t\t**************************************************************\n");
	printf("\t\t*                  #:障碍           .:通路                 *\n");
	printf("\t\t**************************************************************\n");	
	
	for(int i=1;i<=60;i++){// 行m
		printf("\t\t*"); 
		for(int j=1;j<=60&&i<=m+2;j++){//列 n
			if(j<=n&&i<=m){
				printf("%c",maze[j][i]);
			}
			else if(j>n+3&&j<=60)printf("#");
			else printf(" ");
		}
		if(i<=m+2)printf("*\n");
		else if(i>m+2&&i<=60)printf("############################################################*\n");
		//else printf("                                                            *\n");
	}
	printf("\t\t**************************************************************\n");
}

//菜单选择进入或退出 
int menu(){
	printf("\t\t*****************************************\n");
	printf("\t\t*             迷宫求解程序              *\n");
	printf("\t\t*                 菜单                  *\n");
	printf("\t\t*         1.进入程序  0.退出程序        *\n");
	printf("\t\t*****PS.输入-1可以快速退出整个程序*******\n");
	printf("\t\t*****************************************\n");
	printf("\t\t请输入你的选择:");
	t=panshu();
	getchar();
	if(t==1)return 1;
	else if(t==-1||t==0)return -1;
	else return 0;
}

//再见结束 
void bye(){
	printf("\n\n\t\t*****************************************\n");
	printf("\t\t*             迷宫求解程序              *\n");
	printf("\t\t*             欢迎下次来玩              *\n");
	printf("\t\t*****************************************\n");
}

//递归输出路径 
void huisu(messege &now,int &flag){
	if(now.x==ex&&now.y==ey){
		flag=0;
		printf("\n\n\n");
		pri();
		return;
	} 
	messege nex;
	for(int i=1;i<=4;i++){
		nex.x=now.x+xto[i];
		nex.y=now.y+yto[i];//下一个点  
		now.z=i;
		//printf("(%d,%d,%d)\n",now.x,now.y,now.z);
		if(nex.x>0&&nex.x<=n&&nex.y>0&&nex.y<=m&&!vis[nex.x][nex.y]&&maze[nex.x][nex.y]==' '){
			vis[nex.x][nex.y]=1;
			maze[nex.x][nex.y]='.';
			huisu(nex,flag);
			vis[nex.x][nex.y]=0;
			maze[nex.x][nex.y]=' ';
		}
	}
	return;
}

//进度条 
void guodu(){
		printf("\n\n\t\t正在加载:") ; 
		int i=16;
		while(i--)
		{	printf("|");
			Sleep(30);
			printf("\b");
			printf("-");
			Sleep(30);
			printf("\b");
			printf("/");
			Sleep(30);
			printf("\b");
			printf(".");
			Sleep(30);
		}
		printf("\n");
} 

//初始化 
void init_vis(){
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=m;i++){//列 tu(第几列,第几排) 
		for(int j=1;j<=n;j++){//行填充 
			if(tu[j][i]==1){
				vis[j][i]=1;
				maze[j][i]='#';
			}
			else maze[j][i]=' ';
		}
	}
	if(maze[sx][sy]==' ')maze[sx][sy]='.';
}

//选择输出方式 
void choosepri(){
	printf("\n\n\t\t*****************************************\n");
	printf("\t\t*          选择输出(回车结束)           *\n");
	printf("\t\t*          1.指示输出一条路径           *\n");
	printf("\t\t*          2.方阵输出所有路径           *\n");
	printf("\t\t*****PS.输入-1可以快速退出整个程序*******\n");
	printf("\t\t*****************************************\n");
	printf("\t\t请输入你的选择:");
} 

//输入大小 
int inputsize(){
	printf("\n\n\t\t*****************************************\n");
	printf("\t\t*      输入迷宫的大小(0<n,m<=60)      *\n");
	printf("\t\t*****PS.输入-1可以快速退出整个程序*******\n");
	printf("\t\t*****PS.按下回车分隔两个数值*************\n");
	printf("\t\t*****************************************\n");
	printf("\t\t请输入|n:");
	n=panshu(); 
	printf("\t\t请输入|m:");
	m=panshu(); 
	if(n==-1||m==-1)return -1;
	else if(0<n&&n<=60&&0<m&&m<=60)return 1;
	else return 0;
}

//输入迷宫 
int inputmaze(){
	printf("\n\n\t\t*****************************************\n");
	printf("\t\t*       输入迷宫(回车换下一排)          *\n");
	printf("\t\t*       1----障碍       0----空路       *\n");
	printf("\t\t******PS.一旦输入有误请全部重新输入******\n");
	printf("\t\t******PS.输入-1可以快速退出整个程序******\n");
	printf("\t\t******PS.输入非0/1字符即可重新输入迷宫***\n");
	printf("\t\t******PS.回车分隔每一排,空格分隔每一列**\n");
	printf("\t\t*****************************************\n");
	int i,j;
	memset(vis,0,sizeof(vis));
	for(i=1;i<=m;i++){//列 tu(第几列,第几排) 
		printf("\t\t");
		for(j=1;j<=n;j++){//行填充 
			tu[j][i]=panshu();
			if(tu[j][i]==1){
				vis[j][i]=1;
				maze[j][i]='#';
			}
			else if(tu[j][i]==0){
				maze[j][i]=' ';
				vis[j][i]=0;
			}
			else if(tu[j][i]==-1){
				fff=0;
				return -1; 
			}
			else return 0; 
		}
	}
	return 1;
}

//输入起点(判错) 
int instart(){
	printf("\n\n\t\t*****************************************\n");
	printf("\t\t*           输入起点(x列,y排)           *\n");
	printf("\t\t*****PS.输入-1可以快速退出整个程序*******\n");
	printf("\t\t*****PS.按下回车分隔两个数值*************\n");
	printf("\t\t*****************************************\n");
	printf("\t\t请输入|x:");
	sx=panshu(); 
	printf("\t\t请输入|y:");
	sy=panshu();
	if(maze[sx][sy]==' ')maze[sx][sy]='.';
	if(sx==-1||sy==-1)return -1;
	else if(0<sx&&sx<=n&&0<sy&&sy<=m)return 1;
	else return 0;
}

//输入终点(判错) 
int inend(){
	printf("\n\n\t\t*****************************************\n");
	printf("\t\t*           输入终点(x列,y排)           *\n");
	printf("\t\t*****PS.输入-1可以快速退出整个程序*******\n");
	printf("\t\t*****PS.按下回车分隔两个数值*************\n");
	printf("\t\t*****************************************\n");
	printf("\t\t请输入|x:");
	ex=panshu();
	printf("\t\t请输入|y:");
	ey=panshu();
	if(ex==-1||ey==-1)return -1;	
	else if(0<ex&&ex<=n&&0<ey&&ey<=m)return 1;
	else return 0;
}

//迷宫无解输出 
void priworry(){
	printf("\n\n\t\t*****************************************\n");
	printf("\t\t*            sorry~此迷宫无解           *\n");
	printf("\t\t*****PS.输入-1可以快速退出整个程序*******\n");
	printf("\t\t*****************************************\n");
}

//输入错误时要求重新输入 ,同时输出该选项重输入 
void inputworry(){
	printf("\n\n\t\t*****************************************\n");
	printf("\t\t*            sorry~输入错误             *\n");
	printf("\t\t**************请重新输入*****************\n");
	printf("\t\t*****PS.输入-1可以快速退出整个程序*******\n"); 
	printf("\t\t*****************************************\n");	
}

//选择输出方式
int choose(){
	choosepri();
	q=panshu();
	if(q==-1)return -1;
	switch(q){
		case 1:{
			init_vis(); 
			if(dfs()&&maze[sx][sy]=='.'){
				LinkStack<messege>ans;
				while(!path.IsEmpty()){
					ans.Push(path.GetTop());
					path.Pop();
				}
				ans.Print();
			}
			else priworry();
			break;
		}
		case 2:{
			init_vis();
			messege a;
			a.x=sx;
			a.y=sy;
			if(maze[sx][sy]=='.'){
				int flag=1;
			printf("\n\n\t\t**************************************************************\n");
	    		printf("\t\t*                     你输入的数值迷宫                       *\n");
	    		printf("\t\t**************************************************************\n");	
				for(int i=1;i<=60;i++){
					printf("\t\t*");
					for(int j=1;j<=60;j++){
						if(i<=m&&j<=n)printf("%d",tu[j][i]);//lie  hang 
						else printf(" ");
					} 
					printf("*\n");
				}
				printf("\t\t**************************************************************\n");	
				huisu(a,flag);
				if(flag)priworry();
			}
			else priworry();
			break;
		}
		default:{
			getchar(); 
			return 0;
			break;
		}
	}
	getchar(); 
	return 1;			
}

//是否想要消除上一个? 
int del(){
	printf("\t\t*****************************************\n");
	printf("\t\t*         是否想要消除上一个?          *\n");
	printf("\t\t*         1.是         0.否             *\n");
	printf("\t\t*****PS.输入-1可以快速退出整个程序********\n");
	printf("\t\t*****************************************\n");
	printf("\t\t请输入你的选择:");
	t=panshu();
	getchar();
	if(t==1)return 1;
	else if(t==-1)return -1;
	else if(t==0)return 0;
	else return -2;
}



int main(){
	system("color 4f");
	freopen("1.txt","r",stdin); 
	while(fff)
	{	
		//输入选项 
		while(fff){
			int z=menu();
			if(z==-1)fff=0;
			else if(z==1){
			    int p; 
				while(fff){
					p=del();
					if(p==-1)fff=0;//退出 
					else if(p==0)break;//否 
					else if(p==1)break;//是 
					else inputworry();//不符要求 
				}
				if(p==0)break;//成功的 				
			}
			else inputworry();
		}
		
		//进度条 
		guodu();
		system("cls");
		
		//输入大小 
		while(fff){
			int z=inputsize();
			if(z==-1)fff=0;
			else if(z==1){
			    int p; 
				while(fff){
					p=del();
					if(p==-1)fff=0;//退出 
					else if(p==0)break;//否 
					else if(p==1)break;//是 
					else inputworry();//不符要求 
				}
				if(p==0)break;//成功的 
			}
			else inputworry();
		}
		
		//输入迷宫 inputmaze
		while(fff){
			int z=inputmaze();
			if(z==-1)fff=0;//退出 
			else if(z==1){//符合要求 
			    int p; 
				while(fff){
					p=del();
					if(p==-1)fff=0;//退出 
					else if(p==0)break;//否 
					else if(p==1)break;//是 
					else inputworry();//不符要求 
				}
				if(p==0)break;//成功的 
			}
			else inputworry();//不符合要求 
		} 
		
		//起点instart
		while(fff){
			int z=instart();
			if(z==-1)fff=0;
			else if(z==1){
			    int p; 
				while(fff){
					p=del();
					if(p==-1)fff=0;//退出 
					else if(p==0)break;//否 
					else if(p==1)break;//是 
					else inputworry();//不符要求 
				}
				if(p==0)break;//成功的 
			}
			else inputworry();
		}
		
		//终点inend
		while(fff){
			int z=inend();
			if(z==-1)fff=0;
			else if(z==1){
			    int p; 
				while(fff){
					p=del();
					if(p==-1)fff=0;//退出 
					else if(p==0)break;//否 
					else if(p==1)break;//是 
					else inputworry();//不符要求 
				}
				if(p==0)break;//成功的 
			}
			else inputworry();
		}
		
		if(fff){
			guodu(); 		
		}
		//输入输出选择
		system("cls");
		
		while(fff){
			int z=choose();
			if(z==-1)fff=0;
			else if(z==0)inputworry();	
			printf("\t\t-----------------------------------------\n");
			printf("\t\t*****PS.按任意键退出这个观察区***********\n");
			getchar();
			system("cls");
			//getchar();
		}
	} 
	bye();
	return 0;
} 



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值