標籤:tac nod int() 優先 set rpo foo size 問題
#include <stdio.h>#include <stdlib.h>#define ROW 10#define COL 10/*迷宮中位置資訊*/typedef struct position{int x;int y;}position;/*在迷宮中的當前位置的資訊,也是入棧的基本元素*/typedef struct SElem{int di;position seat;}SElem;/*鏈式棧中節點的定義*/typedef struct position_stack{SElem p;struct position_stack *next;}*Stack_pNode,Stack_Node;void InitStack(Stack_pNode *Link){*Link = NULL;}void push(Stack_pNode *Link,SElem e){Stack_pNode new_SElem = (Stack_pNode)calloc(1,sizeof(Stack_Node));new_SElem->p = e;new_SElem->next = NULL;if (*Link == NULL)*Link = new_SElem;else{new_SElem->next = *Link;*Link = new_SElem;}}int pop(Stack_pNode *Link,SElem *e){if (*Link == NULL)return 0;*e = (*Link)->p;Stack_pNode q = *Link;*Link = (*Link)->next;free(q);return 1;}int top(Stack_pNode Link, SElem *e){if (Link == NULL)return 0;*e = Link->p;return 1;}int empty(Stack_pNode Link){if (Link == NULL)return 1;elsereturn 0;}int reverse(Stack_pNode *Link){Stack_pNode p, q, r;if (*Link == NULL || (*Link)->next == NULL)return 0;r = *Link;p = (*Link)->next;q = NULL;while (p){r->next = q;q = r;r = p;p = p->next;}r->next = q;*Link = r;}void print(Stack_pNode Link){Stack_pNode r = Link;while (r){printf("(%d,%d) -> ",r->p.seat.x,r->p.seat.y);r = r->next;}printf("exit\n");}int curstep = 1;/*紀錄當前的足跡,填寫在探索前進的每一步正確的路上*//*迷宮地圖。1代表牆的位置,0代表可行的路,周圍有一圈牆*/int m[ROW+2][COL+2] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1,1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1,1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1,1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1,1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1,1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1,1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1,1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};/*方向優先順序設定。依次為當前位置的右,下,左。上,在位置資訊中。儲存有本次前進的方向--數組的下標*/position dir_set[4] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };/*推斷當前位置是否可行。即推斷是路。還是牆*/int pass(position p){if (m[p.x][p.y])return 0;elsereturn 1;}/*將當前的步數填寫在走的每一步正確的路上,當發現走不通時,會把當時寫的資訊用‘1’抹掉,代表走不通。*/void footPrint(position p){m[p.x][p.y] = curstep;}/*計算下一步的座標。di代表方向。本函數僅僅負責計算下一步座標。不推斷優先順序*/void nextPos(position *p, int di){(*p).x += dir_set[di].x;(*p).y += dir_set[di].y;}/*如上面的footPrint()凝視中提到的,當發現當前路走不通時,會用‘1’把走不通的路堵上。
*/void markPrint(position p){m[p.x][p.y] = 1;}/*迷宮程式的主函數。形參是一個指向不帶前端節點的棧的指標的指標,一個開始位置,一個結束位置*/int find_path(Stack_pNode * Maze_stack,position start,position end){position curpos = start;/*定義一個位置變數。用來儲存當前的位置資訊*/SElem e;/*棧的元素。包含位置資訊,和前進的方向*/do{if (pass(curpos)){ /*假設當前節點是路,則要將當前節點入棧。並計算下一步前進方向*/footPrint(curpos);/*在前進節點上紀錄當前的步數*/e.seat = curpos;/*儲存位置資訊*/e.di = 0;/*儲存方向資訊。默覺得向右*/push(Maze_stack, e);/*將位置資訊入棧*/++curstep;/*步數加1*/if (curpos.x == end.x && curpos.y == end.y)/*假設當前節點是出口。則返回運行成功的標識*/return 1;nextPos(&curpos, e.di);/*計算下一步的座標。是依據當前位置資訊計算的,即已經入棧了的資訊*/}else{/*假設當前節點是牆。則須要從棧取出之前走過的路,即沿原路返回,在返回的過程中,還要不斷的推斷有沒有其它的路*/if (!empty(*Maze_stack)){/*假設棧中有元素*/pop(Maze_stack,&e);--curstep;while (e.di == 3 && !empty(*Maze_stack)){/*邊向前回溯,邊推斷是否有其它的路可走*/markPrint(e.seat);/*用"牆"覆蓋之前填寫的步數資訊*/pop(Maze_stack,&e);--curstep;}if (e.di < 3){/*當找到了一個還有其它的路可走之前走過的一個方塊(最壞的情況是回到起始位置)*/++e.di;/*按優先順序改變之前的行走方向*/push(Maze_stack, e);/*再次入棧*/++curstep;/*再次將步數加1*/curpos = e.seat;/*再次紀錄如今的位置*/nextPos(&curpos, e.di);/*再次計算下次的方向,有了以上的準備,即將進行下一次的迴圈*/}//end if}//end if}//end else} while (!empty(*Maze_stack));return 0;}/*列印迷宮*/void printMaze(){int i, j;for (i = 0; i < ROW+2; ++i){for (j = 0; j < COL+2; ++j){printf("%2d ", m[i][j]);}printf("\n");}}int main(){//stack_test();position start = { 1, 1 };/*迷宮入口*/position end = { 10, 10 };/*迷宮出口*/Stack_pNode maze_stack;/*聲明一個棧,一會兒用來存放在迷宮中走過的位置*/InitStack(&maze_stack);/*初始化棧*/if (find_path(&maze_stack, start, end)){reverse(&maze_stack);/*因為棧中存放的是倒置的資訊,須要將棧倒置*/print(maze_stack);/*列印帶有走過的步數資訊的迷宮地圖*/}else{printf("Has no way to out of the maze.\n");}printMaze();return 0;}
用C語言解決迷宮問題