迷宫问题(C++实现)

/*
	Name:迷宫问题
*/
#include <ctime>
#include <iostream>
#include <windows.h>
#include <queue>
#include <stack>
#include <windows.h> 
using namespace std;
#define MAX 40//迷宫最大30*30
#define in -1//迷宫初始化
#define b 2//起点标识
#define e 3//终点标识 
#define PQ -2//探索过的路径;
#define shorts -4//最短路径 
int move[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//四个方向,依次是右,下,左,上
int maze[MAX][MAX];//二维数组存储迷宫 
int end_x,end_y;//终点坐标 
int begin_x,begin_y;//起点坐标
int x,y;//迷宫的行数与列数 
int i,j;//控制循环
//坐标 
typedef struct po{
	int x1,y1;
}point;
//每个点的前驱路径 
point paths[MAX][MAX]; 
//队列 
queue<point> p;
//栈 
stack<point> path,ppath; 
//获取迷宫模块函数
int getFile();

//自动生成迷宫
void Autoge();
 
//手动输入迷宫 
void Minput();

//输出迷宫
void printmaze();
 
//探索路径模块函数
int Findway();

//用栈结构保存路径 
void Shortestpath();

//输出最短路径模块函数
void printway();
 
//定义字体颜色函数 
int color(int c);

//输出位置获取函数 
void gotoxy(int x,int y);

//主界面函数
void interface1(); 
int main(){
	int choose;
	interface1(); 
	color(3);
	cout<<"☆请选择要实现的功能【0 1 2 3 4】:";
	cin>>choose; 
	while(1){
		switch(choose){
			case 1:getFile();color(3);cout<<"☆请再次选择要实现的功能【0 1 2 3 4】:";cin>>choose; break;
			case 3:Findway();color(3);cout<<"☆请选择要实现的功能【0 1 2 3 4】:";cin>>choose; break;
			case 2:printmaze();color(3);cout<<"☆请选择要实现的功能【0 1 2 3 4】:";cin>>choose;break;
			case 4:Shortestpath();printway();color(3);cout<<"☆请选择要实现的功能【0 1 2 3 4】:";cin>>choose;break;
			case 0:return 0;break;
		}
	}
	return 0;
}
//自动生成迷宫
void Autoge(){
	//思考问题1:自动生成的迷宫有可能通路杂乱
	//思考问题2:边界应为墙
	//思考问题3:随机数的生成来随机生成迷宫,但应保证墙和路成一定的比列,才能使得最路径研究有意义
	//规定:墙的比列为控制小于或等于40%(边界墙不计算在内)
	color(15);
	memset(maze,in,sizeof(maze));
	float ratio = 0.4;//墙的比列系数 
	time_t GG;//时间种子 
	int cou = 0;//统计个数(初始化为0) 
	srand((unsigned)time(&GG));//随机数
	cout<<"请输入要生成迷宫的行数与列数:";
	cin>>x>>y;
	//不符合要求迷宫 
	while(x == 0||y == 0||x > MAX||y > MAX){
		cout<<"输入的迷宫不符合要求,请重新输入:";
		cin>>x>>y; 
	}
	//随机产生墙和路(0代表墙,1代表路) 
	for(i = 0;i < x;i++){
		for(int j = 0;j < y;j++){
			maze[i][j] = rand()%10;//0-9随机数产生 
			maze[i][j] = maze[i][j]/5;//除5产生0/1 
		}
	}
	//调整迷宫
	for(j = 0;j < y;j++){
		maze[0][j] = 0;
		maze[x-1][j] = 0;
	}
	//解决问题2:边界问题(将边界都变成墙) 
	for(i = 1;i < x - 1;i++){
		maze[i][0] = 0;
		maze[i][y - 1] = 0;
	}
	//统计当前墙的个数 
	for(i = 1;i < x - 1;i++){
		for(j = 1;j < y - 1;j++){
			if(maze[i][j] == 0){
				cou++;
			}
		}
	}
	//墙的总数
	int sum;
	sum = (int)(x-2)*(y-2)*ratio;
	while(sum!=cou){
		//判断墙多了还是少了 
		if(cou<sum){
			i = rand()%(x - 2) + 1;//产生1 - x-2的随机数 
			j = rand()%(y - 2) + 1;
			//随机产生的坐标位子如果为路修改为墙 
			if(maze[i][j] == 1){
				maze[i][j] = 0;
				cou++;
			} 
		}else{
			i = rand()%(x - 2) + 1;//产生1 - x-1的随机数 
			j = rand()%(y - 2) + 1;
			//随机产生的坐标位子如果为墙修改为路 
			if(maze[i][j] == 0){
				maze[i][j] = 1;
				cou--;
			} 
		} 
	}
	cout<<"已自动生成!"<<endl<<endl<<endl; 
}
//手动输入迷宫
void Minput(){
	color(15);
	memset(maze,in,sizeof(maze));
	//输入的数据边界都控制为墙 
	cout<<"请输入要生成迷宫的行数与列数"<<endl;
	cin>>x>>y;
	//不符合要求迷宫 
	while(x == 0||y == 0||x > MAX||y > MAX){
		cout<<"输入的迷宫不符合要求,请重新输入:"<<endl;
		cin>>x>>y; 
	}
	cout<<"请输入数据"<<endl;
	for(i = 0;i < x;i++){
		for(j = 0;j < y;j++){
			cin>>maze[i][j];
		}
	} 
	for(i = 1;i < x - 1;i++){
		maze[i][0] = 0;
		maze[i][y - 1] = 0;
	}
	cout<<"已建立成功!"<<endl<<endl<<endl;
}
//输出迷宫 
void printmaze(){
	color(15);
//	SetConsoleOutputCP(437);
	int wall = 219;//墙标识 
	int origin = 65;//起点标识
	int destination = 66;//终点标识 
	char c; 
	for(i = 0;i < x;i++){
		for(j = 0;j < y;j++){
			switch(maze[i][j]){
				case 0: color(15);c = wall; cout<<"■";break; 
				case -2:color(15);cout<<"  ";break;
				case 1: color(15);cout<<"  ";break;
				case 2: color(11);c = origin; cout<<"★";break;
				case 3: color(11);c = destination; cout<<"★";break;
				case -4: color(15);cout<<"⊙";
			}
		}
		cout<<endl;
	}
	cout<<endl<<endl<<endl;
}
//获取迷宫模块函数
int getFile(){
	int choose; 
    color(15); 
    cout<<"☆请从下面选项中选择获取迷宫的方法:"<<endl;
	cout<<"    1.手动输入"<<endl<<"    2.自动生成 "<<endl;
	cout<<"☆请选择:"; 
	cin>>choose;
	if(choose == 1)
	Minput(); 
	if(choose == 2)
	Autoge();
}
//探索路径模块函数
int Findway(){
	color(15);
	int m,n;//记录坐标位置,用此位置来探测下一位置
	int c,f;
	point ll,gg,kk;
	//初始化 
	for(i = 0;i < x;i++){
		for(j = 0;j < y;j++){
			paths[i][j].x1 = -1;
			paths[i][j].y1 = -1;
		}
	}
	cout<<"请输入迷宫的起点:";
	cin>>begin_x>>begin_y;
	while(maze[begin_x][begin_y] == 0||begin_x >= x||begin_y >= y){
		cout<<"该点不符合要求,请重新输入:";
		cin>>begin_x>>begin_y; 
	}
	cout<<"请输入迷宫的终点:";
	cin>>end_x>>end_y;
	while(maze[end_x][end_y] == 0||end_x >= x||end_y >= y){
		if(end_x == begin_x&&end_y == begin_y){
			cout<<"起点与终点相同,请重新输入:"; 
			cin>>end_x>>end_y; 
		}else{
			cout<<"该点不符合要求请重新输入:";
			cin>>end_x>>end_y;
		}
	}
	//规为起点与终点 
	ll.x1 = begin_x;
	ll.y1 = begin_y;
	maze[begin_x][begin_y] = b;
	//起点入队 
	p.push(ll); 
	while(!p.empty()){
		gg = p.front();
		p.pop();
		m = gg.x1;
		n = gg.y1;
		//搜索四个方向 
		for(i = 0;i < 4;i++){
			c = m + move[i][0];
			f = n + move[i][1];
			//为路就入队操作 
			if(maze[c][f] == 1){
				maze[c][f] = PQ;
				kk.x1 = c;
				kk.y1 = f;
				p.push(kk);
				//记录当前点时由哪个点探索到的 
				paths[c][f].x1 = m;
				paths[c][f].y1 = n;
				if(c == end_x&&f == end_y){
					maze[end_x][end_y] = e;
					cout<<"迷宫路径探索成功!"<<endl<<endl<<endl; 
					return 0;
				}
			}
		}
	}
	maze[end_x][end_y] = e;
	cout<<"迷宫路径探索成功!"<<endl<<"("<<begin_x<<","<<begin_y<<")"<<"--("<<end_x<<","<<end_y<<")"<<"不存在通路"<<endl<<endl<<endl; 
	return 1;
}
//用栈结构保存路径 
void Shortestpath(){
	point v1,v2;
	//探索终点的由哪个节点探索到的 
	v1.x1 = paths[end_x][end_y].x1;
	v1.y1 = paths[end_x][end_y].y1;
	//循环找,知道找到起点,并把最短路径保存在栈中 
	while(v1.x1 != begin_x||v1.y1 != begin_y){
		path.push(v1);
//		maze[v1.x1][v1.y1] = shorts;
		v2.x1 = paths[v1.x1][v1.y1].x1;
		v2.y1 = paths[v1.x1][v1.y1].y1;
		v1.x1 = v2.x1;
		v1.y1 = v2.y1;
	}
}
//定义字体颜色函数 
int color(int c){
       SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),c);
       return 0;
}
//主界面函数
void interface1(){ 
    color(10); 
    cout<<"                         ☆迷宫问题"<<endl;
    color(14);
    cout<<"┌━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┐"<<endl;
	cout<<"│                                                            │" <<endl;
	cout<<"│                                                            │" <<endl;
	cout<<"│" ;
	color(12);
	cout<<"         1.建立迷宫              2.输出迷宫                 ";
	color(14);
	cout<<"│"<<endl; 
	cout<<"│                                                            │" <<endl;
	cout<<"│                                                            │" <<endl;
	cout<<"│                                                            │" <<endl;
	cout<<"│";
	color(12);
	cout<<"         3.探索最短路            4.输出迷宫最短路径   ";
	color(14);
	cout<<"      │"<<endl;
	cout<<"│                                                            │" <<endl;
	cout<<"│                                                            │" <<endl;
	cout<<"└━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┘" <<endl;	 
}
//输出最短路径模块函数
void printway(){
	point c;
	//复制栈 
	ppath = path;
	//清屏 
	system("cls");
	//直到栈为空 
	while(!ppath.empty()){
		c = ppath.top();
		ppath.pop();
		maze[c.x1][c.y1] = shorts;
		gotoxy(0,0); 
		printmaze();
		Sleep(300);
	}
}
//位置获取函数 
void gotoxy(int x,int y){
       COORD pos;
       pos.X=x;
       pos.Y=y;
       SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}

 

  • 9
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值