课程名称:数据结构与算法
设计题目:迷宫问题
已知技术参数和设计要求:
问题描述:
以一个m*n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。迷宫问题要求求出从入口(1,1)到出口(m,n)的一条通路,或得出没有通路的结论。
基本要求:
首先实现一个以链表作存储结构的栈类型,然后编写一个求迷宫问题的非递归程序,求得的通路以三元组(i,j,d)的形式输出,其中:(i,j)指示迷宫中的一个坐标, d表示走到下一坐标的方向。
测试数据:
迷宫用伪随机数产生程序产生。
左上角(1,1)为入口,右下角(m,n)为出口。
选作内容:
1.编写递归形式的算法,求得迷宫中的所有可能的通路。
2.以方阵的形式输出迷宫及其通路迷宫中的所有可能的通路。
基本思路:
1.创建一个二维数组代表迷宫,另外在创建一个的等大且初值全为“0”的二维数组,用来在寻找通路的函数中记录位置。
2.创建一个栈结构体,用来存储路线(走过的点压进栈,走不通返回则弹栈)。
3.定义上、下、左、右、上左、上右、下左、下右八个遍历方向(如果是四个方向的话非常容易出现死路,且不符合实际)。
代码及相关注释如下:
#include <stdio.h>
#include <stdlib.h>
#include<time.h>
#define size 100
#define M 100
#define N 100
typedef struct
{
int x;//横
int y;//纵
}position;
typedef struct stack
{
int row;//行
int col;//列
int dir;//方向
}date;
typedef struct//定义栈
{
date stack[size] ;
int top;
}tstack;
position direction[8]={{-1,0},{1,0},{0,-1},{0,1},{-1,-1},{-1,1},{1,-1},{1,1}};//八个遍历方向
int sum=0;
int maze[M][N];
int maze_2[M+2][N+2]={0};//等大全为0的数组
int m,n;
void push(tstack*s,date x)//压栈
{
if(s->top==size-1)//从0开始,所以size-1
printf("栈满了");
else
{
s->top++;
s->stack[s->top]=x;//把x赋给top指向的栈顶
}
}
void pop(tstack*s)//弹栈
{
if(s->top==-1)//判断栈顶的值来判断是否为空栈
printf("栈空");
else
{
s->top--;//弹出栈顶元素
}
}
void print_path(int sum,tstack s)
{
int a;
printf("第 %d 条通路:\n",sum);
for(a=0;a<s.top;a++)
printf("(%d,%d,%d)->",s.stack[a].row ,s.stack[a].col,s.stack[a+1].dir );//输出栈里的元素 ,三元坐标
printf("出口\n");
printf("\n");
}
void path(int x,int y,tstack e)//寻找迷宫的通路
{
int i,a,b,c;
date t;//引用结构体date
if(x==m&&y==n)//判断是否到(m,n)出口
{
sum++;
print_path(sum,e);//调用打印迷宫(print_path)函数
}
else
{
for(i=0;i<8;i++)//遍历八个方向
{
a=x+direction[i].x;//判断走向
b=y+direction[i].y;
c=i;
if(!maze[a][b]&&!maze_2[a][b])//可以走的路,相当于if(1&&1)
{
t.row=a;
t.col=b;
t.dir=c;
maze_2[a][b]=maze[a][b]=1;//走过的地方在maze和maze_2中标记为1
push(&e,t);//然后存到栈里面去
path(a,b,e);//在path函数自身调用path函数 ,获得点
maze_2[a][b]=maze[a][b]=0;//将位置清空,表示没有走过的路
pop(&e);//走不通的点,弹栈弹出走不通的点
}
}
}
}
/*主函数部分*/
int main()
{
int a,b;
tstack *s;//初始化栈
s=(tstack *)malloc(sizeof(tstack));
s->stack[0].row =1;
s->stack[0].col=1;
s->top=0;
maze_2[1][1]=maze[1][1]=1;
printf("输入迷宫行数和列数:\n");
scanf("%d %d",&m,&n);
srand((unsigned)time(NULL));//随机迷宫
for(a=0;a<m+2;a++)
{
for(b=0;b<n+2;b++)
{
maze[a][b]=rand()%2;//只有0和1的随机迷宫
if(a==m&&b==n)
{
maze[a][b]=0;//出口设为0
maze[1][1]=0; //入口设为0
}
}
}
for (a = 0; a < n + 2; a++) maze[0][a] = 1;//上 墙 (上下左右的墙用1代表,即为输出中的“#”)
for (a = 0; a < m + 2; a++) maze[a][0] = 1;//左 墙
for (a = 0; a < n + 2; a++) maze[m+ 1][a] = 1;//下 墙
for (a = 0; a < m + 2; a++) maze[a][n + 1] = 1;//右 墙
for (a = 0; a < n; a++) maze[m][a] = 1;
printf("随机迷宫:\n");
for(a=0;a<m+2;a++)
{
for(b=0;b<n+2;b++)
{
if (maze[a][b] == 1)
printf("#");//“#”代表墙
else if(maze[a][b]==0)
printf(" ");//“ ”代表可到到达的地方
}
printf("\n");
}
path(1,1,*s);//调用path函数得到通路
return 0;
}
注意:本代码仅供参考!