【语法】
一、机制原理
一行代码拆解:f = g + h。A 在广度优先的骨架上加了一个大脑:每个格子记 g(起点到该格的已走步数)与 h(该格到终点的估算距离),f 是两者之和;每次从开放列表取 f 最小的格子展开。h 用曼哈顿距离(横纵差绝对值之和),网格四向移动时恰好不高估,A 的最优性就守得住。关闭列表记录已展开的格子防回头,到达终点沿父指针回溯即得完整路径。
二、错误写法
-- 错误:无差别扩散,大地图穷举到天荒地老
for _, step in ipairs(allDirections) do
expand(step)
end
三、正确写法
local function heuristic(x, y, tx, ty)
return math.abs(x - tx) + math.abs(y - ty)
end
local function findPath(sx, sy, tx, ty)
local open = {{x = sx, y = sy, g = 0,
f = heuristic(sx, sy, tx, ty)}}
local closed, from = {}, {}
local keyOf = function(x, y) return x .. "_" .. y end
while #open > 0 do
local best = 1
for i = 2, #open do
if open[i].f < open[best].f then best = i end
end
local cur = table.remove(open, best)
local ck = keyOf(cur.x, cur.y)
if closed[ck] then
else
closed[ck] = true
if cur.x == tx and cur.y == ty then
local path = {}
local k = ck
while from[k] do
path[#path + 1] = k
k = from[k]
end
return path
end
for _, d in ipairs({{1,0},{-1,0},{0,1},{0,-1}}) do
local nx, ny = cur.x + d[1], cur.y + d[2]
local nk = keyOf(nx, ny)
if not closed[nk] and passable(nx, ny) then
from[nk] = ck
local g = cur.g + 1
open[#open + 1] = {x = nx, y = ny,
g = g, f = g + heuristic(nx, ny, tx, ty)}
end
end
end
end
return nil
end
四、引擎验证
带障碍的网格上 A* 返回的路径步数与广度优先一致,展开的格子数少一半以上;不可达返回空路径。
五、FAQ
问:h 能随便取吗?
答:不能高估实际距离,高估会破坏最优性。
问:开放列表能更快吗?
答:能,换二叉堆取最小 f 即可。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【语法算法】 next 的遍历本质就这一行: 传入上一个键,返回下一个键值对——不传上一个键就从第一个开始——next 是 …
【语法算法】 返回值的截取本质就这一行: 函数返回三个值,左侧三个变量各接一个——多余的返回值被丢弃,不足的补 nil——多…
【语法算法】 collectgarbage 的分步回收就这一行: "step" 模式让 GC 执行一步增量回收——参数 20…
【语法算法】 gmatch 的迭代本质就这一行: gmatch 返回一个迭代函数——每次调用返回下一个匹配——遍历完返回 n…
【语法算法】 xpcall 的错误处理函数就这一行: xpcall 和 pcall 的本质区别就一个:xpcall 可以传入…
【语法算法】 元方法 __index 设为函数的本质就这一行: 读取表中不存在的键时,Lua 调用 __index 函数——…