1. 程式人生 > 實用技巧 >AStar尋路

AStar尋路

#include "pch.h"
#include <iostream>
#include <vector>
#include <windows.h>
using namespace std;
//行 高
#define ROW 12
//列 寬
#define COL 12

#define ZXDJ 10
#define XXDJ 14

struct MyPoint
{
    int row;
    int col;
    //g起點到當前點代價
    //w權重
    //h當前點到終點的預估代價 忽略障礙只看直線
    //f = g+h+w
    int g, h, f;
    
void setF() { f = g + h; } }; //八個方向 enum direct { p_up,p_down,p_left,p_right,p_lup,p_ldown,p_rup,p_rdown }; //輔助地圖節點 //記錄走過沒,代價值 struct pathNode { int val;// bool isFind;//走過沒,true走過 }; //判斷pos點能不能走,能true bool canWalk(MyPoint pos, pathNode pathMap[ROW][COL]) { //不在地圖內 if (pos.row < 0
||pos.row>=ROW||pos.col<0||pos.col>=COL) { return false;} //是障礙,不能走 if (pathMap[pos.row][pos.col].val == 1)return false; //走過了 if (pathMap[pos.row][pos.col].isFind == 1)return false; return true; } //樹的節點型別,使用樹儲存走過路徑 struct treeNode { MyPoint pos; treeNode* pParent;//
指向父節點指標 vector<treeNode*> child;//儲存所有孩子節點陣列 }; //計算g值 int getG(MyPoint pos,MyPoint endPos); int main() { //地圖 0:路 1:障礙 2:大樓 3:井蓋 int map[ROW][COL] = { {0,0,0,0,0,1,0,0,0,0,0,0}, {0,0,0,0,0,1,0,0,0,0,0,0}, {0,0,0,0,0,1,0,0,0,0,0,0}, {0,0,0,0,0,1,0,0,0,0,0,0}, {0,0,0,0,0,1,0,0,0,0,0,0}, {0,0,0,0,0,1,0,0,0,0,0,0}, {0,0,0,0,0,1,0,0,0,0,0,0}, {0,0,0,0,0,1,0,0,0,0,0,0}, {0,0,0,0,0,1,0,0,0,0,0,0}, {0,0,0,0,0,1,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,1,0,0,0,0,0,0}, }; //2 起點和重點 MyPoint begPos = {1,1}; MyPoint endPos = { 5,10 }; //3 記錄,輔助地圖,初始化 pathNode pathMap[ROW][COL] = { 0 }; for (int i = 0;i<ROW;i++) for (int j = 0; j < COL; j++) { pathMap[i][j].val = map[i][j]; } //4 建立一棵樹 treeNode* pRoot = NULL; //5 標記起點點走過 pathMap[begPos.row][begPos.col].isFind = true; //6 起點入數成為根節點 pRoot = new treeNode; memset(pRoot, 0, sizeof treeNode);//清空 pRoot->pos = begPos; //7 準備一個數組儲存所有評估點 vector<treeNode*> buff; //迭代器找最小點 vector<treeNode*>::iterator itMin; vector<treeNode*>::iterator it; //8 尋路 bool isFindEnd = false; //當前點 MyPoint currentPos = begPos; //當前樹節點 treeNode* pTemp = pRoot; while (true) { //8.1 檢查當前點哪些需要計算 for (int i = 0; i < 8; i++) { treeNode* pChild = new treeNode; memset(pChild, 0, sizeof treeNode); pChild->pos = pTemp->pos; switch (i) { case p_up: pChild->pos.row--; pChild->pos.g = 10; break; case p_down: pChild->pos.row++; pChild->pos.g = 10; break; case p_left: pChild->pos.col--; pChild->pos.g = 10; break; case p_right: pChild->pos.col++; pChild->pos.g = ZXDJ; break; case p_lup: pChild->pos.col--; pChild->pos.row--; pChild->pos.g = XXDJ; break; case p_ldown: pChild->pos.col--; pChild->pos.row++; pChild->pos.g = XXDJ; break; case p_rup: pChild->pos.col++; pChild->pos.row--; pChild->pos.g = XXDJ; break; case p_rdown: pChild->pos.col++; pChild->pos.row++; pChild->pos.g = XXDJ; break; default: break; }//8.2 計算所有點f //8.2.1 判斷是否計算(能走不) if (canWalk(pChild->pos,pathMap)) { //8.2.2 jisuanf pChild->pos.g = getG(pChild->pos, endPos); pChild->pos.setF(); //8.2.3 判斷能否入樹buff pTemp->child.push_back(pChild); pChild->pParent = pTemp; buff.push_back(pChild); //printf("(%d,%d)", pChild->pos.row, pChild->pos.col); } } //cout << endl; //Sleep(2000); //8.3 找出f值最小的點,走,並從buff中刪除該店 itMin = buff.begin(); for (it = buff.begin(); it != buff.end(); it++) { if ((*itMin)->pos.f > (*it)->pos.f) { itMin = it; } } pathMap[pTemp->pos.row][pTemp->pos.col].isFind = true; pTemp = *itMin;// buff.erase(itMin); //8.4 判斷是否找到重點,判斷整個地圖是否沒有終點 if (pTemp->pos.row == endPos.row&& pTemp->pos.col == endPos.col) { isFindEnd = true; break; } if (buff.empty()) { break; } } //9 列印路徑 if (isFindEnd) { printf("找到終點了!\n"); while (pTemp) { printf("(%d,%d)", pTemp->pos.row, pTemp->pos.col); pTemp = pTemp->pParent; } cout << "\n"; } cout << fun(); system("pause"); } int getG(MyPoint pos, MyPoint endPos) { int x = ((pos.col > endPos.col) ? (pos.col - endPos.col) : (endPos.col - pos.col)); int y = ((pos.row > endPos.row) ? (pos.row - endPos.row) : (endPos.row - pos.row)); return ZXDJ * (x + y); } // 執行程式: Ctrl + F5 或除錯 >“開始執行(不除錯)”選單 // 除錯程式: F5 或除錯 >“開始除錯”選單 // 入門提示: // 1. 使用解決方案資源管理器視窗新增/管理檔案 // 2. 使用團隊資源管理器視窗連線到原始碼管理 // 3. 使用輸出視窗檢視生成輸出和其他訊息 // 4. 使用錯誤列表視窗檢視錯誤 // 5. 轉到“專案”>“新增新項”以建立新的程式碼檔案,或轉到“專案”>“新增現有項”以將現有程式碼檔案新增到專案 // 6. 將來,若要再次開啟此專案,請轉到“檔案”>“開啟”>“專案”並選擇 .sln 檔案