《演算法七》(深度尋路演算法)
阿新 • • 發佈:2020-02-10
深度尋路演算法:
二維地圖:二維陣列
二維陣列上標識特定數值作為地圖上物件
應用於RGB遊戲中比較廣泛
缺點:1.二維地圖,只可以走直線
2.不一定能找到最佳路徑
怎麼尋路:
1.一個方向只能試探一次
順時針: 上 右 下 左
逆時針: 上 左 下 右
2.需要標記已經走過,走過了的不能再走
深度尋路演算法邏輯:
1.地圖
2 輔助地圖
3.起點 終點
4.準備棧
5.標記起點走過
7起點入棧
8 尋路:
8.1 準備變數
8.2 確定試探點
8.3 改變當前點試探方向
8.4 試探試探點能不能走
8.5 走
8.6 標記當前點已經走過
8.7 當前點入棧
深度尋路程式碼:
int _tmain(int argc, _TCHAR* argv[]) { //1 地圖 int map[ROWS][COLS] = { { 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 0, 1, 0, 0, 0, 0, 1 }, { 1, 0, 1, 0, 1, 0, 1, 1 }, { 1, 0, 1, 0, 1, 0, 1, 1 }, { 1, 0, 1, 0, 1, 0, 0, 1 }, { 1, 0, 1, 0, 1, 0, 1, 1 }, { 1, 0, 0, 0, 1, 0, 0, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1 } }; //2 輔助地圖 pathNode pathMap[ROWS][COLS] = { 0 }; for (int i = 0; i < ROWS; i++){ for (int j = 0; j < COLS; j++){ pathMap[i][j].val = map[i][j]; } } //4 起點 終點 MyPoint beginPos; MyPoint endPos; printf("請輸入起點(x,y)\n"); scanf("%d,%d", &(beginPos.col), &(beginPos.row) ); printf("請輸入終點(x,y)\n"); scanf("%d,%d", &(endPos.col), &(endPos.row)); //5 準備棧 MyStack<MyPoint> stack; //6 標記起點走過 pathMap[beginPos.row][beginPos.col].isFind = true; //7 起點入棧 stack.push(beginPos); //8 尋路 //8.1 準備變數 //當前角色位置 MyPoint currentPos = beginPos; //角色試探點 MyPoint searchPos; bool isFindEnd = false; initDraw();//準備圖形介面 while (1){ searchPos = currentPos; switch (pathMap[currentPos.row][currentPos.col].dir) { case p_up: //8.2 確定試探點 searchPos.row--; //8.3 改變當前點試探方向 pathMap[currentPos.row][currentPos.col].dir = p_right; //8.4 試探試探點能不能走 if (pathMap[searchPos.row][searchPos.col].isFind != true &&//沒有走過 pathMap[searchPos.row][searchPos.col].val != 1)//不是障礙 {//能走 //8.5 走 currentPos = searchPos; //8.6 標記當前點已經走過 pathMap[currentPos.row][currentPos.col].isFind = true; //8.7 當前點入棧 stack.push(currentPos); } break; case p_right: //8.2 確定試探點 searchPos.col++; //8.4 改變當前點試探方向 pathMap[currentPos.row][currentPos.col].dir = p_down; //8.3 試探試探點能不能走 if (pathMap[searchPos.row][searchPos.col].isFind != true &&//沒有走過 pathMap[searchPos.row][searchPos.col].val != 1)//不是障礙 {//能走 //8.5 走 currentPos = searchPos; //8.6 標記當前點已經走過 pathMap[currentPos.row][currentPos.col].isFind = true; //8.7 當前點入棧 stack.push(currentPos); } break; case p_down: //8.2 確定試探點 searchPos.row++; //8.4 改變當前點試探方向 pathMap[currentPos.row][currentPos.col].dir = p_left; //8.3 試探試探點能不能走 if (pathMap[searchPos.row][searchPos.col].isFind != true &&//沒有走過 pathMap[searchPos.row][searchPos.col].val != 1)//不是障礙 {//能走 //8.5 走 currentPos = searchPos; //8.6 標記當前點已經走過 pathMap[currentPos.row][currentPos.col].isFind = true; //8.7 當前點入棧 stack.push(currentPos); } break; case p_left: //8.2 確定試探點 searchPos.col--; //8.3 試探試探點能不能走 if (pathMap[searchPos.row][searchPos.col].isFind != true &&//沒有走過 pathMap[searchPos.row][searchPos.col].val != 1)//不是障礙 {//能走 //8.5 走 currentPos = searchPos; //8.6 標記當前點已經走過 pathMap[currentPos.row][currentPos.col].isFind = true; //8.7 當前點入棧 stack.push(currentPos); } else{//不能走 //8.8 回退 //8.8.1 退棧 stack.pop(); //8.8.2 當前點變為棧頂元素 currentPos = stack.getTop(); } break; } printMap(map, currentPos); drawMap(map, currentPos); //找到終點 迴圈結束 if (currentPos.row == endPos.row && currentPos.col == endPos.col){ isFindEnd = true; break; } //棧為空:回到起點 迴圈結束 if (stack.isEmpty()) break; } //9 列印整個路徑 if (isFindEnd){ printf("path:"); while (!stack.isEmpty()){ //9.1 列印棧頂元素 printf("(%d,%d)\n", stack.getTop().row, stack.getTop().col); //9.2 退棧 stack.pop(); } } while (1); return 0; }
完整程式碼:
//定義棧 //定義棧 template<class T> class MyStack{ T* pBuff; size_t capacity; size_t len; public: MyStack(){ pBuff = NULL; capacity = len =0; } ~MyStack(){ if(pBuff){ delete[] pBuff; } pBuff = NULL; capacity = len =0; } void push(const T& data);//入棧 void pop(void);//出棧 T getTop(void);//獲取棧頂元素 bool isEmpty(void);//判斷是否為空 }; template<class T> void MyStack<T>::push(const T& data){//入棧 if (len >= capacity){ capacity = capacity + (((capacity >> 1) > 1) ? (capacity >> 1) : 1 ); T* pNew = new T[capacity]; if (pBuff){ memcpy(pNew, pBuff, sizeof(T)*len); delete[] pBuff; } pBuff = pNew; } pBuff[len++] = data; } template<class T> //出棧 void MyStack<T>::pop(void){ len--; } template<class T> //獲取棧頂元素 T MyStack<T>::getTop(void){ return pBuff[len - 1]; } template<class T> //判斷是否為空 bool MyStack<T>::isEmpty(void){ return (len==0); } // 深度尋路演算法.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include "MyStack.h" //#include <windows.h> #include <graphics.h> /* RPG遊戲中 地圖 深度尋路演算法 1.二維地圖,只能走直線 2.不一定能找到最佳路徑 廣度尋路演算法 A星尋路演算法 尋路: 1.一個方向只能試探一次 順時針: 上 右 下 左 逆時針: 上 左 下 右 2.需要標記已經走過,走過了的不能再走 */ //x 橫 列數 #define COLS 8 //y 豎 行數 #define ROWS 8 //每個格子大小 #define SPACE 50 //方向列舉 enum direct{p_up,p_right,p_down,p_left}; //輔助地圖元素型別 struct pathNode{ int val; //這個點上是什麼 direct dir; //試探方向 bool isFind; //有沒有走過 0 false 沒走過 1 true 走過 }; //點結構 struct MyPoint{ int row; //y int col; //x }; //圖片全域性變數 IMAGE g_wall, g_road, g_people; void printMap(int map[ROWS][COLS], MyPoint pos); void initDraw(); void drawMap(int map[ROWS][COLS], MyPoint pos); int _tmain(int argc, _TCHAR* argv[]) { //1 地圖 int map[ROWS][COLS] = { { 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 0, 1, 0, 0, 0, 0, 1 }, { 1, 0, 1, 0, 1, 0, 1, 1 }, { 1, 0, 1, 0, 1, 0, 1, 1 }, { 1, 0, 1, 0, 1, 0, 0, 1 }, { 1, 0, 1, 0, 1, 0, 1, 1 }, { 1, 0, 0, 0, 1, 0, 0, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1 } }; //2 輔助地圖 pathNode pathMap[ROWS][COLS] = { 0 }; for (int i = 0; i < ROWS; i++){ for (int j = 0; j < COLS; j++){ pathMap[i][j].val = map[i][j]; } } //4 起點 終點 MyPoint beginPos; MyPoint endPos; printf("請輸入起點(x,y)\n"); scanf("%d,%d", &(beginPos.col), &(beginPos.row) ); printf("請輸入終點(x,y)\n"); scanf("%d,%d", &(endPos.col), &(endPos.row)); //5 準備棧 MyStack<MyPoint> stack; //6 標記起點走過 pathMap[beginPos.row][beginPos.col].isFind = true; //7 起點入棧 stack.push(beginPos); //8 尋路 //8.1 準備變數 //當前角色位置 MyPoint currentPos = beginPos; //角色試探點 MyPoint searchPos; bool isFindEnd = false; initDraw();//準備圖形介面 while (1){ searchPos = currentPos; switch (pathMap[currentPos.row][currentPos.col].dir) { case p_up: //8.2 確定試探點 searchPos.row--; //8.3 改變當前點試探方向 pathMap[currentPos.row][currentPos.col].dir = p_right; //8.4 試探試探點能不能走 if (pathMap[searchPos.row][searchPos.col].isFind != true &&//沒有走過 pathMap[searchPos.row][searchPos.col].val != 1)//不是障礙 {//能走 //8.5 走 currentPos = searchPos; //8.6 標記當前點已經走過 pathMap[currentPos.row][currentPos.col].isFind = true; //8.7 當前點入棧 stack.push(currentPos); } break; case p_right: //8.2 確定試探點 searchPos.col++; //8.4 改變當前點試探方向 pathMap[currentPos.row][currentPos.col].dir = p_down; //8.3 試探試探點能不能走 if (pathMap[searchPos.row][searchPos.col].isFind != true &&//沒有走過 pathMap[searchPos.row][searchPos.col].val != 1)//不是障礙 {//能走 //8.5 走 currentPos = searchPos; //8.6 標記當前點已經走過 pathMap[currentPos.row][currentPos.col].isFind = true; //8.7 當前點入棧 stack.push(currentPos); } break; case p_down: //8.2 確定試探點 searchPos.row++; //8.4 改變當前點試探方向 pathMap[currentPos.row][currentPos.col].dir = p_left; //8.3 試探試探點能不能走 if (pathMap[searchPos.row][searchPos.col].isFind != true &&//沒有走過 pathMap[searchPos.row][searchPos.col].val != 1)//不是障礙 {//能走 //8.5 走 currentPos = searchPos; //8.6 標記當前點已經走過 pathMap[currentPos.row][currentPos.col].isFind = true; //8.7 當前點入棧 stack.push(currentPos); } break; case p_left: //8.2 確定試探點 searchPos.col--; //8.3 試探試探點能不能走 if (pathMap[searchPos.row][searchPos.col].isFind != true &&//沒有走過 pathMap[searchPos.row][searchPos.col].val != 1)//不是障礙 {//能走 //8.5 走 currentPos = searchPos; //8.6 標記當前點已經走過 pathMap[currentPos.row][currentPos.col].isFind = true; //8.7 當前點入棧 stack.push(currentPos); } else{//不能走 //8.8 回退 //8.8.1 退棧 stack.pop(); //8.8.2 當前點變為棧頂元素 currentPos = stack.getTop(); } break; } printMap(map, currentPos); drawMap(map, currentPos); //找到終點 迴圈結束 if (currentPos.row == endPos.row && currentPos.col == endPos.col){ isFindEnd = true; break; } //棧為空:回到起點 迴圈結束 if (stack.isEmpty()) break; } //9 列印整個路徑 if (isFindEnd){ printf("path:"); while (!stack.isEmpty()){ //9.1 列印棧頂元素 printf("(%d,%d)\n", stack.getTop().row, stack.getTop().col); //9.2 退棧 stack.pop(); } } LOGFONT font = { 0 }; font.lfHeight = 25; font.lfWeight = 10; settextstyle(&font); outtextxy((COLS*SPACE - 110) / 2, (ROWS*SPACE - 25) / 2, L"恭喜你通關!"); while (1); return 0; } void printMap(int map[ROWS][COLS], MyPoint pos){ system("cls");//清屏 for (int i = 0; i < ROWS; i++){ for (int j = 0; j < COLS; j++){ if (i == pos.row && j == pos.col){//人 printf("人"); } else if (map[i][j] == 1){//障礙 printf("牆"); } else{//路 printf(" "); } } printf("\n"); } Sleep(500); } void initDraw(){ initgraph(COLS*SPACE, ROWS*SPACE, SHOWCONSOLE); loadimage(&g_wall, L"wall.jpg", SPACE, SPACE, true); loadimage(&g_road, L"road.jpg", SPACE, SPACE, true); loadimage(&g_people, L"people.jpg", SPACE, SPACE, true); } void drawMap(int map[ROWS][COLS], MyPoint pos){ cleardevice();//清屏 for (int i = 0; i < ROWS; i++){ for (int j = 0; j < COLS; j++){ if (i == pos.row && j == pos.col){//人 putimage(j*SPACE, i*SPACE, &g_people); } else if (map[i][j] == 1){//障礙 putimage(j*SPACE, i*SPACE, &g_wall); } else{//路 putimage(j*SPACE, i*SPACE, &g_road); } } } }
&n