标签:
1.A*基本流程图
2.扩展节点方法
3.A*最短路径条件
代码:
1.main.lua
require "Lib"
--create scene
local gameScene = cc.Scene:create()
gameScene:addChild(GameLayer:create())2.Lib.lua
require "src/GameLayer" require "src/Cube" require "src/Constant"3.Constant.lua
CubeSplit = 3 CellWidth = cc.Director:getInstance():getWinSize().width/10 CellHeight = cc.Director:getInstance():getWinSize().height/10 CubeWidth = CellWidth - CubeSplit --格子宽 CubeHeight = CellHeight - CubeSplit --格子高4.Cube.lua
--地图方格
Cube = class("Cube", function ()
return cc.Node:create()
end)
Cube.CUBE_TYPE_WALL = 1 --墙
Cube.CUBE_TYPE_START = 2 --起点格子
Cube.CUBE_TYPE_DESTANATION = 3 --目标地格子
Cube.CUBE_TYPE_AVIABLE = 4 --可以行走的格子
function Cube:create(row, col, type)
local view = Cube:new()
view:__init(row, col, type)
return view
end
function Cube:__init(row, col, type)
self.row = row
self.col = col
self.type = type
self:addBgByType()
end
function Cube:addBgByType()
local layerColor = nil
local lblDesp = nil
local fontSize = 15
local color = {
black = cc.c3b(0,0,0),
red = cc.c3b(255,0,255),
yellow = cc.c3b(255,255,0),
white = cc.c3b(255,255,255),
blue = cc.c3b(0,0,255),
green = cc.c3b(0,255,127)
}
if self.type == Cube.CUBE_TYPE_WALL then
layerColor = cc.LayerColor:create(color.blue, CubeWidth, CubeHeight) --黑色
lblDesp = cc.Label:createWithSystemFont("墙","Arial",fontSize)
elseif self.type == Cube.CUBE_TYPE_START then
layerColor = cc.LayerColor:create(color.red, CubeWidth, CubeHeight) --紫红
lblDesp = cc.Label:createWithSystemFont("起始点","Arial",fontSize)
elseif self.type == Cube.CUBE_TYPE_DESTANATION then
layerColor = cc.LayerColor:create(color.yellow, CubeWidth, CubeHeight) --黄
lblDesp = cc.Label:createWithSystemFont("终点","Arial",fontSize)
elseif self.type == Cube.CUBE_TYPE_AVIABLE then
layerColor = cc.LayerColor:create(color.white, CubeWidth, CubeHeight) --白
else
layerColor = cc.LayerColor:create(color.green, CubeWidth, CubeHeight) --白
layerColor:setOpacity(100)
end
layerColor:ignoreAnchorPointForPosition(false)
self:addChild(layerColor)
if lblDesp then
lblDesp:setColor(cc.c3b(0,0,0))
self:addChild(lblDesp)
end
end
function Cube:getPositionByRowCol()
return cc.p( CellWidth * (self.col-0.5), CellHeight * (self.row-0.5))
end
5.GameLayer.lua
GameLayer = class("GameLayer",function()
return cc.Layer:create()
end)
function GameLayer:create()
local view = GameLayer.new()
view:__init()
return view
end
function GameLayer:__init()
self:addMap()
end
--是否出界
function GameLayer:checkIsInSide(cube)
return cube.row >= 1 and cube.row <= 10 and cube.col >= 1 and cube.col <= 10 and not self:checkIsInSide(cube)
end
--判断2个格子是否一样
function GameLayer:isEqual(cube1, cube2)
return cube1.row == cube2.row and cube1.col == cube2.col
end
--背景格子
function GameLayer:initBg()
for row = 1, 10 do
for col = 1, 10 do
local cube = Cube:create(row, col, Cube.CUBE_TYPE_AVIABLE)
cube:setPosition(cube:getPositionByRowCol())
self:addChild(cube)
end
end
end
--是否可以行走
function GameLayer:checkIsCanGo(cube)
if cube.row <= 0 or cube.row > 10 or cube.col <= 0 or cube.col > 10 then
return false
end
for _, cubeTmp in ipairs(self.mapList) do
if cube.row == cubeTmp.row and cube.col == cubeTmp.col and cubeTmp.type == Cube.CUBE_TYPE_WALL then
return false
end
end
return true
end
--开始点
function GameLayer:initStart()
self.startCube = Cube:create(3, 4, Cube.CUBE_TYPE_START)
self.startCube:setPosition(self.startCube:getPositionByRowCol())
self:addChild(self.startCube)
table.insert(self.mapList, self.startCube)
end
--结束点
function GameLayer:initDestination()
self.desCube = Cube:create(3, 9, Cube.CUBE_TYPE_DESTANATION)
self.desCube:setPosition(self.desCube:getPositionByRowCol())
self:addChild(self.desCube)
table.insert(self.mapList, self.desCube)
end
--墙
function GameLayer:initWall()
math.randomseed(os.time())
for i = 1, 60 do
local row = math.random(1,10)
local col = math.random(1,10)
local cube = Cube:create(row, col, Cube.CUBE_TYPE_WALL)
if not self:isEqual(cube, self.startCube) and not self:isEqual(cube, self.desCube) then
cube:setPosition(cube:getPositionByRowCol())
self:addChild(cube)
table.insert(self.mapList, cube)
end
end
end
function GameLayer:clearMap()
self:removeAllChildren()
self.mapList = {}
end
--480 * 320
--格子大小 48 * 32
function GameLayer:addMap()
self:clearMap()
self:initBg()
self:initStart()
self:initDestination()
self:initWall()
self:findAStarPath()
end
function GameLayer:tableInclude(cubeList, cube)
local isResult = false
for i = 1, #cubeList do
if self:isEqual(cube, cubeList[i]) then
isResult = true
break
end
end
return isResult
end
function GameLayer:tableRemove(cubeList, cube)
for i = 1, #cubeList do
if self:isEqual(cube, cubeList[i]) then
table.remove(cubeList, i)
break
end
end
end
function GameLayer:findValueInTable(cubeList, cube)
for i = 1, #cubeList do
if self:isEqual(cube, cubeList[i]) then
return cubeList[i]
end
end
end
function GameLayer:findAStarPath()
--以左下角为起点,顺时针转一圈
local dirList = {
{-1,-1},{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1}
}
self.openList = {}
self.closeList = {}
table.insert(self.openList, self.startCube)
self.startCube.g = 0
self.startCube.h = self:getManhattonDis(self.startCube)
self.startCube.f = self.startCube.g + self.startCube.h
while true do
if #self.openList == 0 then
print("Fail, not find !!!")
break
else
local firstCubeInOpenList = self.openList[1]
table.remove(self.openList, 1)
table.insert(self.closeList, firstCubeInOpenList)
if self:isEqual(firstCubeInOpenList, self.desCube) then
self.desCube.parent = firstCubeInOpenList
print("Success, find !!!")
self:printPath()
break
else
for i = 1, 8 do
local dir = dirList[i]
local tmpCube = Cube:create(firstCubeInOpenList.row + dir[1], firstCubeInOpenList.col + dir[2], self.startCube.type)
if not self:checkIsCanGo(tmpCube) then
elseif not self:tableInclude(self.openList, tmpCube) and not self:tableInclude(self.closeList, tmpCube) then
self:getOrGetAndSetCubeFGH(firstCubeInOpenList, tmpCube, i)
table.insert(self.openList, tmpCube)
elseif self:tableInclude(self.openList, tmpCube) then
local newFTmp = self:getOrGetAndSetCubeFGH(firstCubeInOpenList, tmpCube, i, true)
if newFTmp < self:findValueInTable(self.openList, tmpCube).f then
self:getOrGetAndSetCubeFGH(firstCubeInOpenList, tmpCube, i)
end
elseif self:tableInclude(self.closeList, tmpCube) then
local newFTmp = self:getOrGetAndSetCubeFGH(firstCubeInOpenList, tmpCube, i, true)
if newFTmp < self:findValueInTable(self.closeList, tmpCube).f then
self:tableRemove(self.closeList, tmpCube)
table.insert(self.openList, tmpCube)
self:getOrGetAndSetCubeFGH(firstCubeInOpenList, tmpCube, i)
end
end
end
end
--按照f值升序排列openList
local sortFunction = function(cube1, cube2)
return cube1.f < cube2.f
end
table.sort(self.openList, sortFunction)
-- self:printOpenList(self.openList)
end
end
end
--打印开放列表
function GameLayer:printOpenList(openList)
print("==========================================")
for i = 1, #openList do
local cube = openList[i]
print("row:"..cube.row.." col:"..cube.col.." f:"..cube.f.." g:"..cube.g.." h:"..cube.h)
end
end
--回溯打印路径
function GameLayer:printPath()
local parentCube = self.desCube
local resultPath = {}
while parentCube.parent ~= nil do
parentCube = parentCube.parent
local row = parentCube.row
local col = parentCube.col
local cube = Cube:create(row, col)
cube:setPosition(cube:getPositionByRowCol())
self:addChild(cube)
end
end
--1.isOnlyGetFValue 为true: 只返回curCube的可能设置的临时f值
--2.isOnlyGetFValue为nil或false: 设置curCubed的f,g,h并且返回节点的f值
function GameLayer:getOrGetAndSetCubeFGH(srcCube, curCube, i, isOnlyGetFValue)
if isOnlyGetFValue then
local g
if i == 1 or i == 3 or i == 5 or i == 7 then
g = srcCube.g + 14
else
g = srcCube.g + 10
end
local h = self:getManhattonDis(curCube)
local f = g + h
return f
else
if i == 1 or i == 3 or i == 5 or i == 7 then
curCube.g = srcCube.g + 14
else
curCube.g = srcCube.g + 10
end
curCube.h = self:getManhattonDis(curCube)
curCube.f = curCube.g + curCube.h
curCube.parent = srcCube
return curCube.f
end
end
--得到一个节点的曼哈顿距离
function GameLayer:getManhattonDis(cube)
local value = math.abs(self.desCube.row - cube.row) + math.abs( self.desCube.col - cube.col)
return value*10
end
return GameLayer
具体代码详见我github工程:
https://git.oschina.net/jianan/AStar/tree/master
截图实例:
说明:在随机生成的墙壁中,给定开始点和结束点,浅绿色部分为A*算法计算出来的最短路径。
1.
2.
3.
总结:当估价函数h选定后,就可以让A*是最优算法,在此处采用的是曼哈顿距离!
其它A*入门视频:
http://m.blog.csdn.net/article/details?id=17187239
http://www.jiangzhongyou.net/forum-40-1.html
标签:
原文地址:http://blog.csdn.net/themagickeyjianan/article/details/52455691