3

Lua で小さなゲームを作成することがあり、2D 配列をグリッドまたはボードとして実装する必要があることがよくあります。特定のセルの周囲のセルをチェックしたい場合、通常は 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

これは機能しますが、私には厄介なようです。それを行うためのより良い、またはより良い方法はありますか?

4

2 に答える 2

3

メタテーブルは必要ありません。

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 

仕事をするべきです。C の三項演算子のように振る舞う論理式andとin 式を使用することは、比較的一般的な lua のイディオムです。したがって、この行は次のようになります。or

local cell = nil
if grid[v[1]]~=nil then
    cell = grid[v[1]][v[2]]
end
于 2013-03-28T20:21:01.297 に答える
2

forEachNeighbor()グリッド、位置、および関数を受け取り、既存の各隣接フィールドでそれを呼び出す関数を作成できます。つまりif、関数の 2 番目のスニペットでループとアウターをカプセル化します。次のように使用します。

forEachNeighbor(grid, position, function(cell)
    if cell == 1 then
        -- do something
    elseif cell == 2 then
        -- do something else
    ...
end)

また、at()グリッド位置を 1 つのパラメーターとして受け取り、対応するフィールド または を返す関数を提供して、それが になるようにするnilことgrid[v[1]][v[2]]もできますat(grid, v)。これは、メタメソッドに加えて、またはメタメソッドの代わりに実装することもできます__index

メタメソッド自体について__index: まず、(無限再帰の原因となる)のt代わりにtablerawget(t, key)代わりにという意味でした。t[key]しかし、 lhf が指摘したように、キーが に存在しない場合にのみ呼び出されるため、チェックはまったく__index不要ですt。したがって、次のように書くことができます。

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

最後に一言:

Lua で小さなゲームを作成することがあり、2D 配列を実装する必要があることがよくあります。

一度実装して、他のゲームで再利用してみませんか? それがモジュールの目的です!

于 2013-03-28T16:18:10.950 に答える