纯lua版A*算法优化测试

来源:互联网 发布:学淘宝开店 编辑:程序博客网 时间:2024/05/29 13:05

写了个A*算法的lua版本,也参考了不少网上资料还有开源的代码,关于写这个的原因,只是在做一个rts的寻路,写了个lua版本也是图省事,想尽快看效果。出于程序员的好奇和执着,修改了好几个版本,优化算法,提高了一些效率,当然这里还有优化的余地,就不做进一步深入了,毕竟时间有限,优化的结果也是很明显的。

关于A*算法的基本原理,可以参考一个很好教程:http://www.policyalmanac.org/games/aStarTutorial.htm


优化

关于A*算法的优化,无非以下二点:

  • openlist、closelist的查找
  • openlist中获得最优节点

这里优化的方向有针对性,不同需要有不同的优化策略。这里我们研究的是针对2维地图的优化方案。
解决第一点,是要有好的查找效率,简单的可以用hash来加速查找。当然lua里直接map就可以提升不少速度:

  local idx = self:getIndex(row, col)  local curNode = self:getNode(node, row, col, (row ~= node.row and col ~= node.col))  local openNode = self.open_list[idx]  local closeNode = self.close_list[idx]  if not openNode and not closeNode then      -- 不在OPEN表和CLOSE表中      self.open_list[idx] = curNode  elseif openNode then      -- 在OPEN表      if openNode.f > curNode.f then          -- 更新OPEN表中的节点          self.open_list[idx] = curNode      end  else      -- 在CLOSE表中      if closeNode.f > curNode.f then          self.open_list[idx] = curNode          self.close_list[idx] = nil      end  end

解决第二点,是要让openlist更快的查找最小f值节点,这里使用更快的heap,代码参考https://github.com/Yonaba/Binary-Heaps:

  -- start node  local idx = self:getIndex(self.startPoint.row, self.startPoint.col)  self.open_list:push(self.nodes[idx])  -- walkable   local check = function(row, col)      ...  end  local dir = self.four_dir and four_dir or eight_dir  while not self.open_list:empty() do      -- check      local node = self.open_list:pop()      node.state = 2      if node.row == self.endPoint.row and node.col == self.endPoint.col then          -- found      end      for i = 1, #dir do          local row = node.row + dir[i][1]          local col = node.col + dir[i][2]          local idx = self:getIndex(row, col)          if check(row, col) then              local g, h, f = self:getCost(node, row, col, ...)              local newNode = self.nodes[idx]              if newNode.state == 0 then                  -- add new node                  newNode.father = node                  newNode.g = g                  newNode.h = h                  newNode.f = f                  newNode.state = 1                  self.open_list:push(newNode)              elseif newNode.state == 1 then                  -- alreay in openlist                  if newNode.f > f then                      -- a better way then update                       newNode.father = node                      newNode.g = g                      newNode.h = h                      newNode.f = f                  end              else                  -- in closelist              end          end      end  end

测试结果

测试环境使用cocos2dx2.2.6-lua,地图tilemap,大小50*50,地图信息如下:
地图信息

PC - Experiment1 实验结果:

Experiment1([1, 1] -> [1, 50]) time (s) A* - array 0.0960~0.1030 A* - map 0.0290~0.0300 A* - map & heap sort 0.0020~0.0030

PC - Experiment2 实验结果:

Experiment2([1, 1] -> [6, 5]) time (s) A* - array 0.1360~0.1450 A* - map 0.0420~0.0460 A* - map & heap sort 0.0020~0.0030

Mobile - Experiment1 实验结果:

Experiment1([1, 1] -> [1, 50]) time (s) A* - array 1.050~1.110 A* - map 0.500~0.600 A* - map & heap sort 0.040~0.050

Mobile - Experiment2 实验结果:

Experiment2([1, 1] -> [6, 5]) time (s) A* - array 1.260~1.300 A* - map 0.640~0.700 A* - map & heap sort 0.024~0.027

Repository

github:adamwu

往后可能写个c++版本的,毕竟lua效率要差些。

1 0
原创粉丝点击