C/C++ 小程序:迷宫求解

项目简介:

    经典迷宫求解问题:迷宫是二维的,有一个入口和一个出口;从入口到出口找到一条路径(不保证是最短路径,也不保证是唯一路径);迷宫是没有回路。

项目思想:

    利用“栈”的、深度优先的、回溯算法
    若当前位置“可通”,则纳入路径,继续前进;
    若当前位置“不可通”,则后退,换方向继续探索;(顺时针:东南西北对应着右下左上)
    若四周“均无通路”,则将当前位置从路径中删除出去。
    求解思想:回溯法(从入口出发,按某一方向向未走过的前方探索。若能走通,则到达新点,否则试探下一方向 ; 若所有的方向均没有通路,则沿原路返回前一点,换下一个方向再继续试探,直到所有可能的通路都探索到,或找到一条通路,或无路可走又返回到入口点。)

算法流程图:

在这里插入图片描述

函数调用关系图:

在这里插入图片描述

实现代码:

#include<bits/stdc++.h>
using namespace std;

/*----------------全局变量-------------------*/
char maze6[6][6]= {      //6×6的迷宫
	//0,  1,  2,  3,  4,  5
	{'#','#','#','#','#','#'},  //0
	{'#','_','_','_','_','#'},  //1
	{'#','_','#','_','_','#'},  //2
	{'#','_','#','#','_','#'},  //3
	{'#','#','_','_','_','#'},  //4
	{'#','#','#','#','#','#'}   //5
};

char maze8[8][8]= {      //8×8的迷宫
	//0,  1,  2,  3,  4,  5,  6,  7
	{'#','#','#','#','#','#','#','#'},  //0
	{'#','_','#','_','#','_','#','#'},  //1
	{'#','_','_','_','_','_','_','#'},  //2
	{'#','_','#','_','_','_','#','#'},  //3
	{'#','#','_','_','#','_','_','#'},  //4
	{'#','_','_','_','#','_','_','#'},  //5
	{'#','#','#','_','_','_','#','#'},  //6
	{'#','#','#','#','#','#','#','#'}   //7
};

char maze10[10][10]= {      //10×10的迷宫
	//0,  1,  2,  3,  4,  5,  6,  7,  8,  9
	{'#','#','#','#','#','#','#','#','#','#'},  //0
	{'#','_','_','#','_','_','_','#','_','#'},  //1
	{'#','_','_','#','_','_','_','#','_','#'},  //2
	{'#','_','_','_','_','#','#','_','_','#'},  //3
	{'#','_','#','#','#','_','_','_','_','#'},  //4
	{'#','_','_','_','#','_','_','_','_','#'},  //5
	{'#','_','#','_','_','_','#','_','_','#'},  //6
	{'#','_','#','#','#','_','#','#','_','#'},  //7
	{'#','#','_','_','_','_','_','_','_','#'},  //8
	{'#','#','#','#','#','#','#','#','#','#'}   //9
};

/*----------------结构体-------------------*/
//坐标位置
typedef struct {
	int row;      //行
	int col;      //列
} XY;

//路径上的通道块
typedef struct {
	int no;           //该通道块在路径上的序号
	XY  seat;         //该通道块所在的坐标位置
	int dir;          //当前的前进方向(东为1,南为2,西为3,北为4)
} block;


/*----------------生成迷宫函数-------------------*/
/*void Make_maze(int p){
	switch(p){
		case 9:
	}
} */


/*----------------打印迷宫函数-------------------*/
void Print_maze(int jie) {
	switch(jie) {
		case 6:
			for(int i=0; i<6; i++) {
				for(int j=0; j<6; j++) {
					cout<<" "<<maze6[i][j];
				}
				cout<<endl;
			}
			break;
		case 8:
			for(int i=0; i<8; i++) {
				for(int j=0; j<8; j++) {
					cout<<" "<<maze8[i][j];
				}
				cout<<endl;
			}
			break;
		case 10:
			for(int i=0; i<10; i++) {
				for(int j=0; j<10; j++) {
					cout<<" "<<maze10[i][j];
				}
				cout<<endl;
			}
			break;
	}
}

/*----------------判断当前位置是否可以通过的函数-------------------*/
bool Can_pass(XY cp,int j) {
	switch(j) {
		case 6:
			if(maze6[cp.row][cp.col]=='_')  return true;
			else return false;
			break;
		case 8:
			if(maze8[cp.row][cp.col]=='_')  return true;
			else return false;
			break;
		case 10:
			if(maze10[cp.row][cp.col]=='_')  return true;
			else return false;
			break;
	}
}

/*----------------标记是路径上的位置块函数-------------------*/
void Make_csign(XY cp,int cs,int j) {
	switch(j) {
		case 6:
			maze6[cp.row][cp.col]='*';
			break;
		case 8:
			maze8[cp.row][cp.col]='*';
			break;
		case 10:
			maze10[cp.row][cp.col]='*';
			break;
	}
}


/*----------------标记是路径上的位置块函数-------------------*/
void Make_nsign(XY seat,int j) {
	switch(j) {
		case 6:
			maze6[seat.row][seat.col]='@';
			break;
		case 8:
			maze8[seat.row][seat.col]='@';
			break;
		case 10:
			maze10[seat.row][seat.col]='@';
			break;
	}
}


/*----------------设置下一位置函数-------------------*/
XY Next_pos(XY cp,int dir) {
	switch(dir) {
		case 1:
			cp.col++;
			break;
		case 2:
			cp.row++;
			break;
		case 3:
			cp.col--;
			break;
		case 4:
			cp.row--;
			break;
	}
	return cp;
}

/*----------------寻找路径函数-------------------*/
bool Find_Path(stack<block> &path,int s1,int s2,int e1,int e2,int j) {
	XY cp;                        //current position:当前位置
	cp.row=s1;
	cp.col=s2;                    //把当前位置设置为起点位置
	int cs;                       //current step:当前步数
	cs=1;                         //探索第一步
	do {
		if(Can_pass(cp,j)) {      //如果当前位置可以通过,即该位置是路径块并且从未走到过
			Make_csign(cp,cs,j);  //标记cp位置为路径上的一块
			block b;
			b.no=cs;
			b.dir=1;
			b.seat=cp;
			path.push(b);       //将当前位置加入路径
			if(cp.row==e1&&cp.col==e2)  return true;   //如果当前位置是终点,则直接返回true,表示已经找到从起点到终点的路径
			cp=Next_pos(cp,1);  //把当前块的东邻块作为当前位置
			cs++;
		} else {                //如果当前位置不能通过
			if(path.empty()==false) {  //如果路径栈不为空
				block b;
				b=path.top();
				path.pop();    //弹出栈顶元素
				while((b.dir==4)&&(path.empty()==false)) {
					Make_nsign(b.seat,j);       //将该位置标记为已经走过但不能通过
					b=path.top();               //往回退一步
					path.pop();
				}
				if(b.dir<4) {                   //如果当前块还有其他方向没有尝试
					b.dir++;
					path.push(b);               //换下一个方向探索
					cp=Next_pos(b.seat,b.dir);  //设定当前位置是该方向上的相邻块
				}
			}
		}
	} while(path.empty()==false) ;
	return false;
}


/*----------------主函数-------------------*/
int main() {
	int flag=1;
	while(flag==1) {
		cout<<"请选择迷宫的阶数(6、8、10):";
		int j;
		cin>>j;
		while(j!=6&&j!=8&&j!=10) {
			cout<<"请您输入正确的数字!(6、8、10):";
			cin>>j;
		}
		cout<<"初始迷宫如下图所示(#代表墙,_代表路):"<<endl<<endl;
		Print_maze(j);
		stack<block> path;         //初始化路径栈
		int s1,s2,e1,e2;          //(s1,s2)是起点位置  (e1,e2)是终点位置
		cout<<"\n"<<"请输入起点位置(例:1,1 ):";
		scanf("%d",&s1);
		getchar();
		scanf("%d",&s2);
		cout<<"请输入终点位置(例:8,8 ):";
		scanf("%d",&e1);
		getchar();
		scanf("%d",&e2);
		cout<<"\n"<<"起点位置是("<<s1<<","<<s2<<"),终点位置是("<<e1<<","<<e2<<")。"<<endl;
		int i=1;
		stack<block> path2;
		if(Find_Path(path,s1,s2,e1,e2,j)) {
			while(path.empty()==false) {
				path2.push(path.top());
				path.pop();
			}
			while(path2.empty()==false) {
				block b=path2.top();
				cout<<"step"<<i<<":("<<b.seat.row<<","<<b.seat.col<<")"<<endl;
				path2.pop();
				i++;
			}
			cout<<"走出迷宫的路线如下图所示(*代表路径,@代表走过但不能不同的位置):"<<endl<<endl;
			Print_maze(j);
		} else {
			cout<<"没有找到能够走出迷宫的通路!";
		}
		cout<<"\n请问您是否需要再来一次?(1:再来一次  0:结束程序):";
		int f;
		cin>>f;
		while(f!=1&&f!=0) {
			cout<<"请您输入正确的数字!(1:再来一次  0:结束程序):";
			cin>>f;
		}
		if(f==0) flag=0;
	}
	return 0;
}

本期分享到这里就结束啦,大家如果对小编的代码有疑问或者想要小编做其他的程序,都欢迎来私信小编呀!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值