C语言 迷宫问题求解(顺序栈应用示例)

来源:互联网 发布:java color rgb值 编辑:程序博客网 时间:2024/06/02 03:32
[cpp] view plaincopy
  1. //顺序栈的应用:迷宫  
  2. //作者:nuaazdh  
  3. //时间:2011年12月7日  
  4. #include <stdio.h>  
  5. #include <stdlib.h>  
  6.   
  7. #define OK      1  
  8. #define ERROR   0  
  9. #define TRUE    1  
  10. #define FALSE   0  
  11. #define STACK_INIT_SIZE 100  
  12. #define STACKINCREMENT 10  
  13.   
  14. #define COLUMN 10   //迷宫行数  
  15. #define ROW 10      //迷宫列数  
  16.   
  17. typedef int Status; //函数返回状态  
  18.   
  19. typedef struct{//迷宫类型  
  20.     char **maze;//迷宫数据  
  21.     int **footprint;//足迹数据  
  22.     int row;//行数  
  23.     int column;//列数  
  24. }MazeType;  
  25.   
  26. typedef struct{//迷宫位置坐标  
  27.     int x;  
  28.     int y;  
  29. }PosType;  
  30.   
  31. typedef struct{  
  32.     int ord;//通道块在路劲上的"序号"  
  33.     PosType seat;//通道块在迷宫中的"坐标位置"  
  34.     int di;//从此通信块走向下一通道块的"方向"  
  35. }SElemType;  //栈元素类型  
  36.   
  37. typedef struct{//顺序栈结构定义  
  38.     SElemType *base;  
  39.     SElemType *top;  
  40.     int stacksize;  
  41. }SqStack;  
  42.   
  43. Status InitStack(SqStack *S);  
  44.     //构造一个空栈S  
  45. Status InitMaze(MazeType *M);  
  46.     //初始化迷宫数据  
  47. Status DestroyStack(SqStack *S);  
  48.     //销毁栈S,S不再存在  
  49. Status ClearStack(SqStack *S);  
  50.     //把栈S置为空栈  
  51. Status StackEmpty(SqStack S);  
  52.     //若栈S为空栈,则返回TRUE,否则返回FALSE  
  53. int StackLength(SqStack S);  
  54.     //返回S元素的个数,即栈的长度  
  55. Status GetTop(SqStack S,SElemType *e);  
  56.     //若栈不为空,则用e返回S的栈顶元素,并返回OK;否则返回FALSE  
  57. Status Push(SqStack *S,SElemType e);  
  58.     //插入元素e为新的栈顶元素  
  59. Status Pop(SqStack *S,SElemType *e);  
  60.     //若栈S不为空,则删除S的栈顶元素,用e返回其值,并返回OK,否则返回ERROR  
  61. Status StackTraverse(const SqStack *S);  
  62.     //从栈底到栈顶依次对每个元素进行访问  
  63. Status PrintMaze(MazeType *M);  
  64.     //输出迷宫  
  65. Status MazePath(SqStack *S,MazeType maze,PosType start,PosType end);  
  66.     //若迷宫maze中存在从入口start到出口end的通道,则求得一条存放在栈中(从栈底  
  67.     //到栈顶),并返回TRUE;否则返回FALSE  
  68. Status FootPrint(MazeType *M,PosType pos);  
  69.     //将迷宫的当前位置pos设置为"走过",即footprint该位置为1  
  70. Status Pass(MazeType *M,PosType pos);  
  71.     //判断当前位置是否走过  
  72. SElemType NewSElem(int step,PosType pos,int d);  
  73.     //创建新结点,用step,pos,d初始化该结点  
  74. PosType NextPos(PosType pos,int d);  
  75.     //将位置pos的方向设为d  
  76. Status MarkPrint(MazeType *M,PosType pos);  
  77.     //将迷宫M的pos位置,设为已走,成功返回OK;否则返回ERROR  
  78. Status PrintFoot(MazeType *M,SqStack *S);  
  79.     //输出迷宫的路径  
  80. int main()  
  81. {  
  82.     MazeType maze;//迷宫结构  
  83.     SqStack stack;//顺序栈,存储迷宫路径  
  84.     PosType start,end;//迷宫的起点和终点;  
  85.     start.x=0;start.y=1;//迷宫的起点  
  86.     end.x=8;end.y=9;//迷宫的终点  
  87.     InitMaze(&maze);//迷宫初始化  
  88.     printf("迷宫形状:\n");  
  89.     PrintMaze(&maze);//打印迷宫形状  
  90.     if(TRUE==MazePath(&stack,maze,start,end))  
  91.         printf("迷宫可解.\n");  
  92.     else  
  93.         printf("迷宫不可解.\n");  
  94.     return 0;  
  95. }  
  96.   
  97. Status InitStack(SqStack *S){  
  98.     //构造一个空栈S  
  99.     S->base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));  
  100.     if(!S->base)//分配失败  
  101.     {  
  102.         printf("分配内存失败.\n");  
  103.         exit(0);  
  104.     }  
  105.     S->top=S->base;  
  106.     S->stacksize=STACK_INIT_SIZE;  
  107.     return OK;  
  108. }  
  109.   
  110. Status InitMaze(MazeType *M){  
  111.     //初始化迷宫数据  
  112.     int i,j;  
  113.     char mz[ROW][COLUMN]={  
  114.     '#',' ','#','#','#','#','#','#','#','#',  
  115.     '#',' ',' ','#',' ',' ',' ','#',' ','#',  
  116.     '#',' ',' ','#',' ',' ',' ','#',' ','#',  
  117.     '#',' ',' ',' ',' ','#','#',' ',' ','#',  
  118.     '#',' ','#','#','#',' ',' ',' ',' ','#',  
  119.     '#',' ',' ',' ','#',' ','#',' ','#','#',  
  120.     '#',' ','#',' ',' ',' ','#',' ',' ','#',  
  121.     '#',' ','#','#','#',' ','#','#',' ','#',  
  122.     '#','#',' ',' ',' ',' ',' ',' ',' ',' ',  
  123.     '#','#','#','#','#','#','#','#','#','#'  
  124.     };  
  125.   
  126.     M->maze=(char **)malloc(sizeof(char *)*ROW);  
  127.     M->footprint=(int **)malloc(sizeof(int *)*ROW);  
  128.     if(!M->maze||!M->footprint){  
  129.         printf("申请空间失败,迷宫无法初始化.\n");  
  130.         return ERROR;  
  131.         exit(0);  
  132.     }  
  133.     for(i=0;i<ROW;i++){  
  134.         M->maze[i]=(char *)malloc(sizeof(char)*COLUMN);  
  135.         M->footprint[i]=(int *)malloc(sizeof(int)*COLUMN);  
  136.         if(!M->maze[i]||!M->footprint[i]){  
  137.             printf("申请空间失败,迷宫初始化失败.\n");  
  138.             return ERROR;  
  139.             exit(0);  
  140.         }  
  141.     }  
  142.     for(i=0;i<ROW;i++){  
  143.         for(j=0;j<COLUMN;j++){  
  144.             M->maze[i][j]=mz[i][j];  
  145.             M->footprint[i][j]=0;  
  146.         }  
  147.     }  
  148.     M->row=ROW;//行  
  149.     M->column=COLUMN;//列  
  150.     return OK;  
  151. }  
  152.   
  153. Status DestroyStack(SqStack *S){  
  154.     //销毁栈S,S不再存在  
  155.     if(!S)//S为空  
  156.     {  
  157.         printf("指针为空,释放失败.\n");  
  158.         exit(0);  
  159.     }  
  160.     free(S);  
  161.     return OK;  
  162. }  
  163.   
  164. Status ClearStack(SqStack *S){  
  165.     //把栈S置为空栈  
  166.     if(!S)//S不存在  
  167.         return FALSE;  
  168.     S->top=S->base;//直接将栈顶指针指向栈底  
  169.     return OK;  
  170. }  
  171.   
  172. Status StackEmpty(SqStack S){  
  173.     //若栈S为空栈,则返回TRUE,否则返回FALSE  
  174.     if(S.top==S.base)  
  175.         return TRUE;  
  176.     else  
  177.         return FALSE;  
  178. }  
  179.   
  180. int StackLength(SqStack S){  
  181.     //返回S元素的个数,即栈的长度  
  182.     return S.stacksize;  
  183. }  
  184.   
  185. Status GetTop(SqStack S,SElemType *e){  
  186.     //若栈不为空,则用e返回S的栈顶元素,并返回OK;否则返回FALSE  
  187.     if(S.top==S.base){  
  188.         printf("栈为空.\n");  
  189.         return FALSE;  
  190.     }else{  
  191.         *e=*(S.top-1);  
  192.         printf("栈顶元素:%c\n",*e);  
  193.         return OK;  
  194.     }  
  195. }  
  196.   
  197. Status Push(SqStack *S,SElemType e){  
  198.     //插入元素e为新的栈顶元素  
  199.     if(S->top-S->base>=S->stacksize){//栈已满,追加存储空间  
  200.         S->base=(SElemType *)realloc(S->base,(S->stacksize+STACKINCREMENT)*sizeof(SElemType));  
  201.         if(!S->base)  
  202.         {  
  203.             printf("重新申请空间失败.\n");  
  204.             exit(0);  
  205.         }  
  206.         S->top=S->base+S->stacksize;//更改栈顶指针  
  207.         S->stacksize+=STACKINCREMENT;  
  208.     }  
  209.     *S->top++=e;  
  210.     return OK;  
  211. }  
  212.   
  213. Status Pop(SqStack *S,SElemType *e){  
  214.     //若栈S不为空,则删除S的栈顶元素,用e返回其值,并返回OK,否则返回ERROR  
  215.     if(S->top==S->base){//栈为空  
  216.         printf("栈为空.\n");  
  217.         return ERROR;  
  218.     }  
  219.     *e=*(--S->top);  
  220.     return OK;  
  221. }  
  222.   
  223. Status StackTraverse(const SqStack *S){  
  224.     //从栈底到栈顶依次对每个元素进行访问  
  225.     SElemType *p=S->base;  
  226.     if(S->base==S->top)  
  227.     {  
  228.         printf("栈为空.\n");  
  229.         return FALSE;  
  230.     }  
  231.     printf("栈中元素:");  
  232.     while(p!=S->top)  
  233.     {  
  234.         printf("x=%d,y=%d\n",p->seat.x,p->seat.y);  
  235.         *p++;  
  236.     }  
  237.     printf("\n");  
  238.     return OK;  
  239. }  
  240.   
  241. Status PrintMaze(MazeType *M){  
  242.     //输出迷宫  
  243.     int i,j;  
  244.     for(i=0;i<M->row;i++){  
  245.         for(j=0;j<M->column;j++){  
  246.             printf("%c",M->maze[i][j]);  
  247.         }  
  248.         printf("\n");  
  249.     }  
  250.     printf("\n");  
  251.     return OK;  
  252. }  
  253.   
  254. Status PrintFoot(MazeType *M,SqStack *S){  
  255.     //输出迷宫的路径  
  256.     int i,j;  
  257.     SElemType *p;  
  258.     for(i=0;i<M->row;i++){  
  259.         for(j=0;j<M->column;j++){  
  260.             M->footprint[i][j]=0;  
  261.         }  
  262.     }  
  263.     p=S->base;  
  264.     if(S->base==S->top)  
  265.     {  
  266.         printf("栈为空.\n");  
  267.         return FALSE;  
  268.     }  
  269.     while(p!=S->top)  
  270.     {  
  271.         M->footprint[p->seat.x][p->seat.y]=1;  
  272.         *p++;  
  273.     }  
  274.     for(i=0;i<M->row;i++){  
  275.         for(j=0;j<M->column;j++){  
  276.             printf("%d",M->footprint[i][j]);  
  277.         }  
  278.         printf("\n");  
  279.     }  
  280.   
  281.     return OK;  
  282. }  
  283.   
  284. Status MazePath(SqStack *S,MazeType maze,PosType start,PosType end){  
  285.     //若迷宫maze中存在从入口start到出口end的通道,则求得一条存放在栈中(从栈底  
  286.     //到栈顶),并返回TRUE;否则返回FALSE  
  287.     int curstep=1;//当前步数  
  288.     SElemType e;  
  289.     PosType curpos=start;//当前位置  
  290.     InitStack(S);//初始化栈  
  291.     do{  
  292.         if(TRUE==Pass(&maze,curpos)){  
  293.             FootPrint(&maze,curpos);  
  294.             e=NewSElem(curstep,curpos,1);  
  295.             Push(S,e);  
  296.             if((curpos.x==end.x)&&(curpos.y==end.y)){//到达终点(出口)  
  297.                 printf("迷宫路径:\n");  
  298.                 //StackTraverse(S);  
  299.                 PrintFoot(&maze,S);  
  300.                 return TRUE;  
  301.             }  
  302.             curpos=NextPos(curpos,1);  
  303.             curstep++;  
  304.         }//if  
  305.         else{//当前位置不能通过  
  306.             if(!StackEmpty(*S)){  
  307.                 Pop(S,&e);  
  308.                 while(e.di==4&&!StackEmpty(*S)){  
  309.                     MarkPrint(&maze,e.seat);  
  310.                     Pop(S,&e);  
  311.                 }//while  
  312.                 if(e.di<4){  
  313.                     e.di++;  
  314.                     Push(S,e);  
  315.                     curpos=NextPos(e.seat,e.di);  
  316.                 }//if  
  317.             }//if  
  318.         }//else  
  319.     //PrintFoot(&maze,S);  
  320.     }while(!StackEmpty(*S));  
  321.     return FALSE;  
  322. }  
  323.   
  324. Status FootPrint(MazeType *M,PosType pos){  
  325.     //将迷宫的当前位置pos设置为"走过",即footprint该位置为1  
  326.     if((pos.x>M->row)||(pos.y>M->column))  
  327.         return FALSE;  
  328.     M->footprint[pos.x][pos.y]=1;  
  329.         return TRUE;  
  330. }  
  331.   
  332. Status Pass(MazeType *M,PosType pos){  
  333.     //判断当前位置是否可通,即为走过的通道块  
  334.     if((M->row<pos.x)||(M->column<pos.y)){  
  335.         printf("位置越位.\n");  
  336.         exit(0);  
  337.     }  
  338.     if((0==M->footprint[pos.x][pos.y])&&(M->maze[pos.x][pos.y]==' '))  
  339.         return TRUE;  
  340.     else  
  341.         return FALSE;  
  342. }  
  343.   
  344. SElemType NewSElem(int step,PosType pos,int d){  
  345.     //创建新结点,用step,pos,d初始化该结点  
  346.     SElemType e;  
  347.     e.ord=step;  
  348.     e.seat=pos;  
  349.     e.di=d;  
  350.     return e;  
  351. }  
  352.   
  353. PosType NextPos(PosType pos,int d){  
  354.     //获取pos位置d方向的位置  
  355.     switch(d){  
  356.     case 1://东  
  357.         pos.x++;  
  358.         break;  
  359.     case 2://南  
  360.         pos.y++;  
  361.         break;  
  362.     case 3://西  
  363.         pos.x--;  
  364.         break;  
  365.     case 4://北  
  366.         pos.y--;  
  367.         break;  
  368.     default:  
  369.         printf("位置编号出错.\n");  
  370.     }  
  371.     return pos;  
  372. }  
  373.   
  374. Status MarkPrint(MazeType *M,PosType pos){  
  375.     //将迷宫M的pos位置,设为已走,成功返回OK;否则返回ERROR  
  376.     if(pos.x>M->row||pos.y>M->column){  
  377.         printf("所要标记位置越位.\n");  
  378.         return ERROR;  
  379.     }  
  380.     M->footprint[pos.x][pos.y]=1;  
  381.     return OK;  
  382. }  


运行结果演示:

0 0