zoukankan      html  css  js  c++  java
  • BFS寻路算法的实现

    关于BFS的相关知识由于水平有限就不多说了,感兴趣的可以自己去wiki或者其他地方查阅资料。

    这里大概说一下BFS寻路的思路,或者个人对BFS的理解:

    大家知道Astar的一个显著特点是带有启发函数,换句话说,Astar尝试以人的思维来去寻找一段路径。而BFS则没有这种聪明劲,他看起来更中规中矩,老实巴交,更像是机器人的风格。

    简单的说,BFS为了找到一条路径,他从起点开始,然后是身边的邻居,然后是邻居的邻居,一个一个的搜查,直到搜到终点(寻路成功),或者把整个地图搜索完(除非最后一个点就是终点,否则寻路失败)。

    可能乍看上去BFS真的比较笨,但是他也并没有笨的不着边际,因为他最多把整个地图都搜一遍,这样,对于一张有限的地图,他寻找一段路径所花的时间也是相对的有一个上限。

    但Astar则不同,Astar虽然看起来带有聪明劲,但是这种聪明只是一种自作聪明,有时候,对于一些设计特殊的地图,Astar要为自己的聪明付出很大的代价。比如带有半岛的地图。

    总体上看,Astar在障碍越少的情况下寻路越快,而BFS则比较平缓,不管障碍多少,他快慢幅度并不大。

    废话不多说,下面用代码来说明BFS的思路:

    01.public function tryFindPath(sx:int, sy:int, ex:int, ey:int):Boolean  
    02.{  
    03.    var start:uint = getTimer();  
    04.      
    05.    _startNode = _mapData.setStartNode(sx,sy);  
    06.    _endNode = _mapData.setEndNode(ex,ey);  
    07.      
    08.    if(_startNode == _endNode) return false;  
    09.    if(!_endNode.walkable) return false;  
    10.      
    11.    var i:uint=0;  
    12.    _startNode.f = i;  
    13.    var queue:MinHeap = new MinHeap(100);  
    14.    queue.Enqueue(_startNode);  
    15.    var neighbor:Node;  
    16.    var testedNodes:Dictionary = new Dictionary();  
    17.      
    18.    while(queue.size>0)  
    19.    {  
    20.        var testNode:Node = queue.Dequeue() as Node;  
    21.        i++;  
    22.        var x:int,y:int;  
    23.        for(var dx:int=-1;dx<=1;++dx)  
    24.        {  
    25.            x = testNode.x + dx;  
    26.            for(var dy:int=-1;dy<=1;++dy)  
    27.            {  
    28.                y = testNode.y+dy;  
    29.                neighbor = _mapData.getNode(x,y);  
    30.                if(!neighbor) continue;  
    31.                if(!neighbor.walkable) continue;  
    32.                if(testedNodes[neighbor]) continue;  
    33.                testedNodes[neighbor] = true;  
    34.                neighbor.parent = testNode;  
    35.                neighbor.f = i;  
    36.                if(neighbor == _endNode)  
    37.                {  
    38.                    return true;  
    39.                }  
    40.                  
    41.                queue.Enqueue(neighbor);  
    42.            }  
    43.        }  
    44.    }  
    45.    return false;  
    46.}

    这里并没有给出全部相关的源码,该方法只展示一个思路:

    _mapData是对一个二维网格地图数据做了一个封装,包括设置起始点,终点,根据索引获取节点等。

    Node是一个节点对象,他有xy的属性和一个f属性,跟Astar的代价属性类似。

    queue是一个最小堆,他保证f值越小的Node对象越靠近队列的顶部。

    testedNodes用来记录节点是否被搜寻过。

    其寻路过程为:

    1,将起点放入队列;

    2,弹出队列中的最小代价的节点,搜寻他周围的有效节点(即存在,可走,而且没有被检查过),设置代价值,和父节点,如果这个节点就是终点,那么寻路成功,否则将此节点放入队列,在检查下一个邻居节点,如果所有的邻居节点都不是终点则进入3;

    3,如果队列空了,那么说明所有的节点都检查过了,没有找到终点,否则继续2。

    BFS的这种平缓特性在有些时候看起来似乎可以弥补Astar的缺陷,比如我们想在长程情况下采用BFS而短程的时候用Astar,但是这并不总是合适的,因为Astar并不是因为路程长才耗时,而是因为地形复杂,而地形复杂又没有一个可以衡量的指标,只能人为的去判断,所以最多我们通过人为的配置来选择寻路的方式。

  • 相关阅读:
    读写文件流
    关闭和退出窗口
    有什么问题?
    将aspx页面转换成htm页面
    读取rss聚合文件
    运算符重载实例
    委托
    将 Visual Studio .NET 调试器用于 ASP.NET 应用程序
    输入的字符串进行有规则的清洗
    几个常用的数据库连接字符串
  • 原文地址:https://www.cnblogs.com/regalys168/p/3599155.html
Copyright © 2011-2022 走看看