迷宫的实现--c语言

来源:互联网 发布:龙神契约升阶数据 编辑:程序博客网 时间:2024/05/21 11:28

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