1. 程式人生 > >【資料結構】棧 實現迷宮演算法

【資料結構】棧 實現迷宮演算法

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
using namespace std;
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define TURE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define MAZE_X 20
#define MAZE_Y 20
typedef int Status;
typedef struct{
 int x;
 int y;
}PosType;//座標位置
typedef struct{
  int maze[MAZE_X][MAZE_Y];//迷宮地圖
  PosType size;//實際的迷宮長、寬
  PosType start;//起點的座標
  PosType end;//重點的座標
}MazeType;
typedef struct{
 int ord; //通道塊在路徑上的序號;
 PosType seat;
 int di ;//通道塊走向下一個通道塊的方向
}SElemType;// 棧的元素型別
typedef struct{
  SElemType* base;
  SElemType* top;
  int stacksize;
}SqStack;
int InitStack(SqStack &s){
 //構造一個空棧
 s.base = (SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
 if(!s.base) exit(OVERFLOW);
 s.top=s.base;
 s.stacksize=STACK_INIT_SIZE;
 return OK;
}
int GetTop(SqStack s,SElemType &sElem){
    //如果棧不空,用sElem返回s的棧頂元素,並返回OK
    if(s.top==s.base) return ERROR;
    sElem = *(s.top-1);
    return OK;

}
int Push(SqStack &s,SElemType sElem){
  //插入sElem元素為新的棧頂元素
  if(s.top-s.base>=s.stacksize){
    //棧滿,追加儲存空間
    s.base = (SElemType*) realloc(s.base,(s.stacksize+STACKINCREMENT)*sizeof(SElemType));
    if(!s.base) return OVERFLOW;
    s.top = s.base+s.stacksize;//重新使top指向棧頂
    s.stacksize+=STACKINCREMENT;
  }
  *s.top=sElem;
  s.top++;
  return OK;

}
int Pop(SqStack &s,SElemType &sElem){
   //出棧操作
   //若棧不空,則刪除棧頂元素,並用sElem返回其值
   //失敗返回ERROR,成功返回OK
   if(s.base==s.top) return ERROR;
   sElem=*(--s.top);
   return OK;
}
int StackLength(SqStack s){//向下方向:1
  //返回棧的元素個數,即棧的長度
  return s.top-s.base;
}
int StackEmpty(SqStack s){
     if(StackLength(s)==0) return TURE;
     else return FALSE;
}
int FootPrint(MazeType &m,PosType seat){//留下走過的標記
    m.maze[seat.x][seat.y]=2;//將走過的位置標記為2
    return TURE;
}
int MazeInit(MazeType &m){ // 初始化迷宮
    int x,y;
    printf("輸入迷宮的長和寬(不超過%d): ",MAZE_X);
    scanf("%d%d",&x,&y);//迷宮的實際長寬
    if(x>MAZE_X||x<0||y>MAZE_Y||y<0){
        printf("x,y範圍不合法");
        return ERROR;}
    printf("\n請輸入%d * %d 的迷宮,1代表通路,0代表牆\n",x,y);
    for(int i=0;i<x;i++){
        for(int j=0;j<y;j++){
            scanf("%d",&m.maze[i][j]);//初始化迷宮
        }
    }
    printf("\n請輸入起點座標:");
    scanf("%d%d",&(m.start.x),&(m.start.y));//設定起點
    printf("\n請輸入終點座標: ");
    scanf("%d%d",&(m.end.x),&(m.end.y));// 重點
    m.size.x=x;m.size.y=y;
    return OK;
}
int NextPos(MazeType m,SElemType &e,SqStack &s){//看上下左右方向是否可以走, 並且用 e 返回下一個通道的座標
    //向下方向:1 
    //向右方向:2 
    //向上方向:3
    //向左方向:4
     if(e.seat.x<MAZE_X-1&&m.maze[e.seat.x+1][e.seat.y]==1){//如果可以向下走
            (s.top-1)->di=1;//告訴棧頂元素下一個元素的位置
            e.seat.x++;//向下走
            return TURE;}
     if(e.seat.y<MAZE_Y-1&&m.maze[e.seat.x][e.seat.y+1]==1){//向右
            (s.top-1)->di=2;
            e.seat.y++;
            return TURE;}
     if(e.seat.x>0&&m.maze[e.seat.x-1][e.seat.y]==1){// 向上
            (s.top-1)->di=3;
            e.seat.x--;
            return TURE;}
     if(e.seat.y>0&&m.maze[e.seat.x][e.seat.y-1]==1){ //向左
            (s.top-1)->di=4;
            e.seat.y--;
            return TURE;}
     return FALSE; //如果都不滿足,說明當前通道是死路
     }
int MazePath(MazeType &maze , SqStack &s){
    InitStack(s);//構建一個空棧
    SElemType e;
    e.seat.x = maze.start.x; //獲得初始座標
    e.seat.y = maze.start.y;
    e.ord=1; 
       Push(s,e);
       FootPrint(maze,e.seat);
    do{
        if(NextPos(maze,e,s)){ //當前路徑可以繼續往下走,e 返回下一個路徑的座標
            e.ord=s.top-s.base+1;//當前步數
            Push(s,e);// 將下一個路徑作為當前路徑
            FootPrint(maze,e.seat);//留下痕跡
            if((e.seat.x==maze.end.x)&&(e.seat.y==maze.end.y)) return TURE;//如果到達終點,則停止
        }else{//當前路徑不能往下走,死路
              Pop(s,e);//後退一步
              GetTop(s,e);//把後一步當作當前路徑
        }

    }while(!StackEmpty(s)); //如果棧不為空,說明還有通道可以走
    return FALSE;
}
void visitmaze(MazeType m){ //檢視走過後的迷宮
   for(int i=0;i<m.size.x;i++){
        printf("\n");
    for(int j=0;j<m.size.y;j++){
        printf("%d ",m.maze[i][j]);
    }
   }
}
int StackTraverse(SqStack s){
  SElemType* p=s.base;

  for(;p<s.top;p++){
  printf("第%d步 當前座標:(%d,%d) 下一方向:%d \n",p->ord,(p->seat.x),(p->seat.y),p->di);
  }

}
int main()
{
    MazeType maze;
    SqStack s;
    MazeInit(maze);
    int i=MazePath(maze,s);
    printf("%d",i);
    visitmaze(maze);
    printf("\n");
    StackTraverse(s);
}