我有时会在Lua中制作小游戏,并且经常需要将2D数组实现为网格或棋盘。当我想检查特定单元格周围的单元格时,我通常会给2D数组赋予元表,这样当网格[outOfBoundsNum]被索引时,它会返回一个空表而不是错误:
setmetatable(grid, {
__index =
function(t, key)
if not table[key] then
return {}
else
return table[key]
end
end})
因此,当调用grid[outOfBoundsNum][anything]
时,它会返回nil
。然后,为了检查周围的单元格,我做了类似的事情:
for k, v in ipairs(neighbours) do
local cell = grid[v[1][v[2]]
if cell then -- check if this is actually within the 2D array
if cell == 1 then
-- do something
elseif cell == 2 then
-- do something else
...
end
end
这有效,但对我来说似乎很尴尬。有没有更好或更好的方法呢?
答案 0 :(得分:3)
您不需要metatable。
for k, v in ipairs(neighbours) do
local cell = grid[v[1]] and grid[v[1]][v[2]]
if cell == 1 then
-- do something
elseif cell == 2 then
-- do something else
...
end
end
应该做的工作。在表达式中使用逻辑and
和or
来充当C中的三元运算符是一种相对常见的lua习语。
所以这一行相当于:
local cell = nil
if grid[v[1]]~=nil then
cell = grid[v[1]][v[2]]
end
答案 1 :(得分:2)
你可以写一个forEachNeighbor()
函数,它将获取网格,位置和函数,然后用每个现有的邻域调用它,即封装循环和外部if
在你的第二个片段中一个函数,你可以使用:
forEachNeighbor(grid, position, function(cell)
if cell == 1 then
-- do something
elseif cell == 2 then
-- do something else
...
end)
此外,您可以提供一个at()
函数,该函数将网格位置作为一个参数并返回相应的字段或nil
,以便grid[v[1]][v[2]]
变为at(grid, v)
。这也可以作为__index
元方法的补充或替代来实现。
对于__index
metamethod本身:首先,您可能需要t
而不是table
和rawget(t, key)
而不是t[key]
(这会导致无限递归) 。
但正如lhf指出的那样,检查完全没必要,因为__index
是only called when the key is not present in t
。所以你可以写:
__index = function(t, key)
return {}
end
最后一句话:
我有时会在Lua中制作小游戏,并且经常需要实现2D数组
为什么不实施一次并在其他游戏中重复使用?这就是modules的用途!