A 星寻路算法实现的细节
来源:互联网 发布:最优化理论与算法ppt 编辑:程序博客网 时间:2024/06/05 03:17
本站文章均为 ftyszyx 原创,转载务必在明显处注明: 原文链接: http://blog.csdn.net/ftyszyx/article/details/9019763
最近学习了A星寻路算法,于是自己照着网上的思路写了一个,发现理论看起来简单,但是真正实现起来,发现很多细节没有注意到,导致最终错误,因此在此记录,以备以后查用。
首先说下A星算法的思路:
添加起始节点到open列表中
循环做以下事情:(退出循环的条件是,open列表为空,获得者S为终点)
1. 将方块添加到open列表中,该列表有最小的和值。且将这个方块称为S吧。
2. 将S从open列表移除,然后添加S到closed列表中。
3. 对于与S相邻的每一块可通行的方块T:
· 如果T在closed列表中:不管它。
· 如果T不在open列表中:添加它然后计算出它的和值。
· 如果T已经在open列表中:当我们使用当前生成的路径到达那里时,检查F 和值是否更小。如果是,更新它的和值和它的前继。
退出循环后,在close列表中,延目的节点的父节点一直反溯到起始节点,即可求得最终路径。
这里面,我觉得要注意以下几点:
1、open和close的数据结构推荐用list,因为程序执行过程中要经常的做插入节点操作
2、open列表的排序,我觉得用插入排序较好(因为插入新节点时,open列表原来的数据是有序的),可以在节点插入open列表时进行,
3、在open列表增加新节点时,如果插入时发现原列表中有节点的f值和自己相同,应该将新插入的节点放在前面(原则就是排在前面的尽量是最近插入的节点)
4、退出循环时,是通过close列表的最后一个节点(也就 是终点)回溯到起点求得路径,而不是把close表中的所有节点当作路径。这点要注意,我就在这里范过错。
下面附上自己的一些部分代码:
主要有三个函数findpath:寻路入口函数 JudgeNode:判断相信方块,主要实现上面的第3步 addToOpen:将节点加入到open表中(插入排序)
findpath(){//加入第一个结点 AstarItem * temp1 = new AstarItem();m_open->addObject(temp1);temp1->setpos(m_curRow,m_curCol);temp1->setg(0);int ag = getH(m_curRow,m_curCol);temp1->seth(ag);temp1->setfid(0);temp1->setf(ag); //遍历寻找路径while(m_open->count() !=0){//open里面没数据//在open里面找最小的f值AstarItem * min=(AstarItem *)m_open->objectAtIndex(0);int minCol=min->getcol();int minRow=min->getrow();//将该节点加入到close中,并从open中移除m_close->addObject(min);m_open->removeObjectAtIndex(0);if (minCol==m_aimCol &&minRow==m_aimRow){//到终点了foundpath=true;break;}//查找与s相邻的区块 int fatherid = m_close->count() - 1; //对周围的8个相邻节点做判断 JudgeNode(minRow-1,minCol,fatherid); JudgeNode(minRow,minCol-1,fatherid); JudgeNode(minRow,minCol+1,fatherid); JudgeNode(minRow+1,minCol,fatherid);// if(checkmap()) /* JudgeNode(minRow+1,minCol+1,fatherid); JudgeNode(minRow-1,minCol-1,fatherid); JudgeNode(minRow-1,minCol+1,fatherid); JudgeNode(minRow+1,minCol-1,fatherid); */}//算法结束 //获得路径if(foundpath == false){ m_path=NULL;}else{//延着终点节点遍历m_path = new CCArray(); AstarItem * temp2=(AstarItem * )(m_close->lastObject()); // m_path->addObject(temp2); while(temp2->getfid()!=0) { m_path->insertObject(temp2,0); //取下一个 temp2=(AstarItem *)(m_close->objectAtIndex(temp2->getfid())) ; } m_path->insertObject(temp2,0); m_path->insertObject(temp1,0);//第一个点}}
//判断周围的结点void JudgeNode(int row,int col,int fatherid){ int tempindex; if(true!=checkmap(row,col)) {//不合格的位置return ; } if(checkclose(row,col)==true) {//close表中有就跳过 return; } tempindex=checkOpen(row,col,fatherid); if(tempindex!=-1) { //原来就在open列表中,更新open列表的值 int g = getG( row, col,fatherid); int h = getH( row,col); if (((AstarItem *)m_open->objectAtIndex(tempindex))->getf()>g+h) { //说明新的路径更短 ((AstarItem *)m_open->objectAtIndex(tempindex))->setf(g+h);((AstarItem *)m_open->objectAtIndex(tempindex))->setg(g);((AstarItem *)m_open->objectAtIndex(tempindex))->seth(h);((AstarItem *)m_open->objectAtIndex(tempindex))->setfid(fatherid); } return; } else { //直接将此节点加入 addToOpen(row,col,fatherid); }}
//添加一个节点到open中 插入时按从小到大排列//注意,如果遇到相等的值,就将最新的元素插在前面。bool addToOpen(int row,int col,int id){ //向open列表中加入点 AstarItem * temp = new AstarItem();temp->setpos(row,col);temp->setfid(id);int g = getG( row,col, id);int h = getH(row,col);temp->setg(g);temp->seth(h);temp->setf(g + h);int i=m_open->count()-1;// 从后向前遍历while(i>=0){if(((AstarItem*)(m_open->objectAtIndex(i)))->getf()>=temp->getf())//当前位置的点比我大,就找下一个{i--;continue;}else//找到一个f值小于等于自己的{i++;//插在这个数后面break;}}if (i<0){i=0;}m_open->insertObject(temp,i);return true;}
- A 星寻路算法实现的细节
- 算法实现的细节
- 实现反向传播算法的细节
- A*算法的实现
- A星寻路算法的Lua实现
- A*算法的C#实现
- A*算法的AS实现
- A*算法的C++实现
- A星寻路算法C++实现
- const的实现细节
- Spider的实现细节
- 线程的实现细节
- 数据结构的实现细节
- Layer的实现细节
- 算法库的使用细节
- KMP算法的一些细节
- 游戏寻路算法A*的实现
- A*算法的最短路径实现!
- IOS 自定义字体
- 深入理解Java内存模型(五)——锁
- 64位驱动开发及驱动签名
- C++lambda表达式权威指南
- ImageButton动态旋转效果
- A 星寻路算法实现的细节
- 分布式数据库系统
- CSS的z-index设置不生效的原因
- 使用srvany.exe将任何程序作为Windows服务运行
- 深入理解Java内存模型(六)——final
- EAS BOS 实现自动换行
- 瑞萨借SuperH系列在电机控制领域表现优异
- 通过当前日期获取周初、月初、月末日期
- EDI