#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");
}