lua实现的A星(a star)算法

来源:互联网 发布:json 数据解析 乱码 编辑:程序博客网 时间:2024/05/29 15:59

这个是在网上找的, 用lua实现的A星(a star)算法, 这个算法实现了上下左右行走,不能斜着走。并且地形只有可通过,不可通过两种状态,在这个算法基础上,你可以增加自己需要的功能 。



function CalcMoves(mapmat, px, py, tx, ty)-- Based on some code of LMelior but made it work and improved way beyond his code, still thx LMelior!--[[ PRE:mapmat is a 2d arraypx is the player's current xpy is the player's current ytx is the target xty is the target yNote: all the x and y are the x and y to be used in the table.By this I mean, if the table is 3 by 2, the x can be 1,2,3 and the y can be 1 or 2.--]]--[[ POST:closedlist is a list with the checked nodes.It will return nil if all the available nodes have been checked but the target hasn't been found.--]]-- variableslocal openlist={}                 -- Initialize table to store possible moveslocal closedlist={}-- Initialize table to store checked gridsquareslocal listk=1                   -- List counter        local closedk=0                -- Closedlist counterlocal tempH=math.abs(px-tx)+math.abs(py-ty)local tempG=0openlist[1]={x=px, y=py, g=0, h=tempH, f=0+tempH ,par=1}   -- Make starting point in listlocal xsize=table.getn(mapmat[1]) -- horizontal map sizelocal ysize=table.getn(mapmat)-- vertical map sizelocal curbase={}-- Current square from which to check possible moveslocal basis=1-- Index of current base-- Growing loopwhile listk>0 do    -- Get the lowest f of the openlist      local lowestF=openlist[listk].f      basis=listkfor k=listk,1,-1 do      if openlist[k].f<lowestF then         lowestF=openlist[k].f                       basis=k           endendclosedk=closedk+1table.insert(closedlist,closedk,openlist[basis])curbase=closedlist[closedk] -- define current base from which to grow listlocal rightOK=truelocal leftOK=true            -- Booleans defining if they're OK to addlocal downOK=true              -- (must be reset for each while loop)local upOK=true-- Look through closedlistif closedk>0 then    for k=1,closedk doif closedlist[k].x==curbase.x+1 and closedlist[k].y==curbase.y thenrightOK=falseendif closedlist[k].x==curbase.x-1 and closedlist[k].y==curbase.y thenleftOK=falseendif closedlist[k].x==curbase.x and closedlist[k].y==curbase.y+1 thendownOK=falseendif closedlist[k].x==curbase.x and closedlist[k].y==curbase.y-1 thenupOK=falseend    endend-- Check if next points are on the map and within moving distanceif curbase.x+1>xsize thenrightOK=falseendif curbase.x-1<1 thenleftOK=falseendif curbase.y+1>ysize thendownOK=falseendif curbase.y-1<1 thenupOK=falseend-- If it IS on the map, check map for obstacles--(Lua returns an error if you try to access a table position that doesn't exist, so you can't combine it with above)if curbase.x+1<=xsize and mapmat[curbase.y][curbase.x+1]~=0 thenrightOK=falseendif curbase.x-1>=1 and mapmat[curbase.y][curbase.x-1]~=0 thenleftOK=falseendif curbase.y+1<=ysize and mapmat[curbase.y+1][curbase.x]~=0 thendownOK=falseendif curbase.y-1>=1 and mapmat[curbase.y-1][curbase.x]~=0 thenupOK=falseend-- check if the move from the current base is shorter then from the former parrenttempG=curbase.g+1for k=1,listk do    if rightOK and openlist[k].x==curbase.x+1 and openlist[k].y==curbase.y and openlist[k].g>tempG thentempH=math.abs((curbase.x+1)-tx)+math.abs(curbase.y-ty)table.insert(openlist,k,{x=curbase.x+1, y=curbase.y, g=tempG, h=tempH, f=tempG+tempH, par=closedk})rightOK=false    end    if leftOK and openlist[k].x==curbase.x-1 and openlist[k].y==curbase.y and openlist[k].g>tempG thentempH=math.abs((curbase.x-1)-tx)+math.abs(curbase.y-ty)table.insert(openlist,k,{x=curbase.x-1, y=curbase.y, g=tempG, h=tempH, f=tempG+tempH, par=closedk})leftOK=false    end    if downOK and openlist[k].x==curbase.x and openlist[k].y==curbase.y+1 and openlist[k].g>tempG thentempH=math.abs((curbase.x)-tx)+math.abs(curbase.y+1-ty)table.insert(openlist,k,{x=curbase.x, y=curbase.y+1, g=tempG, h=tempH, f=tempG+tempH, par=closedk})downOK=false    end    if upOK and openlist[k].x==curbase.x and openlist[k].y==curbase.y-1 and openlist[k].g>tempG thentempH=math.abs((curbase.x)-tx)+math.abs(curbase.y-1-ty)table.insert(openlist,k,{x=curbase.x, y=curbase.y-1, g=tempG, h=tempH, f=tempG+tempH, par=closedk})upOK=false    end   end-- Add points to openlist-- Add point to the right of current base pointif rightOK thenlistk=listk+1tempH=math.abs((curbase.x+1)-tx)+math.abs(curbase.y-ty)table.insert(openlist,listk,{x=curbase.x+1, y=curbase.y, g=tempG, h=tempH, f=tempG+tempH, par=closedk})end-- Add point to the left of current base pointif leftOK thenlistk=listk+1tempH=math.abs((curbase.x-1)-tx)+math.abs(curbase.y-ty)table.insert(openlist,listk,{x=curbase.x-1, y=curbase.y, g=tempG, h=tempH, f=tempG+tempH, par=closedk})end-- Add point on the top of current base pointif downOK thenlistk=listk+1tempH=math.abs(curbase.x-tx)+math.abs((curbase.y+1)-ty)table.insert(openlist,listk,{x=curbase.x, y=curbase.y+1, g=tempG, h=tempH, f=tempG+tempH, par=closedk})end-- Add point on the bottom of current base pointif upOK thenlistk=listk+1tempH=math.abs(curbase.x-tx)+math.abs((curbase.y-1)-ty)table.insert(openlist,listk,{x=curbase.x, y=curbase.y-1, g=tempG, h=tempH, f=tempG+tempH, par=closedk})endtable.remove(openlist,basis)listk=listk-1                if closedlist[closedk].x==tx and closedlist[closedk].y==ty then                   return closedlist                endendreturn nilendfunction CalcPath(closedlist)--[[ PRE:closedlist is a list with the checked nodes.OR nil if all the available nodes have been checked but the target hasn't been found.--]]--[[ POST:path is a list with all the x and y coords of the nodes of the path to the target.OR nil if closedlist==nil--]]    if closedlist==nil then       return nil    end local path={} local pathIndex={} local last=table.getn(closedlist) table.insert(pathIndex,1,last) local i=1 while pathIndex[i]>1 doi=i+1 table.insert(pathIndex,i,closedlist[pathIndex[i-1]].par) end for n=table.getn(pathIndex),1,-1 do     table.insert(path,{x=closedlist[pathIndex[n]].x, y=closedlist[pathIndex[n]].y})   end closedlist=nil return pathend


0 0