超越2D Lua表中的界限

时间:2013-03-28 14:08:47

标签: arrays lua lua-table

我有时会在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

这有效,但对我来说似乎很尴尬。有没有更好或更好的方法呢?

2 个答案:

答案 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 

应该做的工作。在表达式中使用逻辑andor来充当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而不是tablerawget(t, key)而不是t[key](这会导致无限递归) 。 但正如lhf指出的那样,检查完全没必要,因为__indexonly called when the key is not present in t。所以你可以写:

__index = function(t, key)
    return {}
end

最后一句话:

  

我有时会在Lua中制作小游戏,并且经常需要实现2D数组

为什么不实施一次并在其他游戏中重复使用?这就是modules的用途!