迷宫问题(C语言)
迷宮尋路C語言
- 一、棧
- 1.名詞
- 2.棧的實現
- 棧元素的結構:
- 初始化棧
- 入棧
- 出棧
- 二、迷宮問題
- 1.定義迷宮類型
- 2.迷宮分析
- 1.迷宮的初始化
- 2.迷宮顯示
- 3.迷宮尋路
- 3.運行結果
- 三.全部程序和參考書籍
一、棧
棧又是線性表,但是它是一個受限制的線性表。線性表可以自由得刪除或插入節點,但棧只能在棧頂刪除(出棧)或插入(入棧)。(見下圖)
順序表的插入與刪除:
棧的入棧與出棧:
1.名詞
棧2.棧的實現
棧元素的結構:
/* 順序棧元素類型定義 */ typedef int SElemType;// 順序棧元素結構 typedef struct {SElemType* base; // 棧底指針SElemType* top; // 棧頂指針int stacksize; // 當前已分配的存儲空間,以元素為單位 } SqStack;其中
SElemType* base; // 棧底指針 //棧底指針,主要用于接收動態分配空間的首地址。SElemType* top; // 棧頂指針 //棧頂指針,主要用于入棧和出棧。初始化棧
"->"是指針式訪問結構體成員
typedef int Status;/* *初始化棧(空棧) *初始化成功返回OK,否則返回ERROR */ Status InitStack(SqStack* S) {if(S == NULL) {return ERROR;}//分配棧空間S->base = (SElemType*) malloc(STACK_INIT_SIZE * sizeof(SElemType));if(S->base == NULL) {exit(1);//非正常結束當前進程}S->top = S->base;S->stacksize = STACK_INIT_SIZE;return OK; }入棧
/* *入棧(將e壓入棧) *入棧成功返回OK,否則返回ERROR */ Status Push(SqStack* S, SElemType e) {if (S->base == NULL || S == NULL)return ERROR;//若棧滿了,則增加空間if (S->top - S->base >= S->stacksiaze){S->base = (SElemType*)realloc(S->base,(S->stacksiaze + STACKINCREMENT) * sizeof(SElemType));if (S->base == NULL)exit(1);//分配失敗S->top = S->base + S->stacksiaze;S->stacksiaze += STACKINCREMENT;}//將e壓入棧(先入棧,棧頂指針再自增)*(S->top++) = e;return OK; }出棧
/* *出棧(e存入的是出棧的內容) *出棧成功返回OK,否則返回ERROR */ Status Pop(SqStack* S, SElemType* e) {if (S->base == NULL || S == NULL || S->base == S->top)return ERROR;//棧頂指針先遞減*e = *(--(S->top));//當前棧頂指針所指的地址都默認是不用地址,棧頂的前一個地址(--(S->top))才是有用地址return OK; }二、迷宮問題
迷宮一般來講都是有外墻、迷宮內墻、通路、死胡同、方向(東南西北)、迷宮的方位(x、y坐標)、迷宮大小等等。
1.定義迷宮類型
typedef int MazeType[M][N]; // 迷宮類型 //迷宮類型 typedef enum {Wall, // 外墻Obstacle, // 迷宮內部的障礙Way, // 通路Impasse, // “死胡同”East, South, West, North // 當前探索方向:東南西北 } MazeNode;//通道信息 typedef struct {int x;int y;int di;//下一個訪問的位置 }SElemType;//迷宮棧 typedef struct {SElemType* base; // 棧底指針SElemType* top; // 棧頂指針int stacksize; // 當前已分配的存儲空間,以元素為單位 } SqStack; typedef int MazeType[M][N]; // 迷宮類型常見的類型定義是:
typedef int** MazeType; // 迷宮類型二者類似但第一種是為二位數組分配了大小的二維數組,第二個是暫未分配大小的二位數組大小。(第一個已經為二位數組初始化元素為0,第二種是未初始化的二維數組)
2.迷宮分析
1.迷宮的初始化
- 在初始化階段將迷宮的外形確定下來,包括迷宮的外輪廓(外墻)、迷宮內的障礙(內墻)確定并打印在終端上,為了保證迷宮的不確定性和迷宮尋路的自主性,迷宮的內墻由系統的隨機數發生器隨機的生成內墻的位置。
- 迷宮的墻壁都是由枚舉類型來給定的,這樣做的好處是代碼閱讀方便容易理解。
- 迷宮的坐標是由二維數組的下標表示。
如下所示是一個4*4大小的迷宮二維數組,數組中存儲的就是迷宮的類型(外墻、內墻、通路、死胡同,方向),假設1是墻壁,0是通路:
| 1 | 0 | 1 | 1 |
| 1 | 0 | 0 | 0 |
| 1 | 1 | 1 | 1 |
代碼如下:
void InitMaze(MazeType maze, PosType* start, PosType* end) {int tmp;srand((unsigned)time(NULL)); //初始化隨機數發生器for (int i=0;i < M;i++){for (int j = 0;j < N;j++){ //墻壁生成if (i == 0 || j == 0 || i == M - 1 || j == N - 1)maze[i][j] = Wall;//外墻else{tmp = rand() % X;if (tmp == 0)maze[i][j] = Obstacle;//內墻elsemaze[i][j] = Way;//通路}}}//入口start->x = 1;start->y = 0;//出口end->x = M - 2;end->y = N - 1;//開放入口和出口maze[1][0] = maze[M - 2][N - 1] = Way;//提高尋路成功率maze[1][1] = maze[M - 2][N - 2] = Way;// 顯示迷宮的初始狀態PrintMaze(maze); }2.迷宮顯示
利用switch函數判斷迷宮類型二位數組maze的類型,根據其類型打印迷宮。
其關鍵點:
- 在每一行的結束位置輸出回車符。
- 每次進入打印函數,先清屏再打印。
3.迷宮尋路
代碼如下:
Status MazePath(MazeType maze, PosType start, PosType end) {SqStack S;PosType curPos;SElemType e;InitStack(&S);curPos = start;//設置當前位置是入口位置do {//如果當前位置是可以通過的(該位置是從未曾探索過的通道塊)if (Pass(maze, curPos)){//留下足跡(留下向東訪問的標記)FootPrint(maze, curPos);e = Construct(curPos,East);//構造一個通道塊信息并返回Push(&S, e);//將通道塊壓入棧if (Equals(curPos, end)){printf("\n尋路成功!!\n\n");return TRUE;}curPos = NextPos(curPos, East);//獲取下一個要探索的位置}else{if (!StackEmpty(S)){Pop(&S, &e);//退回上一個位置while (e.di == North && !StackEmpty(S)){MarkPrint(maze, e.seat, Impasse);//留下死胡同印記Pop(&S, &e);//繼續退回}if (e.di < North){++e.di;//改變探索方向,按東南西北方向輪詢MarkPrint(maze, e.seat, e.di);//在迷宮下留下訪問標記,用來觀察迷宮的狀態Push(&S, e);//從新將該位置加入到路徑只能curPos = NextPos(e.seat, e.di);}}}} while (!StackEmpty(S));printf("\n尋路失敗\n\n");return FALSE; }3.運行結果
8:向北方向
4:向西方向
6:向東方向
2:向南方向
0:死胡同
*:墻壁
三.全部程序和參考書籍
下載程序
參考書籍:嚴蔚敏,吳偉民 《書籍結構(C語言版)》 清華大學出版社(第52頁算法3.3) 書號:9787302147510
總結
- 上一篇: html怎么制作附页,2020-05-2
- 下一篇: 企业集群平台架构设计与实现(lvs/ha