zoukankan      html  css  js  c++  java
  • 用简单直白的方式讲解A星寻路算法原理

    很多游戏特别是rts,rpg类游戏,都需要用到寻路。寻路算法有深度优先搜索(DFS),广度优先搜索(BFS),A星算法等,而A星算法是一种具备启发性策略的算法,效率是几种算法中最高的,因此也成为游戏中最常用的寻路算法。

    直入正题:

    在游戏设计中,地图可以划分为若干大小相同的方块区域(方格),这些方格就是寻路的基本单元。

    在确定了寻路的开始点,结束点的情况下,假定每个方块都有一个F值,该值代表了在当前路线下选择走该方块的代价。
    而A星寻路的思路很简单:从开始点,每走一步都选择代价最小的格子走,直到达到结束点。

    A星算法核心公式就是F值的计算:
    F = G + H

    F - 方块的总移动代价
    G - 开始点到当前方块的移动代价
    H - 当前方块到结束点的预估移动代价

    以下详细解释这个公式,方便更好地理解它。

    G值是怎么计算的?
    假设现在我们在某一格子,邻近有8个格子可走,当我们往上、下、左、右这4个格子走时,移动代价为10;当往左上、左下、右上、右下这4个格子走时,移动代价为14;即走斜线的移动代价为走直线的1.4倍。
    这就是G值最基本的计算方式,适用于大多数2.5Drpg页游。

    基本公式:
    G = 移动代价

    根据游戏需要,G值的计算可以进行拓展。如加上地形因素对寻路的影响。格子地形不同,那么选择通过不同地形格子,移动代价肯定不同。同一段路,平地地形和丘陵地形,虽然都可以走,但平地地形显然更易走。
    我们可以给不同地形赋予不同代价因子,来体现出G值的差异。如给平地地形设置代价因子为1,丘陵地形为2,在移动代价相同情况下,平地地形的G值更低,算法就会倾向选择G值更小的平地地形。

    拓展公式:
    G = 移动代价 * 代价因子

    H值是如何预估出来的?
    很显然,在只知道当前点,结束点,不知道这两者的路径情况下,我们无法精确地确定H值大小,所以只能进行预估。
    有多种方式可以预估H值,如曼哈顿距离、欧式距离、对角线估价,最常用最简单的方法就是使用曼哈顿距离进行预估:
    H = 当前方块到结束点的水平距离 + 当前方块到结束点的垂直距离

    题外话:A星算法之所以被认为是具有启发策略的算法,在于其可通过预估H值,降低走弯路的可能性,更容易找到一条更短的路径。其他不具有启发策略的算法,没有做预估处理,只是穷举出所有可通行路径,然后从中挑选一条最短的路径。这也是A星算法效率更高的原因。

    每个方块的G值、H值是怎么确定的呢?
    G值 = 父节点的G值 + 父节点到当前点的移动代价
    H值 = 当前点到结束点的曼哈顿距离

    最后,A星算法还需要用到两个列表:
    开放列表 - 用于记录所有可考虑选择的格子
    封闭列表 - 用于记录所有不再考虑的格子

    以上就是要完成A星算法所需要的东西,而算法的过程并不复杂。

    A星算法伪码:
    a、将开始点记录为当前点P
    b、将当前点P放入封闭列表
    c、搜寻点P所有邻近点,假如某邻近点既没有在开放列表或封闭列表里面,则计算出该邻近点的F值,并设父节点为P,然后将其放入开放列表
    d、判断开放列表是否已经空了,如果没有说明在达到结束点前已经找完了所有可能的路径点,寻路失败,算法结束;否则继续。
    e、从开放列表拿出一个F值最小的点,作为寻路路径的下一步。
    f、判断该点是否为结束点,如果是,则寻路成功,算法结束;否则继续。
    g、将该点设为当前点P,跳回步骤c。

    后续优化

    以上就是A星算法最基本的原理,明白了基本原理,用2,3百行代码写出一个可用的A星算法并不难。当然A星算法在实际应用中不仅于此,还可以对细节进行优化:

    1、选择排序更快的二叉树来作为开放列表,帮助我们更快地从开放列表中取出F值最小的点;

    2、对何种情况下可以走斜线路径加以判断;

    3、采用布兰森汉姆算法预先判断两点是否可以直接通行,可通行就直接返回两点的直线路径,不可直接通行再采用A星算法寻路,提高寻路效率;

    4、A星算法得出寻路路径后,可采用弗洛伊德算法对路径进行平滑处理,使人物走动更为自然


    这里只是用语言讲解A星算法原理,并没有配图讲解整个寻路的过程,希望进一步直观理解整个过程的,推荐参考下面两个网友翻译过来的A星教程

    http://www.raywenderlich.com/zh-hans/21503/a%E6%98%9F%E5%AF%BB%E8%B7%AF%E7%AE%97%E6%B3%95%E4%BB%8B%E7%BB%8D

    http://www.cppblog.com/mythit/archive/2009/04/19/80492.aspx

  • 相关阅读:
    完美解决Python与anaconda之间的冲突问题
    ansible之roles
    ansible剧本之playbook操作
    git从远程仓库拉取内容或向远程仓库上传内容
    python操作excel
    nginx基于uwsgi部署Django
    第二篇:版本控制git之分支
    笔试题92-101
    Django总结
    笔试题70-91
  • 原文地址:https://www.cnblogs.com/leoin2012/p/3899822.html
Copyright © 2011-2022 走看看