A*寻路算法所生成的路径

本文目的是对A*寻路算法所生成的路径进行一些人性化的调整,使其看起来不至于太机械化。关于A*算法的原理与实现,读者可以阅读其他资料,这里不再详细阐述。

如何写估价函数

A*寻路算法本质上是一个有方向性的广度优先搜索算法,它使用一个估价函数,来估测可能的最短路径,在每一次搜索迭代完成后,选取其邻接点中最优的一个(即,距离终点最近的一个点),作为下一次迭代的起点。如此反复,直到找到终点。下面先列出估价函数的常规写法:

设i点到起点的价值为S,到终点的估价为E,i点的总估价G等于S+E。S的值是确定的:

[cpp] view plain copy 

  1. S = parent.S + 1(i点是其父节点的水平或垂直方向上的邻接点)
  2. S = parent.S + sqrt(2))(i点是其父节点斜方向上的邻接点)

E点的值需要估算。精确一点的写法:

[cpp] view plain copy 

  1. 水平距离:dx = abs(ix - ex)
  2. 垂直距离:dy = abs(iy - ey)
  3. 需要斜着走过的距离:v1 = min(dx, dy) * sqrt(2)
  4. 需要直线走过的距离:v2 = max(dx, dy) - min(dx, dy)
  5. E =  v1 + v2

粗略的写法:

[cpp] view plain copy 

  1. E = abs(ix - ex) + abs(iy - ey)

如何避免转向抖动

A*寻路得到的结果是最优的,但不是唯一的,这源于两点之间最近的路线可能不只一条。那么问题就产生了,两条最佳路线距离都相等的情况下,哪一条会更好?

   

(红色是障碍,白色可通行,黑色是搜索路径)

如上图所示,是A* 8方向搜索得到的两条距离相等的路线,但是左图的路线在中间位置发生了“拐弯”,要比右图的路线多一个“拐弯”。如果路线上拐弯太多,人物行走的过程中,会出现频繁转向,从而出现“抖动”现象。所以,我们判定右图路线优于左图路线。针对这一问题,我们可以通过修改估价函数,来选择“拐弯”更少的路线。

拐弯的问题,可以简化成先尽可能的向一个方向走,然后再考虑转向。进一步简化成,点越接近起点或是终点,越优先考虑。我们给E加上一个干扰值factor,

[cpp] view plain copy 

  1. factor = min(abs(ix - sx), abs(ix - ex)) + min(abs(iy - sy), abs(iy - ey))
  2. factor *= 0.01

factor的值不能过大,否则会造成搜索结果不是最短距离,因此适当的给factor乘上一个缩放系数。

如何远离障碍物

A*寻路的效果是抄近道,走捷径。但对于游戏体验来说,这并不完全是件好事,放着宽阔的马路不走,非得走悬崖峭壁,一不小心就跌落万丈深渊,或者卡在岩石边上。那么,我们该如何避免这些现象呢?同样,我们可以通过修改估计函数做到。

我们给每一块可走区域都加上一个干扰值,越靠近障碍的可走区域,其干扰值越大。干扰值计算方法:

[cpp] view plain copy 

  1. factor = 0
  2. for(x = -n; x <= n; ++x)
  3. {
  4. for(y = -n; y <= n; ++y)
  5. {
  6. if(isObstacle(ix + x, iy + y))
  7. {
  8. factor += n - min(abs(x), abs(y))
  9. }
  10. }
  11. }

我们甚至可以根据地表的材质来增加干扰值,比如山路和沼泽地带明显比马路的干扰值大。

后记

总之,我们可以调节估价函数来达到不同的效果。但是,也不能随意修改,不良的估价函数,会增加搜索成本。

时间: 2024-08-04 11:58:05

A*寻路算法所生成的路径的相关文章

PHP树生成迷宫及A*自己主动寻路算法

PHP树生成迷宫及A*自己主动寻路算法 迷宫算法是採用树的深度遍历原理.这样生成的迷宫相当的细,并且死胡同数量相对较少! 随意两点之间都存在唯一的一条通路. 至于A*寻路算法是最大众化的一全自己主动寻路算法 完整代码已上传,http://download.csdn.net/detail/hello_katty/8885779 ,此处做些简单解释,还须要大家自己思考动手.废话不多说,贴上带代码 迷宫生成类: /** 生成迷宫类 * @date 2015-07-10 * @edit http://w

5 X 5 方阵引出的寻路算法 之 路径遍历(完结)

??此篇文章源自对一个有趣问题的思考,在我的另一篇博文<一个有趣的 5 X 5 方阵一笔画问题>中有详细介绍.在已知其结论的情况下,作为程序员的我,还是想利用该问题当做出发点,写一个可以遍历所有"可能路线"的寻路算法,当做学习"图"相关算法的练习.如果对那个原始问题有兴趣,点击上面的文章链接,出门右转便是. 一.问题回顾 ??还是要简单描述一下问题:有一个 5 X 5 的点方阵,如下图,要想用一笔画将所有的蓝色点连起来,是否有可行路线.需要满足3点要求:

ActionScript 3.0 实现的A*寻路算法源代码

首先是文档类Index.as: package code{ import flash.display.Sprite; import flash.text.TextField; import flash.text.TextFormat; public class Index extends Sprite{ private var road:Road; public function Index(){ stage.align = "TL"; stage.scaleMode = "

关于A*寻路算法的认识

最近要参加学校的APP比赛,我们组做的是一个3D迷宫的小APP,我负责的是迷宫的生成与寻路. 寻路算法选择的是A*寻路算法,具体参考的是下面的这篇博客. 本文主要是谈谈自己对A*算法的理解,具体细节,上文链接以及讲的很详细了. http://www.cnblogs.com/technology/archive/2011/05/26/2058842.html 关于A*算法的实现我是用的广度优先搜索这种比较常见的实现模式. 那么关于这两者之间的关系是怎么样呢? 个人理解的是A*算法其实是一种带有路径

A星寻路算法以及C++实现

A星寻路算法真是我一生接触的第一个人工智能算法了... A星寻路算法显然是用来寻路的,应用也很普遍,比如梦幻西游...算法的思路很简单,就是在bfs的基础上加了估值函数. 它的核心是 F(x) = G(x) + H(x) 和open.close列表: G(x)表示从起点到X点的消耗(或者叫移动量什么的),H(X)表示X点到终点的消耗的估值,F(x)就是两者的和值.open列表记录了可能要走的区域,close列表记录了不会再考虑的区域.我们每次都选F值最小的区域搜索,就能搜到一条到终点的最短路径,

简简单单的寻路算法

今天搞了寻路算法   搞了好久  唉  瞬间感觉智商捉急啊  = = 直接上代码咯 主函数: // 随机生成一个10*10的迷宫(可以用*表示起点,#表示终点,0代表不可以通过,1代表可以通过),假如[0,0] 为入口 [9,9] 为出口. // (1)在控制台上显示该迷宫 // (2)利用栈结构求解该迷宫是否能抵达出口(入口与出口是否联通). // (3)如能抵达出口,输出从入口到出口的行走路径. Maze maze = new Maze(); maze.Show(); maze.Find()

A星寻路算法-(入门级)

你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法的文章,但是大部分都是提供给已经了解基本原理的高级开发者的. 本篇教程将从最基本的原理讲起.我们会一步步讲解A星寻路算法,幷配有很多图解和例子. 不管你使用的是什么编程语言或者操作平台,你会发现本篇教程很有帮助,因为它在非编程语言的层面上解释了算法的原理. 现在找下到达一杯咖啡因饮料和美味的零食的最

寻路算法A*, JPS(跳点搜索)的一些杂谈

A*是一个比较经典的启发式寻路算法.是基于dijkstra算法,但是加入了启发函数,使路径搜索效率更高.实现起来很简单.不过要做到通用性高,比如支持各种不同类型的地图,甚至不仅仅是地图,而是个图结构如解决拼图游戏N-puzzle会用到的,就需要多花点心思.用C++实现的话,可以使用模板来适应不同的需要.也可以使用类继承. template <typename NodeType, typename CostType, typename Heuristic> static vector<No

C#实现简单的AStar寻路算法

1.算法实施模型 在我看来,最简单最基础的寻路环境是:在一片二维网格区域中存在一些围墙(Block),在起始点和终点之间保持连通的前提下寻找一条最佳路径. 2.算法原理 详细介绍有很多,可参考网址:http://www.policyalmanac.org/games/aStarTutorial.htm,浅显易懂,重点是理解"启发式搜索"的概念.下面谈谈我自己的理解,如果是第一次接触A*寻路算法,还是先老老实实看完给出的参考网址吧(当然也可以参考相关的中文介绍资料). 在一片二维网格中,