转自:http://blog.csdn.net/qq352773277/article/details/8209513
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define M 20
#define N 20
#define visited 2
#define TRUE 1
#define FALSE 0
#define INITSIZE 100
typedef int Status;
typedef struct{ //坐标点结构体
int y; //每个可通的行坐标
int x; //每个可通的列坐标
}PosType;
typedef struct{
int ord; //通道块在路径上的"序号"
int di; //从此通道块走向下一通道块的"方向"
PosType seat; //通道块在迷宫中的"坐标位置"
}MazeNode; //迷宫节点
typedef struct {
MazeNode base[INITSIZE];
int top; //栈顶指针
}Stack;
typedef struct{ //用于存储迷宫的路径
PosType coor[INITSIZE];
int top;
}Postion;
void RandMatrix(); //随机生成迷宫
int InitStack(Stack *); //初始化栈
int InitStack1(Postion *);
int StackEmpty(Stack *); //判断栈是否为空
int StackEmpty1(Postion *);
int StackIsFull(Stack *); //判断栈是否满了
int StackIsFull1(Postion *); //判断栈是否满了
int Push(Stack *s,MazeNode m); //压栈
int Push1(Postion *,PosType);
int Pop(Stack *s,MazeNode *m); //出栈
int Pop1(Postion *,PosType *);
int DestroyStack(Stack *s); //撤销栈
int Pass(PosType pos); //判断指定坐标是否可通过
int FootPrint(PosType pos); //标记能通过的
PosType NextCoord(PosType pos,int i); //获取下一位置
int MarkPrint(PosType pos); //留下不能通过的标记,并退回一步
int MazePath(PosType start,PosType end,Postion *); //从迷宫的入口到出口查找
void PrintMaze(Postion *); //输出迷宫
int mg[M][N]; //生成一个M*N 的迷宫
int main()
{
int h=1;
PosType start,end;
Postion P;
while(h)
{
printf("创建迷宫\n");
InitStack1(&P);
RandMatrix();
printf("\n");
printf("1、重新生成迷宫,0、就这个:");
scanf("%d",&h);
}
do //输入迷宫入口坐标
{
printf("\n输入迷宫入口坐标");
scanf("%d%d",&start.x,&start.y);
if(start.x>N || start.y>M)
{
printf("输入的坐标越界,请重新输入!\n");
continue;
}
}while(start.x>N || start.y>M);
do //输入迷宫出口坐标
{
printf("\n输入迷宫出口坐标:");
scanf("%d%d",&end.x,&end.y);
if(end.x>N || end.y>M)
{
printf("输入的坐标越界,请重新输入!\n");
continue;
}
}while(end.x>N || end.y>M);
if(!MazePath(start,end,&P)) //调用函数查找路径
{
printf("\n无法通过!\n");
}
else
{
PrintMaze(&P); //打印找到的路径
}
system("pause");
return 0;
}
int InitStack(Stack *s)
{
s->top=-1;
return 1;
}
int InitStack1(Postion *s)
{
s->top=-1;
return 1;
}
int StackEmpty(Stack *s)
{
if(s->top==-1)
return 1;
return 0;
}
int StackEmpty1(Postion *s)
{
if(s->top==-1)
return 1;
return 0;
}
int StackIsFull(Stack *s)
{
if(s->top==INITSIZE-1)
return 1;
else
return 0;
}
int StackIsFull1(Postion *s)
{
if(s->top==INITSIZE-1)
return 1;
else
return 0;
}
int Push(Stack *s,MazeNode m)
{
if(!StackIsFull(s))
{
s->top++;
s->base[s->top]=m;
}
return 1;
}
int Push1(Postion *s,PosType m)
{
if(!StackIsFull1(s))
{
s->top++;
s->coor[s->top]=m;
}
return 1;
}
int Pop(Stack *s,MazeNode *m)
{
if(s->top!=-1)
{
*m=s->base[s->top];
s->top--;
return 1;
}
return 1;
}
int Pop1(Postion *s,PosType *m)
{
if(s->top!=-1)
{
*m=s->coor[s->top];
s->top--;
return 1;
}
return 1;
}
int DestroyStack(Stack *s)
{
s->top=-1;
return 1;
}
int Pass(PosType pos) //判断指定坐标是否可通过
{
if(mg[pos.y][pos.x]==0) //可通
return 1;
else
return 0;
}
int FootPrint(PosType pos) //标记能通过的
{
mg[pos.y][pos.x]=2; //2表示可通
return 1;
}
PosType NextCoord(PosType pos,int i) //获取下一位置
{
switch(i) //1,2,3,4,5,6,7,8代表方向顺时针
{
case 1:
pos.x+=1; //向右侧查找
break;
case 2:
pos.x+=1;
pos.y+=1;
break;
case 3:
pos.y+=1;
break;
case 4:
pos.y+=1;
pos.x-=1;
break;
case 5:
pos.x-=1;
break;
case 6:
pos.x-=1;
pos.y-=1;
break;
case 7:
pos.y-=1;
break;
case 8:
pos.y-=1;
pos.x+=1;
break;
default :
exit(0);
}
return pos;
}
int MarkPrint(PosType pos) //留下不能通过的标记,并退回一步
{
mg[pos.y][pos.x]=3; //3表示曾走过,但不通
return 1;
}
void RandMatrix()
{
int i=0,j=0;
srand((unsigned)time(NULL));
for(i=0;i<M;i++)
for(j=0;j<N;j++)
mg[i][j]=rand()%2;
i=0;
for(j=0;j<N;j++)
{
mg[i][j]=1;
mg[j][i]=1;
}
i=N-1;
for(j=0;j<M;j++)
{
mg[j][i]=1;
mg[i][j]=1;
}
mg[1][1]=0;
mg[M-2][N-2]=0;
printf("\n");
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
{
if(mg[i][j]==1) //若是障碍
{
printf("█");
}
else if(mg[i][j]==2) //若是可通路径
{
printf("◎");
}
else if(mg[i][j]==3)
{
printf("☆"); //其他位置
}
else
printf(" ");
}
printf("\n");
}
}
int MazePath(PosType start,PosType end,Postion *P) //从迷宫的入口到出口查找
{
//若迷宫maze中存在从入口start到出口end的通道,则求得一条存放在栈中(从栈底到栈顶)
//并返回TRUE,否则返回FALSE
Stack S; //定义栈
PosType curpos;
int curstep; //当前序号1,2,3,4,5,6,7,8代表方向,1代表向右,后依次顺时针
MazeNode e;
InitStack(&S);
curpos=start; //设定"当前位置"为"入口位置",从入口位置开始查找
curstep=1; //探索第一步
do
{
if(Pass(curpos))
{
//从当前位置可以通过,即是未曾走到过的通道块
FootPrint(curpos); //标记能通过的
e.ord=curstep; //保存步数
e.seat=curpos;
e.di=1; //向右侧探测
Push(&S,e); //加入路径
Push1(P,curpos);
if(curpos.y==end.x && curpos.x==end.y) //若当前位置是出口坐标
{
DestroyStack(&S); //释放栈占用的空间
return 1; //返回查找成功
}
else //与出口坐标不同
{
curpos=NextCoord(curpos,1); //向右侧探测
curstep++; //探索下一步
}
}
else //当前位置不能通过(为障碍或已走过)
{
if(!StackEmpty(&S)) //若栈不为空,之前有走过的位置
{
Pop(&S,&e); //出栈(返回上一步的位置)
Pop1(P,&curpos);
while(e.di==8 && !StackEmpty(&S)) //上一步,四个方向都探测定,且栈不为空
{
MarkPrint(e.seat); //留下不能通过的标记,并退回一步
Pop(&S,&e); //出栈,返回上一步
Pop1(P,&curpos);
}
if(e.di<8)
{
e.di++; //换下一个方向探索,准备探测下一个方向
Push(&S,e); //将当前节点入栈
Push1(P,curpos);
curpos=NextCoord(e.seat,e.di); //设定当前位置是该新方向上的相邻块,查找下一个应该探测的方向
}
}
}
}while(!StackEmpty(&S));
//程序运行到这里,表示没有能通达的路径
DestroyStack(&S); //释放占用的空间
return FALSE; //返回失败
}
void PrintMaze(Postion *P) //输出迷宫
{
int i,j;
PosType e;
Postion W;
InitStack1(&W);
while(!StackEmpty1(P))
{
Pop1(P,&e);
Push1(&W,e);
}
printf("\n可以通过,迷宫路径:\n"); //在这里可以设置迷宫的界面
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
{
if(mg[i][j]==1) //若是障碍
{
printf("█");
}
else if(mg[i][j]==2) //若是可通路径
{
printf("◎");
}
else if(mg[i][j]==3)
{
printf("☆"); //其他位置
}
else
{
printf(" ");
}
}
printf("\n");
}
printf("\n\n");
i=1;
printf("迷宫的最短路径为:");
while(!StackEmpty1(&W))
{
i++;
Pop1(&W,&e);
printf("(%d,%d), ",e.y,e.x);
}
printf("\n\n");
}