公式:F=G+H+W
F是代价函数,G代表从起点到当前点的距离,H代表从当前点到终点的距离,W是权值。
H不考虑障碍物,只计算直线距离(计算横纵距离差)
算法思想:从起始点出发计算周围8个点的F,选择最小的点进行拓展,如果F相等选择|G-H|小的结点,循环操作。若走进死胡同(周围所有点都被访问或者是障碍物)回溯。
#include<stdio.h> #include<iostream> #include<vector> #include<windows.h> using namespace std; #define ROWS 9 #define CLOS 11 #define ZXDJ 10 #define XXDJ 14 //点的类型 struct MyPoint { int row; int col; int f; int g; int h; void setF() { f = g + h; } bool operator==(const MyPoint& p1) { if (this->row == p1.row && this->col == p1.col) { return true; }else return false; } }; //树的节点类型 struct TreeNode { MyPoint pos; //当前点坐标 vector<TreeNode*> childs;//存储当前点的孩子节点指针数组 TreeNode* pParent;//存储当前点父节点数组 }; enum direct{p_up,p_down,p_left,p_right,p_lup,p_ldown,p_rup,p_rdown}; //检查是否需要统计 bool needAdd(MyPoint pos, int map[ROWS][CLOS], bool pathMap[ROWS][CLOS]) { if (pos.row >= ROWS || pos.row < 0|| pos.col >= CLOS || pos.col < 0) { return false; } if (map[pos.row][pos.col]||pathMap[pos.row][pos.col]) return false; return true; } void printMap(int map[ROWS][CLOS],TreeNode* pCurrent,MyPoint endPos) { for (int i = 0; i < ROWS; i++) { for (int j = 0; j < CLOS; j++) { if (i == pCurrent->pos.row && j == pCurrent->pos.col) { cout << "人"; } else if (i == endPos.row && j == endPos.col) { cout << "终"; } else if (map[i][j] == 0) { cout << "口"; } else if(map[i][j]==1) { cout << "墙"; } } cout << endl; } } //计算h值:endPos:终点坐标 pos:当前点坐标 int getH(MyPoint endPos, MyPoint pos) { int x = abs(endPos.col-pos.col); int y = abs(endPos.row - pos.row); return (x + y) * ZXDJ; } int main() { int map[ROWS][CLOS] = { {0,0,0,0,0,1,0,0,0,0,0}, {0,0,0,1,0,1,0,1,1,1,0}, {0,0,0,1,0,1,0,0,0,0,0}, {0,0,0,1,0,1,0,0,0,0,0}, {0,0,0,0,0,1,0,0,0,0,0}, {0,1,1,0,0,1,0,0,0,0,0}, {0,0,1,1,0,1,0,0,0,0,0}, {0,0,0,0,1,1,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0}, }; //2 辅助地图 false 0:没有走过 true 1:走过 bool pathMap[ROWS][CLOS] = { 0 }; //3.起点 终点 MyPoint begPos = { 8,8 }; MyPoint endPos = { 0,8 }; //4.标记起点走过 pathMap[begPos.row][begPos.col] = true; //5.创建一棵树,起点是树的根节点 //创建一个新节点 TreeNode* pNew = new TreeNode;//创建一个节点 //memset(pNew, 0, sizeof TreeNode);//给节点赋值 //pNew={0}; //新节点成为树根 //pRoot一直指向树的根节点 TreeNode* pRoot = pNew; //新节点是记录起点 pRoot->pos = begPos; pRoot->pParent = NULL; //6.动态数组 存储用来比较的节点 vector<TreeNode*> buff; TreeNode* pCurrent = pRoot; TreeNode* pChild = NULL;//中间节点 vector<TreeNode*>::iterator it; vector<TreeNode*>::iterator itMin; //7.寻路 while (1) { printMap(map, pCurrent, endPos); Sleep(300); system("cls"); //7.1找到当前点周围能走的点 for (int i = 0; i < 8; i++) { pChild = new TreeNode; //memset(pChild, 0, sizeof TreeNode); //pChild = { 0 }; pChild->pos = pCurrent->pos; switch(i) { case p_up: pChild->pos.row--; pChild->pos.g += ZXDJ; break; case p_down: pChild->pos.row++; pChild->pos.g += ZXDJ; break; case p_left: pChild->pos.col--; pChild->pos.g += ZXDJ; break; case p_right: pChild->pos.col++; pChild->pos.g += ZXDJ; break; case p_lup: pChild->pos.row--; pChild->pos.col--; pChild->pos.g += XXDJ; break; case p_rup: pChild->pos.row--; pChild->pos.col++; pChild->pos.g += XXDJ; break; case p_ldown: pChild->pos.row++; pChild->pos.col--; pChild->pos.g += XXDJ; break; case p_rdown: pChild->pos.row++; pChild->pos.col++; pChild->pos.g += XXDJ; break; default: break; } /*printf("(%d,%d):%d\n", pChild->pos.row, pChild->pos.col, pChild->pos.g);*/ //7.2计算 g h f值 pChild->pos.h = getH(endPos, pChild->pos); pChild->pos.setF(); //7.3入树,入buff数组 if (needAdd(pChild->pos, map, pathMap)) { //入树 pCurrent->childs.push_back(pChild); pChild->pParent = pCurrent; /*printf("(%d,%d):%d\n", pChild->pos.row, pChild->pos.col, pChild->pos.g);*/ //入buff数组 buff.push_back(pChild); //标记走过 pathMap[pChild->pos.row][pChild->pos.col] = true; } else { delete pChild; } } //7.4从buff数组中找到f值最小的那个 回溯也是靠这个buff回溯的 //TreeNode* tmin=*(buff.begin());//迭代器解引用,迭代器相当于一个指针 itMin = buff.begin(); int differ = abs((*buff.begin())->pos.g - (*buff.begin())->pos.h); for (it = buff.begin();it!=buff.end();it++) { itMin = (*itMin)->pos.f > (*it)->pos.f ? it : itMin; if ((*itMin)->pos.f > (*it)->pos.f) { itMin = it; } else if ((*itMin)->pos.f > (*it)->pos.f) { itMin = itMin; } else if ((*itMin)->pos.f == (*it)->pos.f) { if (abs((*it)->pos.g - (*it)->pos.h) < differ) { differ = abs((*it)->pos.g - (*it)->pos.h); itMin = it; } } } //7.5删掉,变化成当前点 pCurrent = *itMin; buff.erase(itMin); //7.6 判断是否寻路结束 if (pCurrent->pos == endPos) { cout << "我到终点了!"<<endl; while (pCurrent) { printf("(%d,%d)", pCurrent->pos.row, pCurrent->pos.col); pCurrent = pCurrent->pParent; } cout << endl; break; } if (buff.empty()) { cout << "无路径!" << endl; break; } } //end while //MyPoint p1; //p1.row = 1; //p1.col = 1; //MyPoint p2; //p2.row = 0; //p2.col = 1; //cout << (p1 == p2) << endl; return 0; }