前言:并在相当长的时间没有写blog该,我觉得有点“颓废”该,最近认识到各种同行,也刚刚大学毕业,我认为他们是优秀的。认识到与自己的间隙,有点自愧不如。我没有写blog当然,部分原因是由于工作。最初体验上有点欠缺,,原本国庆回去就要把这个寻路的功能改进一下,结果第一次去女朋友家了就没碰电脑,回上海来的第一个夜晚满脑子全是心事。早上凌晨四点就在床上辗转睡不着了,这个月随着项目的进行感觉压力也越来越大,上班时期天天六点多就醒了睡不着,希望挺过这段适应期。

关于寻路问题。在几个月之前一次面试就碰到。面试官叫我上机写出这个算法。由于之前没看过A*,仅仅是有这个概念,所以仅仅能凭着自己的思路来暂时编写。最后憋出了一段后来主动跟面试官说名能够用A*算法来实现,最后还是我的坚持打动了面试官。今天又碰到相同的问题,也让我纠结了一两天,再次写下寻路的学习心得。

一、问题概述

游戏中有敌我两方,有四十个方格。当轮到我方武将行动的时候,要先显示出我方武将能够行动的方位,这个就涉及到我方武将的行动力的大小来决定,预先做出路径的预算。这里还要考虑敌方以及地标(比如:炸弹、势头)的阻挡,以及特殊方格对武将行动力的消耗以及敌方的间隔阻挡规则。

当碰到这个问题的时候,问老大选择用什么寻路算法。他推荐的是Dijstra算法。但我看了之后感觉还不是非常适合我的需求。第一:我认为Dijstra算法是有向图的最佳路径选择。节点之间路径长度必须先知晓,但我这里四十个方格假设要两两制定感觉略微复杂,而且随着武将的移动,地图还是时时变化的,感觉更复杂。第二:Distra算法没有阻挡考虑。当然也能够记录若干路径然后考虑阻挡选择最优路径,我感觉也稍复杂。

然而我的第一反应该需求A*算法挺接近的,然后咨询老大,老大说A*方格之间距离必须要均等不然比較复杂。然后再咨询公司其它稍有经验同事,当然各有个的说法,什么深度、广度遍历,感觉没一个确定的说法。

让我选择就纠结了一天,不敢轻易选择,假设稍有考虑不慎。说不定就要做几天白用工,但最后我还是坚持自己的想法用A*来实现。

二、关于A*

A*通用的计算公式F=G+H
G:表示从起点A移动到网格上指定方格的移动耗费(我这里没考虑斜方向移动),也可理解为节点的权重
H:表示从制定方格移动到终点B的估计耗费,这里一般就是计算距离*系数

三、寻路思想

1.从起点A開始。把它加入到"开启列表"
2.寻找A点可到到的周围四个点,这里可到达是指没有阻挡而且已经不再关闭列表中的节点。并把他们加入进开启列表。并设置他们的父节点为A
3.从开启列表中删除A点并加入进关闭列表中,关闭列表就是存放的不须要检測的方格节点
4.检查它全部相邻而且合一到达的方格,假设这些方格还不再开启列表里的话就把他们加入开启列表。计算这些方格的GHF值并设置它的父节点
5.假设某个相邻方格 D 已经在 "开启列表" 里了, 检查假设用新的路径 (就是经过C 的路径) 到达它的话, G值是否会更低一些, 假设新的G值更低, 那就把它的 "父方格" 改为眼下选中的方格 C, 然后又一次计算它的 F 值和 G 值 (H 值不须要又一次计算, 由于对于每一个方块, H 值是不变的). 假设新的 G 值比較高, 就说明经过 C 再到达 D 不是一个明智的选择, 由于它须要更远的路, 这时我们什么也不做
6.当发现开启列表中有终点目标方格的时候则说明路径已经找到。
关于具体的图解能够參考其它网友的具体解释,我这里就不具体写了。

四、找回路径

我们找到最后一个点的时候然后层层往之前找到他的父节点迭代到最后不为空结束

五、数据结构

Point类
  1. module('Point', package.seeall)
  2. -- require("script/battle/BattleCommon")
  3. --计算F
  4. function CalcF( point )
  5. point.F = point.G + point.H
  6. end
  7.  
  8. function create( posId )
  9. local point = {}
  10. point.parentPoint = {}
  11. point.step = 1 --用于计算h
  12. local x,y = BattleCommon.convertPosIdToCoord(posId)
  13. point.F = 0
  14. point.G = 0
  15. point.H = 0
  16. point.X = y --point.X范围[1,5]
  17. point.Y = x --point.Y范围[1,8]
  18. point.posId = posId
  19. point.CalcF = CalcF
  20.  
  21. return point
  22. end
  23.  
  24. return Point

地形(Maze)结构

  1. --依据一个table创建一个地形
  2. function create( tb )
  3. local maze = {}
  4. maze.step = 1 --格子与格子的基本距离,用于计算H
  5. maze.mazeArray = tb
  6. maze.openList = TabledArray.create() --开启列表
  7. maze.closeList = TabledArray.create() --关闭列表
  8. maze.findPath = findPath
  9. return maze
  10. end

六、主要代码

  1. module('Maze', package.seeall)
  2. require("script/battle/TabledArray")
  3. require("script/battle/BattleCommon")
  4. require ("script/battle/Point")
  5.  
  6. -- --获取列表中F值最小的点
  7. function getMinPoint( pointsList )
  8. local minPoint = pointsList.tbl[1]
  9. for i = 1,pointsList:getSize() do
  10. if minPoint.F > pointsList.tbl[i].F then
  11. minPoint = pointsList.tbl[i]
  12. end
  13. end
  14. return minPoint
  15. end
  16.  
  17. -- --检測是否有阻挡,没有阻挡为true
  18. function checkBlock( maze,x,y,roleFlag) --x范围[1,5] y范围[1,8]
  19. if roleFlag == BattleCommon.BATTLE_GROUP_ALLIES then --我方阵营
  20. if maze.mazeArray[x][y][1] == 0 or maze.mazeArray[x][y][1] == 1 then
  21. return true --没有阻挡
  22. else
  23. return false
  24. end
  25. elseif roleFlag == BattleCommon.BATTLE_GROUP_ENEMY then
  26. if maze.mazeArray[x][y][1] == 0 or maze.mazeArray[x][y][1] == 2 then
  27. return true --没有阻挡
  28. else
  29. return false
  30. end
  31. end
  32. end
  33.  
  34. -- --列表中是否包括x,y的点
  35. function existsXY( list,x,y )
  36. if list:getSize()>0 then
  37. for i,point in pairs(list.tbl) do
  38. if point.X == x and point.Y == y then
  39. return true
  40. end
  41. end
  42. end
  43. return false
  44. end
  45.  
  46. --列表中是否包括某个点
  47. function existsPoint( list,point )
  48. for i, p in pairs(list.tbl) do
  49. if (p.X == point.X) and (p.Y == point.Y) then
  50. return true
  51. end
  52. end
  53. return false
  54. end
  55.  
  56. -- --检測能达到的点
  57. function canReach( maze,startPoint,x,y,roleFlag)
  58. if (not checkBlock(maze,x,y,roleFlag)) or existsXY(maze.closeList,x,y) then --关闭列表中包括这个点或者有阻挡
  59. return false
  60. else
  61. if (math.abs(x-startPoint.X)+math.abs(y-startPoint.Y) == 1 ) then
  62. return true
  63. end
  64. end
  65. end
  66.  
  67. -- --获取相邻的点
  68. function getSurroundPoints( maze,point,roleFlag )
  69. local surroundPoints = TabledArray.create()
  70. for i = point.X - 1 ,point.X + 1 do
  71. for j=point.Y - 1,point.Y + 1 do
  72. if i>0 and i<6 and j > 0 and j < 9 then --排除超过表姐
  73. if BattleCommon.distanceFromTo(point.posId,BattleCommon.convertToPositionId(j-1,i-1)) < 2 then
  74. if canReach(maze,point,i,j,roleFlag) then
  75. surroundPoints:append(maze.mazeArray[i][j][2])
  76. end
  77. end
  78. end
  79. end
  80. end
  81. return surroundPoints --返回point点的集合
  82. end
  83.  
  84. -- --计算G
  85. function CalcG( point )
  86. local G = point.G
  87. local parentG = 0
  88. if point.parentPoint then
  89. parentG = point.parentPoint.G
  90. end
  91. return G + parentG
  92. end
  93.  
  94. function foundPoint( tempStart,point )
  95. local G = CalcG(point)
  96. if G < point.G then
  97. point.parentPoint = tempStart
  98. point.G = G
  99. point:CalcF()
  100. end
  101. end
  102.  
  103. function notFoundPoint( maze,tempStart,point )
  104. point.parentPoint = tempStart
  105. point.G = CalcG(point)
  106. point:CalcF()
  107. maze.openList:append(point)
  108. end
  109.  
  110. function getPoint( list,data )
  111. for i,point in pairs(list.tbl) do
  112. if point.posId == data.posId then
  113. return point
  114. end
  115. end
  116. return nil
  117. end
  118.  
  119. -- --寻找路径(起始路径)
  120. local function findPath( maze,startPoint,endPoint,roleFlag)
  121. maze.openList:append(startPoint)
  122. while maze.openList:getSize() ~= 0 do
  123. --找出F的最小值
  124. local tempStart = getMinPoint(maze.openList)
  125. maze.openList:removeById(1)
  126. maze.closeList:append(tempStart)
  127. --找出它相邻的点
  128. local surroundPoints = getSurroundPoints(maze,tempStart,roleFlag)
  129. for i,point in pairs(surroundPoints.tbl) do
  130. if existsPoint(maze.openList,point) then
  131. --计算G值,假设比原来大,就什么都不做,否则设置他的父节点为当前节点,并更新GF
  132. foundPoint(tempStart,point)
  133. else
  134. --假设他们不再開始列表里面,就加入,并设置父节点,并计算GHF
  135. notFoundPoint(maze,tempStart,point)
  136. end
  137. end
  138. --假设最后一个存在则返回
  139. if getPoint(maze.openList,endPoint) then
  140. return getPoint(maze.openList,endPoint)
  141. end
  142. end
  143. return getPoint(maze.openList,endPoint)
  144. end
  145.  
  146. --依据一个table创建一个地形
  147. function create( tb )
  148. local maze = {}
  149. maze.step = 1 --格子与格子的基本距离,用于计算H
  150. maze.mazeArray = tb
  151. maze.openList = TabledArray.create() --开启列表
  152. maze.closeList = TabledArray.create() --关闭列表
  153. maze.findPath = findPath
  154. return maze
  155. end
  156.  
  157. return Maze

调用方法

  1. function printPath( presentPoint )
  2. local pathArray = TabledArray.create()
  3. while presentPoint do
  4. pathArray:preppend(presentPoint.posId)
  5. presentPoint = presentPoint.parentPoint
  6. end
  7. local startPoint = pathArray:get(2)
  8. local endPoint = pathArray:getLast()
  9.  
  10. cclog(startPoint)
  11. cclog(endPoint)
  12. cclog("从"..startPoint.."到"..endPoint.."的路径是:")
  13. for i,p in pairs(pathArray.tbl) do
  14. cclog(p)
  15. end
  16. end

  1. local array = battleBoard:createBoxPoints(cRole:getFlag(),40)
  2. local maze = Maze.create(array)
  3. local startPoint = Point.create(cRole:getPositionId())
  4. local endPoint = Point.create(40)
  5. local presentPoint = maze:findPath(startPoint,endPoint,cRole:getFlag())
  6. printPath(presentPoint)

七、执行效果

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZGluZ3hpYW93ZWkyMDEz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" style="font-size:14px;" alt="" />

手机測试效果还能够。貌似在255*255规模的方格规模上採用A*还是不会很多效率。

假设需要交流请联系。

版权声明:本文博客原创文章,博客,未经同意,不得转载。

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

  1. A*寻路算法详细解读

    文章目录 A*算法描述 简化搜索区域 概述算法步骤 进一步解释 具体寻路过程 模拟需要更新F值的情况 Lua代码实现 在学习A*算法之前,很好奇的是A*为什么叫做A*.在知乎上找到一个回答,大致意思是 ...

  2. A星寻路算法介绍

    你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...

  3. A*寻路算法探究

    A*寻路算法探究 A*算法常用在游戏的寻路,是一种静态网路中求解最短路径的搜索方法,也是解决很多搜索问题的算法.相对于Dijkstra,BFS这些算法在复杂的搜索更有效率.本文在U3D中进行代码的测试 ...

  4. A*寻路算法

    对于初学者而言,A*寻路已经是个比较复杂的算法了,为了便于理解,本文降低了A*算法的难度,规定只能横竖(四方向)寻路,而无法直接走对角线,使得整个算法更好理解. 简而言之,A*寻路就是计算从起点经过该 ...

  5. 算法:Astar寻路算法改进,双向A*寻路算法

    早前写了一篇关于A*算法的文章:<算法:Astar寻路算法改进> 最近在写个js的UI框架,顺便实现了一个js版本的A*算法,与之前不同的是,该A*算法是个双向A*. 双向A*有什么好处呢 ...

  6. 算法:Astar寻路算法改进

    早前写了一篇<RCP:gef智能寻路算法(A star)> 出现了一点问题. 在AStar算法中,默认寻路起点和终点都是N x N的方格,但如果用在路由上,就会出现问题. 如果,需要连线的 ...

  7. js实现A*寻路算法

    这两天在做百度前端技术学院的题目,其中有涉及到寻路相关的,于是就找来相关博客进行阅读. 看了Create Chen写的理解A*寻路算法具体过程之后,我很快就理解A*算法的原理.不得不说作者写的很好,通 ...

  8. 用简单直白的方式讲解A星寻路算法原理

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

  9. A星寻路算法

    A星寻路算法 1.准备一个close关闭列表(存放已被检索的点),一个open开启列表(存放未被检索的点),一个当前点的对象cur 2.将cur设成开始点 3.从cur起,将cur点放入close表中 ...

随机推荐

  1. arcgis jsapi 调用google地区服务

    做地理信息系统(GIS)项目,除了实现功能用户体验度要好之外,最重要的是地图渲染效果更要好.很多时候苦于数据的完整性和对于配图的审美观,程序猿们都很难配出好看的地图效果.基于上述一般直接调用googl ...

  2. friend keyword 对于模板 并不只不过友元!!!

    friend是C++中封装的漏网之鱼. C++中的friend同意其它的类或者是函数訪问本类的不论什么成员.甚至是private成员,仅仅要该类声明其为友元. 但是,在有些情况下,并非同意外界訪问类的 ...

  3. hadoop namenode -format Couldn&#39;tload main class &quot;-Djava.library.path=.home.hadoop.hadoop-2.5.2.lib&quot;

    <pre name="code" class="sql">[hadoop@MasterHadoop50 ~]$ hadoop namenode -f ...

  4. Spring官方网站的改版后下载

    Spring官方网站改版很长一段时间后还没有找到直接下载Jar链接包,下面总结了一些方法,可在网上,亲測可用. 1.直接输入地址,改对应版本号就可以:http://repo.springsource. ...

  5. ZOJ Problem Set - 3829Known Notation(贪心)

    ZOJ Problem Set - 3829Known Notation(贪心) 题目链接 题目大意:给你一个后缀表达式(仅仅有数字和符号),可是这个后缀表达式的空格不幸丢失,如今给你一个这种后缀表达 ...

  6. 开源Math.NET基础数学类库使用(15)C#计算矩阵行列式

    原文:[原创]开源Math.NET基础数学类库使用(15)C#计算矩阵行列式                本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p ...

  7. Ising模型(伊辛模型)

    Ising模型(伊辛模型)是一个最简单且能够提供非常丰富的物理内容的模型.可用于描写叙述非常多物理现象,如:合金中的有序-无序转变.液氦到超流态的转变.液体的冻结与蒸发.玻璃物质的性质.森林火灾.城市 ...

  8. lua5.1 和 5.2 关于 sequence 的定义变化,对#table取值的影响

    引子 环境 lua 5.2 a = {}   for i=1,2 do a[i] = i*3 end   a[4] = 11;   print(a[#a])   ---print 11 ------- ...

  9. SharePoint 2013 创建web应用程序报错&quot;This page can’t be displayed&quot;

    错误描写叙述 This page can't be displayed •Make sure the web address http://centeradmin is correct. •Look ...

  10. UVa 11879 - Multiple of 17

    称号:计算一个数字是不17倍数. 说明:串,睑板. 简单的问题,直接推论可以是. 设定 n = 10a + d:(0 ≤ d ≤ 9) a - 5d = 51a - 5n,假设n被17整除,这个数必定 ...