【完成题目3】迷宫求解【问题描述】以一个m*n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。
设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。
【基本要求】首先实现一个栈类型,然后编写一个求解迷宫的非递归程序。
求得的通路以三元组(i,j,d)的形式输出,其中(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。
【算法设计】本实验的目的是设计一个程序,实现手动或者自动生成一个n×m矩阵的迷宫,寻找一条从入口点到出口点的通路。
我们将其简化成具体实验内容如下:选择手动或者自动生成一个n×m的迷宫,将迷宫的左上角作入口,右下角作出口,设“0”为通路,“1”为障碍,即无法穿越。
假设从起点出发,目的为右下角终点,可向“上、下、左、右、左上、左下、右上、右下”8个方向行走。
如果迷宫可以走通,则用“■”代表“1”,用“□”代表“0”,用“→”代表行走迷宫的路径。
输出迷宫原型图、迷宫路线图以及迷宫行走路径。
如果迷宫为死迷宫,输出信息。
可以二维数组存储迷宫数据,用户指定入口下标和出口下标。
为处理方便起见,可在迷宫的四周加一圈障碍。
对于迷宫中任一位置,均可约定有东、南、西、北四个方向可通。
本程序包含三个模块1)主程序模块:void main(){初始化;do {接受命令;处理命令;} while (命令! = 退出);}2)栈模块——实现栈抽象数据类型;3)迷宫模块——实现迷宫抽象数据类型。
【源代码】#include<stdlib.h> //库中包含system("pause")和rand()函数#include<stdio.h> //c语言里的库#include<iostream>#include <malloc.h>#define OK 1#define ERROR 0#define STACK_INIT_SIZE 100#define STACKINCREMENT 10#define OVERFLOW -1#define M 49#define N 49using namespace std;int maze[M][N];typedef int Status;typedef struct{int m,n,direc;}MazeType,*LMazeType;typedef struct{LMazeType top;LMazeType base;int stacksize;int over;}Stack;void Init_hand_Maze(int maze[M][N],int m,int n){int i,j;for(i=1;i<=m+1;i++)for(j=1;j<=n+1;j++){maze[i][j]=1;}cout<<"请按行输入迷宫,0表示通路,1表示障碍:"<<endl;for(i=1;i<m+1;i++)for(j=1;j<n+1;j++)cin>>maze[i][j];for(i=1;i<m+1;i++){for(j=1;j<n+1;j++){if(maze[i][j]!=0&&maze[i][j]!=1){cout<<" 您输入有误,请重新输入";Init_hand_Maze(maze,m,n);}}}}void Init_automatic_Maze(int maze[M][N],int m,int n) //自动生成迷宫int i,j;cout<<"\n迷宫生成中……\n\n";system("pause");for(i=1;i<m+1;i++)for(j=1;j<n+1;j++)maze[i][j]=rand()%2; //随机生成0、1}void PrintMaze(int maze[M][N],int row,int col){int i,j;cout<<"迷宫如图所示."<<endl;for(i=1;i<row+1;i++){for(j=1;j<col+1;j++){if(maze[i][j]==1)cout<<"■";elsecout<<"□";}cout<<endl;}}Status InitStack(Stack &S){S.base=(LMazeType)malloc(STACK_INIT_SIZE * sizeof(MazeType));if(!S.base)exit(OVERFLOW);S.top=S.base;S.stacksize=STACK_INIT_SIZE;S.over=0;return OK;}Status Push(Stack &S,MazeType e){if(S.top-S.base>=S.stacksize){S.base=(LMazeType)realloc(S.base,(S.stacksize+STACKINCREMENT) * sizeof(MazeType)); if(!S.base)exit(OVERFLOW);S.top=S.base+S.stacksize;S.stacksize+=STACKINCREMENT;}*S.top++=e;return OK;Status Pop(Stack &S,MazeType &e){if(S.top==S.base)return ERROR;e=*--S.top;return OK;}Status MazePath(Stack &S,MazeType &e,int maze[M][N],int m,int n) {do{if(maze[e.m][e.n]==0)//0可通,1不可通,2为已走过{Push(S,e);maze[e.m][e.n]=2;if(e.m==m&&e.n==n){S.over=1;//表示存满一条路径return OK;}else {e.n++;e.direc=0;//来这一点时的方向,0右1下2左3上MazePath(S,e,maze,m,n);}}else{if(S.top!=S.base&&S.over!=1){switch(e.direc) //回到上一位置并同时改变方向走下一步 {case 0:e.n--;e.m++;e.direc=1;break;case 1:e.m--;e.n--;e.direc=2;break;case 2:e.n++;e.direc=3;break;case 3:Pop(S,e);break;}}}}while(S.top!=S.base&&S.over!=1);return OK;}int PrintPath(Stack S,int maze[M][N],int row,int col){if(S.top==S.base){cout<<"\n===============================================\n"; cout<<"此迷宫无解\n\n";return ERROR;}MazeType e;while(S.top!=S.base){Pop(S,e);maze[e.m][e.n]=(e.direc+10);}cout<<"完成!"<<endl;cout<<"\n===============================================\n";cout<<"路径为:"<<endl;int i,j;for(i=1;i<row+1;i++){for(j=1;j<col+1;j++){switch(maze[i][j]){case 0:cout<<"□";break;case 1:cout<<"■";break;case 2:break;case 10:cout<<"→";break;case 11:cout<<"↓";break;case 12:cout<<"←";break;case 13:cout<<"↑";break;}}cout<<endl;}cout<<"入口"<<endl;cout<<"完成!"<<endl;return OK;}int main(){int i,m,n,maze[M][N],cycle=0;while(cycle!=(-1)){cout<<"********************************************************************************\n"; cout<<" 欢迎进入迷宫求解系统\n";cout<<endl;cout<<"********************************************************************************\n"; cout<<" ☆ 1 手动生成迷宫☆\n";cout<<" ☆ 2 自动生成迷宫☆\n";cout<<" ☆ 3 退出☆\n\n";cout<<"********************************************************************************\n"; cout<<"\n";cout<<"请选择你的操作:\n";cin>>i;switch(i){case 1:cout<<"\n请输入行数:";cin>>m;cout<<"\n";cout<<"请输入列数:";cin>>n;while((m<1||m>49)||(n<1||n>49)){cout<<"\n抱歉,你输入的行列数超出预设范围(1-49,1-49),请重新输入:\n\n";cout<<"\n请输入行数:";cin>>m;cout<<"\n";cout<<"请输入列数:";cin>>n;}Init_hand_Maze(maze,m,n);PrintMaze(maze,m,n);MazeType start,end;cout<<"请输入起点m n:"<<endl;cin>>start.m>>start.n;start.direc=0;cout<<"请输入终点m n:"<<endl;cin>>end.m>>end.n;Stack S;cout<<"寻找路径..."<<endl;InitStack(S);MazePath(S,start,maze,end.m,end.n);PrintPath(S,maze,m,n);system("pause");cout<<"\n\nPress Enter Contiue!\n";getchar();while(getchar()!='\n'); //接受一个输入,当为回车时执行break跳出,否则一直执行接受数据break;case 2:cout<<"\n请输入行数:";cin>>m;cout<<"\n";cout<<"请输入列数:";cin>>n;while((m<0||m>49)||(n<0||n>49)){cout<<"\n抱歉,你输入的行列数超出预设范围(0-49,0-49),请重新输入:\n\n";cout<<"\n请输入行数:";cin>>m;cout<<"\n";cout<<"请输入列数:";cin>>n;}Init_automatic_Maze(maze,m,n);PrintMaze(maze,m,n);cout<<"请输入起点m n:"<<endl;cin>>start.m>>start.n;start.direc=0;cout<<"请输入终点m n:"<<endl;cin>>end.m>>end.n;cout<<"寻找路径..."<<endl;InitStack(S);MazePath(S,start,maze,end.m,end.n); PrintPath(S,maze,m,n);system("pause");cout<<"\n\nPress Enter Contiue!\n";getchar();while(getchar()!='\n');break;case 3:cycle=(-1);break;default:cout<<"\n";cout<<"你的输入有误!\n"; cout<<"\nPress Enter Contiue!\n";getchar();while(getchar()!='\n');break;}}}【结果截图】迷宫无解的情况手动生成迷宫的情况11 /11自动生成迷宫的情况 【收获及体会】1. 本次实验核心算法明晰,思路明确,易于实现。