【问题标题】:Looking out of bounds in a 2D Lua table在 2D Lua 表中查看越界
【发布时间】:2013-03-19 00:28:20
【问题描述】:

我有时在 Lua 中制作小游戏,并且经常需要将 2D 数组实现为网格或棋盘。当我想检查特定单元格周围的单元格时,我通常给二维数组一个元表,这样当 grid[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

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

【问题讨论】:

  • 为什么neighbours 包含{{x1, y1}, {x2, y2}, ...} 而不是{cell1, cell2, ...}
  • 没有理由,这只是一个例子。我写的模块其实用的是第二种方法{cell1, cell2, ...}

标签: arrays lua lua-table


【解决方案1】:

您不需要元表。

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

【讨论】:

    【解决方案2】:

    您可以编写一个forEachNeighbor() 函数,该函数将获取网格、一个位置和一个函数,然后使用每个现有的neighborfield 调用它,即将循环和外部if 封装在您的第二个sn-p 中的函数中,你会像这样使用:

    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 元方法实现。

    对于__index 元方法本身:首先,您可能指的是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 的用途!

    【讨论】:

    • 没有必要在__index中调用rawget,因为__index只有在key不在表中时才会调用。
    • 我不知道为什么我不只是制作一个模块......谢谢你的建议!
    猜你喜欢
    • 1970-01-01
    • 2021-04-16
    • 2013-11-09
    • 1970-01-01
    • 2012-03-31
    • 2015-08-22
    • 2018-04-03
    • 1970-01-01
    • 2013-12-23
    相关资源
    最近更新 更多