项目简介:
经典迷宫求解问题:迷宫是二维的,有一个入口和一个出口;从入口到出口找到一条路径(不保证是最短路径,也不保证是唯一路径);迷宫是没有回路。
项目思想:
利用“栈”的、深度优先的、回溯算法
若当前位置“可通”,则纳入路径,继续前进;
若当前位置“不可通”,则后退,换方向继续探索;(顺时针:东南西北对应着右下左上)
若四周“均无通路”,则将当前位置从路径中删除出去。
求解思想:回溯法(从入口出发,按某一方向向未走过的前方探索。若能走通,则到达新点,否则试探下一方向 ; 若所有的方向均没有通路,则沿原路返回前一点,换下一个方向再继续试探,直到所有可能的通路都探索到,或找到一条通路,或无路可走又返回到入口点。)
算法流程图:
函数调用关系图:
实现代码:
#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;
}