A*算法;A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法。估价值与实际值越接近,估价函数取得就越好。

  公式表示为: f(n)=g(n)+h(n),其中 f(n) 是从初始点经由节点n到目标点的估价函数,g(n) 是在状态空间中从初始节点到n节点的实际代价,h(n) 是从n到目标节点最佳路径的估计代价。

  保证找到最短路径(最优解的)条件,关键在于估价函数f(n)的选取:估价值h(n)<= n到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。但能得到最优解。并且如果h(n)=d(n),即距离估计h(n)等于最短距离,那么搜索将严格沿着最短路径进行, 此时的搜索效率是最高的。如果 估价值>实际值,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。

  创建两个表,OPEN表保存所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。算起点的估价值;将起点放入OPEN表;保存路径,即从终点开始,每个节点沿着父节点移动直至起点,这就是你的路径。

  算法伪码:

  1. while(OPEN!=NULL)
  2. {
  3. OPEN表中取估价值f(n)最小的节点n;
  4. if(n节点==目标节点)
  5. break;
  6. for(当前节点n的每个子节点X)
  7. {
  8. X的估价值;
  9. if(XinOPEN)
  10. if(X的估价值小于OPEN表的估价值)
  11. {
  12. n设置为X的父亲;
  13. 更新OPEN表中的估价值;//取最小路径的估价值
  14. }
  15. if(XinCLOSE)
  16. continue;
  17. if(Xnotinboth)
  18. {
  19. n设置为X的父亲;
  20. X的估价值;
  21. 并将X插入OPEN表中;//还没有排序
  22. }
  23. }//endfor
  24. n节点插入CLOSE表中;
  25. 按照估价值将OPEN表中的节点排序;//实际上是比较OPEN表内节点f的大小,从最小路径的节点向下进行。
  26. }//endwhile(OPEN!=NULL)

  以上摘自百度百科,以下将用Perl语言实现:  

  1、建立路径数组,下标即是步数,并使用匿名哈希保存坐标点、开销、到目的地开销、实际开销、父节点等信息,数据结构如下:

    path[step]={ coordinate=>[y,x],

           cost=>0,

           next_cost=>(y-end.y)+(x-end.x),

           previous=>path[step-1],

           actual_cost=>cost+next_cost }

  2、另一个数组,下标即是坐标点,指向的匿名哈希存放OPEN、CLOSE、前一节点的状态,如: arr[y][x]->{point},方便回退时能直接获取到上一步的坐标点和状态,数据结构如下:

    arr[y][x]={ flag=>0,

          point=>arr[y-1][x-1] }

  数据结构设计好后,根据上面的伪代码实现还是比较容易:

  1. use strict;
  2. use List::Util;
  3. use constant {WIDTH=>,HEIGHT=>,DEBUG=>,};
  4. my @uldr=( ,[-,],[,-],[,],[,], ); # 上、左、下、右
  5. my @bg=();
  6. for(my $y=;$y<HEIGHT;$y++){
  7. for( my $x= ; $x<WIDTH ; $x++ ){
  8. if( $y == || $y == HEIGHT- ||
  9. $x == || $x == WIDTH- ){
  10. $bg[$y][$x] = '*';
  11. }
  12. else{
  13. $bg[$y][$x] = ' ';
  14. }
  15. }
  16. } # 初始化迷宫
  17.  
  18. my @obstruction=( [,],[,],[,],[,],[,],[,],[,],[,],[,],[,],[,],[,], ); # 障碍物坐标
  19. map{ $bg[ $obstruction[$_][] ][ $obstruction[$_][] ] = '#' } ..$#obstruction-1;
  20. $bg[ $obstruction[][] ][ $obstruction[][] ] = '@';
  21.  
  22. @bg=( ['*','*','*','*','*','*','*','*','*','*','*','*',],
  23. ['*',' ',' ',' ','#',' ',' ',' ',' ',' ',' ','*',],
  24. ['*',' ','#',' ',' ',' ',' ',' ',' ',' ',' ','*',],
  25. ['*',' ','#',' ',' ',' ','#',' ',' ',' ',' ','*',],
  26. ['*',' ','#',' ',' ',' ','#','#','#','#','#','*',],
  27. ['*',' ',' ','#',' ',' ','#',' ',' ',' ',' ','*',],
  28. ['*',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',],
  29. ['*','*','*','*','*','*','*','*','*','*','*','*',],
  30. );
  31. print @$_,"\n" foreach(@bg);
  32. my @bg_ghost=(); # 0--未经过 1--已走 2--不可通过
  33.  
  34. print "-"x15,"\n";
  35. sub caclulate_cost{
  36. my ($sp,$ep)=@_;
  37. return abs($sp->[] - $ep->[]) + abs($sp->[] - $ep->[]);
  38. }
  39. sub handle{
  40. my @path=(); # 存放步数的数组
  41. my $start=[ $obstruction[][] , $obstruction[][] ]; # 起点
  42. $start=[,];
  43. my $end=[ $obstruction[-][] , $obstruction[-][] ]; # 终点
  44. $end=[,];
  45. my ($step,$p_step,$p_gh)=(,'',''); # 步数、指向数组元素的指针、指向bg_ghost元素的指针
  46.  
  47. $path[$step]={ coordinate=>[$start->[],$start->[]],
  48. cost=>,
  49. next_cost=>&caclulate_cost( $start,$end ),
  50. previous=>,
  51. }; # 每一步保存坐标、预计开销、到目的地距离、父节点,起点开销为0
  52. $path[$step]->{actual_cost}=$path[$step]->{cost} + $path[$step]->{next_cost}; # 实际开销
  53. $bg_ghost[ $start->[] ][ $start->[] ]->{point}=''; # 起点的父节点为空
  54. while(@path){
  55. $p_step=pop(@path);
  56. print " step:$step,p_step:$p_step\n" if DEBUG;
  57. if( $p_step->{coordinate}->[] == $end->[] &&
  58. $p_step->{coordinate}->[] == $end->[] ){ # 到达目的地
  59. my @arr=('A'..'Z','a'..'z');
  60. my @temp=();
  61. while($p_step){
  62. push @temp,$p_step->{coordinate};
  63. $p_step=$p_step->{previous}; # 顺着父节点回溯,获取每个节点
  64. }
  65. @temp=reverse(@temp);
  66. foreach(..$#temp){
  67. $bg[ $temp[$_]->[] ][ $temp[$_]->[] ] = $arr[$_];
  68. }
  69. return ;
  70. } # end if
  71. $step++;
  72. for(my $cnt=;$cnt<=;$cnt++){
  73. my $y= $p_step->{coordinate}->[]+$uldr[$cnt][] ;
  74. my $x= $p_step->{coordinate}->[]+$uldr[$cnt][] ;
  75. print " ($p_step->{coordinate}->[0],$p_step->{coordinate}->[1])+($uldr[$cnt][0],$uldr[$cnt][1]),(y,x)=($y,$x)\n" if DEBUG;
  76. if( $y < || $y > HEIGHT- || $x < || $x > WIDTH- || $bg[$y][$x] eq '#' ){
  77. $bg_ghost[$y][$x]->{flag} = ; # 不可经过
  78. }
  79. if( ! $bg_ghost[$y][$x]->{flag} ){ # 未经过的
  80. $bg_ghost[$y][$x]->{flag}=; # 设置已经过
  81. $bg_ghost[$y][$x]->{point}=$p_step; # 保存前一节点状态
  82. my $px={ coordinate=>[$y,$x],
  83. cost=>$p_step->{cost}+,
  84. next_cost=>&caclulate_cost( [$y,$x],$end ),
  85. previous=>$p_step,
  86. };
  87. $px->{actual_cost}=$px->{cost} + $px->{next_cost};
  88. push @path,$px;
  89. }
  90. else{
  91. $p_gh=$bg_ghost[$y][$x]->{point};
  92. print " p_gh:$p_gh\n" if DEBUG;
  93. if($p_gh && $p_step->{cost}+ < $p_gh->{cost} ){ # 如果当前开销较小
  94. print " $p_step->{cost},$p_gh->{cost}\n" if DEBUG;
  95. $p_gh->{cost}=$p_step->{cost}+; #
  96. $p_gh->{previous}=$p_step; # 将前一个节点设置为当前节点之父
  97. $p_gh->{actual_cost}=$p_gh->{cost}+$p_gh->{next_cost}; # 更新前一节点开销
  98. }
  99. }
  100. }
  101. $bg_ghost[ $p_step->{coordinate}->[] ][ $p_step->{coordinate}->[] ]->{flag}=; # 设置已经过
  102. @path=sort{$b->{actual_cost}<=>$a->{actual_cost}}@path; # 排序,开销最小的放在最后
  103. }
  104. return ;
  105. }
  106. &handle;
  107. print @$_,"\n" foreach(@bg);

  计算出来的最短路径:

    

  比较一下深度优先算法:

    

  

  

  

  

Perl寻路A*算法实现的更多相关文章

  1. 游戏寻路A*算法

    A*算法是一种启发式的BFS,目的就是找到到达目标位置的最短路径.启发式函数如下: f(x) = g(x) + h(x) g(x)是对出发点到达当前点距离的估约,h(x)是当前点到终点距离的估约.算法 ...

  2. A*寻路算法的探寻与改良(一)

    A*寻路算法的探寻与改良(一) by:田宇轩                                                                    第一部分:这里我们主 ...

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

    PHP树生成迷宫及A*自己主动寻路算法 迷宫算法是採用树的深度遍历原理.这样生成的迷宫相当的细,并且死胡同数量相对较少! 随意两点之间都存在唯一的一条通路. 至于A*寻路算法是最大众化的一全自己主动寻 ...

  4. 数据结构和算法总结(三):A* 寻路算法

    前言 复习下寻路相关的东西,而且A star寻路在游戏开发中应用挺多的,故记录下. 正文 迪杰斯特拉算法 说起A*得先谈谈Dijkstra算法,它是在BFS基础上的一种带权值的两点最短寻路贪心算法. ...

  5. 基于Unity的A星寻路算法(绝对简单完整版本)

    前言 在上一篇文章,介绍了网格地图的实现方式,基于该文章,我们来实现一个A星寻路的算法,最终实现的效果为: 项目源码已上传Github:AStarNavigate 在阅读本篇文章,如果你对于里面提到的 ...

  6. Unity实现A*寻路算法学习2.0

    二叉树存储路径节点 1.0中虽然实现了寻路的算法,但是使用List<>来保存节点性能并不够强 寻路算法学习1.0在这里:https://www.cnblogs.com/AlphaIcaru ...

  7. 关于php Hash算法的一些整理总结

    最近在公司内部的分享交流会上,有幸听到了鸟哥的关于php底层的一些算法的分享,虽然当时有些问题没有特别的明白,但是会后,查阅了各种各样的相关资料,对php的一些核心的hash算法有了进一步的理解和认识 ...

  8. 一步一步写算法(之 A*算法)

    [ 声明:版权全部,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 在前面的博客其中,事实上我们已经讨论过寻路的算法.只是,当时的演示样例图中,可选的路径是唯一的 ...

  9. JS - A*寻路

    算法核心 A*估值算法 寻路估值算法有非常多:常用的有广度优先算法,深度优先算法,哈夫曼树等等,游戏中用的比较多的如:A*估值 算法描述 对起点与终点进行横纵坐标的运算 代码实现 start: 起点坐 ...

随机推荐

  1. LINQ to Entities 不识别方法“System.String ToString(System.String)”,因此该方法无法转换为存储表达式。

    来源:https://www.cnblogs.com/hao-1234-1234/p/9112434.html 6  Select的时候,时间无法转换成 年月日  YYMMMdd 报错:LINQ to ...

  2. python02---基础数据类型

    python02---基础数据类型 一. 什么是数据类型 我们人类可以很容易的分清数字与字符的区别,但是计算机并不能呀,计算机虽然很强大,但从某种角度上看又很傻,除非你明确的告诉它,1是数字,&quo ...

  3. Python学习日记(十八) 序列化模块

    什么是序列? 就是每一个元素被有序的排成一列 什么是序列化? 就是将原本的列表.字典等内容转化成字符串的过程 什么时候会用到序列化? 数据存储(把数据放在文件.数据库),网络传输等 序列化的目的 1. ...

  4. [archlinux][tls] archlinux下使curl支持sslv3的方法

    描述 在archlinux下,希望使用curl产生一条使用sslv3的https访问请求. 使用curl的如下命令: curl -k -vvv --sslv3 https://192.168.7.9: ...

  5. shell文件比较运算符

    1.文件比较运算符 -e filename 如果 filename 存在,则为真 [ -e /var/log/syslog ] -d filename 如果 filename 为目录,则为真 [ -d ...

  6. python的简介(解释器、变量、用户交互、if语句)

    一.python的起源 python是吉多·范罗苏姆(Guido van Rossum)在1989年的圣诞节期间因为无聊打发时间所开发的一个脚本解释程序. python是一门解释型.弱类型的编程语言. ...

  7. C#使用托管程序连接Oracle数据库(Oracle.ManagedDataAccess.dll)

    一.概述 Oracle Data Provider for  .NET, Managed Driver: Oracle官方的托管数据库访问组件,单DLL,Oracle.ManagedDataAcces ...

  8. java singleton(单例设计模式)

    单例设计模式的主要作用是: 1.控制资源的使用,我们对资源使用线程同步来实现并发访问. 2.节约资源,我们对一个类只进行一个实例化进行全局的资源访问,节约了内存. 3.作为通信媒介,也是数据共享,可以 ...

  9. H3CNE学习1 课程简介

    一.认证对比 二.企业网架构

  10. COM Error---HRESULT

    一.COM Error 调用COM接口产生的错误.几乎所有的COM函数和接口方法都返回类型为HRESULT的值.HRESULT(用于结果句柄)是返回成功.警告和错误值的一种方法.HRESULTs实际上 ...