迷宫问题
来源:互联网 发布:淘宝连衣裙女装 编辑:程序博客网 时间:2024/05/02 02:46
【问题描述】 以一个m×n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。 【基本要求】 首先实现一个以链表作存储结构的栈类型,然后编写一个求解迷宫的非递归程序;求得的通路以三元组(i,j,d)的形式输出,其中:(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。如:对于下列数据的迷宫,输出的一条通路为:(1,1,1),(1,2,2),(2,2,2),(3,2,3),(3,1,2),…。 【测试数据】 迷宫的测试数据如下:左上角(1,1)为入口右下角(8,9)为出口。 【实现提示】 计算机解迷宫通常用的是“穷举求解”方法,即从入口出发,顺着某一个方向进行探索,若能走通,则继续往前进;否则沿着原路退回,换一个方向继续探索,直至出口位置,求得一条通路。假如所有可能的通路都探索到而未能到达出口,则所设定的迷宫没有通路。 可以二维数组存储迷宫数据,通常设定入口点的下标为(1,1),出口点的下标为(n,n)。为处理方便起见,可在迷宫的四周加一圈障碍。对于迷宫中任一位置,均可约定有东、南、西、北四个方向可通。 【选作内容】 (1)编写递归形式的算法,求得迷宫中所有可能的通路; (2)以方阵形式输出迷宫及其通路。 一、 求解迷宫一条路径的伪代码: 设定当前位置的初始值为入口位置; Do{ 若当前位置可通则{ 若该位置为出口位置则结束; 否则切换当前位置的东邻方块为新的当前位置;} 否则若栈不空且栈顶位置尚有其他方向未被探索, 则设新的当前位置为沿顺时针方向旋转找到的栈顶位置的下一相邻块; 若栈不空但栈顶位置的四周均不通, 则{删去栈顶位置; 若栈不空,则重新测试新的栈顶位置, 直至找到一个可通的相邻块或出栈至栈空;}}}while(栈不空); {栈空说明没有路径存在}
将当前位置插入栈顶;
二、程序代码:
#include <stdio.h>
#include <malloc.h>
#include <conio.h>
#define NULL 0
int m=0; /*迷宫的行数*/
int n=0; /*迷宫的列数*/
typedef struct locality /*描述迷宫当前位置和方向*/
{
int x;
int y;
int direction; /*0:无效,1:左,2:下,3:右,4:上*/
}lo;
typedef struct LinkNode /*链表结构,用于栈的元素类型*/
{
lo locality;
struct LinkNode *next;
}LinkNode;
typedef struct stack /*链式栈,用于存储迷宫路径信息*/
{
LinkNode *top; /*头指针*/
}Stack;
void InitStack(Stack *s) /*栈置空*/
{
s->top=NULL;
}
void Push(Stack *s,lo p) /*数据入栈*/
{
LinkNode *Labyrinth=(LinkNode *)malloc(sizeof(LinkNode));
Labyrinth->locality=p;
Labyrinth->next=s->top;
s->top=Labyrinth;
}
lo Pop(Stack *s) /*栈顶元素出栈*/
{
lo locality;
LinkNode *Labyrinth;
Labyrinth=s->top;
s->top=s->top->next;
locality=Labyrinth->locality;
delete Labyrinth;
return locality;
}
lo GetPop(Stack s) /*读取栈顶元素*/
{
return s.top->locality;
}
int Empty(Stack s) /*判空*/
{
if(s.top==NULL)
return 1;
else
return 0;
}
int **InitMaze() /*返回迷宫的二维指针*/
{
int **maze=NULL;
int i,j;
printf("Please input the maze's row and line:/n");
scanf("%d,%d",&m,&n); /*输入迷宫的行和列*/
maze=(int **)malloc((m+2)*sizeof(int *));
for(i=0;i<m+2;i++)
{
maze[i]=(int *)malloc(sizeof(int)*(n+2));
}
printf("Please input the labyrinth:/n"); /*输入迷宫,1代表路障,0代表通行*/
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
scanf("%d",&maze[i][j]);
for(i=0;i<n+2;i++) /*将迷宫的四周都变为1*/
maze[0][i]=1;
for(i=0;i<n+2;i++)
maze[m+1][i]=1;
for(i=0;i<m+2;i++)
maze[i][0]=1;
for(i=0;i<m+2;i++)
maze[i][n+1]=1;
printf("Output the labyrinth:/n");
for(i=0;i<m+2;i++) /*输出迷宫*/
{
for(j=0;j<n+2;j++)
printf("%3d",maze[i][j]);
printf("/n");
}
return maze;
}
void PrintWay(Stack p) /*输出路径*/
{int k,i;
lo locality;
Stack t; /*临时栈,用于存储从入口到出口的路径*/
LinkNode *temp;
int a,b;
int s[100][3];
k=0;
InitStack(&t);
temp=(LinkNode *)malloc(sizeof(LinkNode));
temp->locality=Pop(&p); /*取栈顶元素,即出口*/
Push(&t,temp->locality); /*入栈*/
free(temp);
while(!Empty(p))
{
temp=(LinkNode *)malloc(sizeof(LinkNode));
temp->locality=Pop(&p); /*获取下一个元素*/
a=GetPop(t).x-temp->locality.x; /*左:a=0,b=1; 下:a=1,b=0*/
b=GetPop(t).y-temp->locality.y; /*右:a=0,b=-1 上:a=-1,b=0;*/
if(b==1)
temp->locality.direction=1;
else if(a==1)
temp->locality.direction=2;
else if(b==-1)
temp->locality.direction=3;
else if(a==-1)
temp->locality.direction=4;
Push(&t,temp->locality); /*新位置入栈*/
free(temp);
}
printf("there is a way to the destination!/n");
printf("The way of maze is:/n");
while(!Empty(t)) /*输出路径*/
{locality=Pop(&t);
s[k][0]=locality.x;
s[k][1]=locality.y;
s[k][2]=locality.direction;
k++;}
for(i=0;i<k;i++)
printf("第%3d步:(%3d,%3d) 方向:%3d/n",i+1,s[i][0],s[i][1],s[i][2]);
}
int FindMaze(int **maze,int i,int j) /*寻找路径,找到返回1,没找到返回0*/
{
Stack p,q; /*栈p,q分别表示探索迷宫的路径和过程*/
lo temp1,temp2;
int a,b;
InitStack(&p);
InitStack(&q);
temp1.x=1;
temp1.y=1; //
maze[1][1]=-1; /*标记已经走过*/
Push(&p,temp1);
Push(&q,temp1);
while(!Empty(q))
{
temp2=GetPop(q);
if(!(GetPop(p).x==GetPop(q).x
&&GetPop(p).y==GetPop(q).y))
Push(&p,temp2); /*若有新元素入栈,就把q的栈顶元素存入p中*/
a=temp2.x;
b=temp2.y+1; /*当前位置左方向相邻的方块*/
if(maze[a][b]==0)
{
temp1.x=a;
temp1.y=b;
maze[a][b]=-1; /*标记已走过*/
Push(&q,temp1);
}
if(a==i&&b==j) /*到达出口*/
{
temp1.direction=0;
Push(&p,temp1);
PrintWay(p);
return 1;
}
a=temp2.x+1;
b=temp2.y; /*当前位置下方向相邻的方块*/
if(maze[a][b]==0)
{
temp1.x=a;
temp1.y=b;
maze[a][b]=-1; /*标记已走过*/
Push(&q,temp1);
}
if(a==i&&b==j) /*到达出口*/
{
temp1.direction=0;
Push(&p,temp1);
PrintWay(p);
return 1;
}
a=temp2.x;
b=temp2.y-1; /*当前位置右方向相邻的方块*/
if(maze[a][b]==0)
{
temp1.x=a;
temp1.y=b;
maze[a][b]=-1; /*标记已走过*/
Push(&q,temp1);
}
if(a==i&&b==j) /*到达出口*/
{
temp1.direction=0;
Push(&p,temp1);
PrintWay(p);
return 1;
}
a=temp2.x-1;
b=temp2.y; /*当前位置上方向相邻的方块*/
if(maze[a][b]==0)
{
temp1.x=a;
temp1.y=b;
maze[a][b]=-1; /*标记已走过*/
Push(&q,temp1);
}
if(a==i&&b==j) /*到达出口*/
{
temp1.direction=0;
Push(&p,temp1);
PrintWay(p);
return 1;
}
if(GetPop(p).x==GetPop(q).x
&&GetPop(p).y==GetPop(q).y) /*若四个方向都走不通,则数据出栈,退回一格*/
{
Pop(&p);
Pop(&q);
}
}
return 0; /*探索迷宫失败*/
}
void main()
{
printf("1表示向左,2表示向下,3表示向右,4表示向上,0表示无方向/n");
int **maze=InitMaze(); /*初始化迷宫*/
if(!FindMaze(maze,m,n)) /*探索路径*/
printf("Can not find a way!/n");
}