A*寻路算法详解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了A*寻路算法详解相关的知识,希望对你有一定的参考价值。
以我个人的理解:
A*寻路算法是一种启发式算法,算法的核心是三个变量f,g,h的计算。g表示 从起点 沿正在搜索的路径 到 当前点的距离,h表示从当前点到终点的距离,而f=g+h,所以f越小,则经过当前点的最终路径长度也就越小。
算法当中,有两个辅助列表用来搜索路径。
搜索域(开启列表)和已搜索域(关闭列表)。其中搜索域用来存放待搜索的节点,已搜索域存放已经搜过的节点。
这两个列表的用法:
1、初始化:首先把起点放进搜索域。
2、从搜索域取出f最小的节点,分别遍历上下左右,左上,右下,左下,右上8个方向,并计算他们的f,g,h值,放进搜索域。
3、把当前节点从搜索域中删除,把当前节点放进已搜索域。进入第2步,循环。直到搜索域为空,或者找到终点。
那么重点的就是这个过程怎么实现。
用下面的图来做演示:
图1
图1中,绿色表示起点,红色表示终点,紫色表示墙。
1、计算起点的g,h,f,放进搜索域。
2、从搜索域取出f值最小的节点,8个方向搜索。(下 图2中蓝色部分)
3、从搜索域中删除当前节点,把当前节点放入已搜索域中。到第2步循环。
图2
图3
图3中橙黄色部分表示在 已搜索域 中。蓝色表示在 搜索域 中。
图4
图5
图6
........此处省略若干图。
最终图
过程大概就是这个过程。下面看代码:
#include <iostream> #include <algorithm> #include <cstdio> #include <list> #include <cmath> #include <windows.h> using namespace std; typedef struct node { node() //构造函数 初始化数据 { x=y=0; f=h=g=0; parent=NULL; } int x,y; //坐标 这里的x对应下面的i,y对应j double f,h,g; //g表示从原点到当前节点路线的长度,h表示当前节点到目标节点的长度,f=g+h表示从原点到目标点经过当前节点的路线长度 struct node *parent; //父节点 } Node; //节点结构体(每个节点表示一个正方形小格子) const int MAX=100; const int LEN=10; //把地图分割成一个一个的正方形小格子,每个格子的长度为LEN const char ROAD=‘*‘; //最后输出的时候,‘*‘表示路线 char mmap[MAX][MAX]; //注意:‘0‘表示起点,‘1‘表示终点 int si,sj,ei,ej; //si,sj分别记录起点的x,y坐标,ei,ej分别记录终点的x,y坐标 int n,m; int dx[8]= {-1,1,0,0,-1,1,-1,1}; //8个方向 上下左右,左上,右下,右上,左下 int dy[8]= {0,0,-1,1,-1,1,1,-1}; list<Node*> startList,endList; //startList表示搜索域,endList存储已搜索过的节点 Node *start=NULL; //起点指针 //判断节点指针node 是否 在列表mlist中 bool in_List(Node * node,list<Node*> mlist) { for(list<Node*>::iterator it=mlist.begin();it!=mlist.end();it++) { if((*it)->x==node->x&&(*it)->y==node->y) { return true; } } return false; } //从列表中获取f最小的节点指针 Node* getMinNode(list<Node*> mlist) { double mmin=1000000; Node *pmmin=NULL; for(list<Node*>::iterator it=mlist.begin(); it!=mlist.end(); it++) { if((*it)->f<mmin) { mmin=(*it)->f; pmmin=(*it); } } return pmmin; } //从列表中删除节点指针 void del(Node *node,list<Node*> &mlist) { for(list<Node*>::iterator it=mlist.begin(); it!=mlist.end(); it++) { if((*it)==node) { mlist.erase(it); return; } } } //向列表中添加节点指针 void add(Node *node,list<Node*> &mlist) { mlist.push_back(node); return; } //计算(x1,y1)到(x2,y2)的距离 double getDis(int x1,int y1,int x2,int y2) { double xx1=x1*LEN+LEN/2.0; double yy1=y1*LEN+LEN/2.0; double xx2=x2*LEN+LEN/2.0; double yy2=y2*LEN+LEN/2.0; return sqrt((xx1-xx2)*(xx1-xx2)+(yy1-yy2)*(yy1-yy2)); } //回溯寻找路径 void setRoad(Node *root) { while(root->parent!=NULL) { if(root->x==ei&&root->y==ej) mmap[root->x][root->y]=‘1‘; else mmap[root->x][root->y]=ROAD; root=root->parent; } } void work() { start=new Node; start->parent=NULL; start->f=0; start->g=0; start->h=0; start->x=si; start->y=sj; add(start,startList); while(!startList.empty()) { Node *cur=getMinNode(startList); //从搜索列表中获取f最小的节点 if(cur==NULL) { cout<<"自动寻路失败"<<endl; return; } add(cur,endList); //把当前节点放入已搜索过的列表中 del(cur,startList); //从搜索列表中删除当前节点 for(int k=0; k<8; k++) //8个方向搜索 { int cx=cur->x+dx[k]; int cy=cur->y+dy[k]; if(cx<0||cy<0||cx>=n||cy>=m) //坐标越界 { continue; } else if(mmap[cx][cy]==‘#‘) //是墙 continue; Node *now=new Node; now->x=cx; now->y=cy; now->parent=cur; now->g=cur->g+getDis(now->x,now->y,cur->x,cur->y); now->h=getDis(now->x,now->y,ei,ej); now->f=now->g+now->h; if(in_List(now,startList)||in_List(now,endList)) //是否在搜索列表或已搜索列表中 continue; add(now,startList); //添加到搜索列表中 if(cx==ei&&cy==ej) //如果当前节点是终点 { setRoad(now); //回溯找路径 for(int i=0; i<n; i++) //输出地图 { for(int j=0; j<m; j++) { if(mmap[i][j]==ROAD||mmap[i][j]==‘0‘||mmap[i][j]==‘1‘) //如果是路径则输出颜色设置成绿色 { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN); } else //否则无色只以亮度显示 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY); cout<<mmap[i][j]<<" "; } cout<<endl; } return; } } } cout<<"自动寻路失败"<<endl; return; } int main() { while(cin>>n>>m) { si=sj=ei=ej=0; startList.clear(); endList.clear(); for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { cin>>mmap[i][j]; if(mmap[i][j]==‘0‘) { si=i; sj=j; } else if(mmap[i][j]==‘1‘) { ei=i; ej=j; } } } work(); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY); } return 0; }
程序测试:
输入:
8 8
````#```
````#```
````#```
`0``#``1
````#```
````#```
```##```
```#````
10 8
````#```
``#`#```
``#`#```
``#`````
``#`##``
``#`#``#
`##`#``#
`###`##1
`0##`##`
####`#``
输出结果:
绿色表示路径。
以上是关于A*寻路算法详解的主要内容,如果未能解决你的问题,请参考以下文章