Search code examples
multidimensional-arraylualua-table

Error when reading a two-dimensional table


I'm trying to create an infinite game field by connecting the opposite edges of the field. I get the following error:

Error: attempting to index field '?' (a nil value)

The error is on the line in bold. As far as I understand, the array field does not contain any values when called in function drawField() despite it was filled with zeros in function clearField(). How can I fix the array so it keeps its values outside clearField()?

local black = 0x000000
local white = 0xFFFFFF

local field = {} 
local function clearField()
  for gx=1,displayWidth do
    if gx==displayWidth then
      field[1] = field[displayWidth+1]
    end
    field[gx] = {}
    for gy=1,displayHeight-3 do
      if gy==displayHeight-3 then
        field[gx][1] = field[gx][displayHeight-2]
      end
      field[gx][gy] = 0
    end
  end
end

--Field redraw
local function drawField()
  for x=1, #field do
    for y=1,x do
      **if field[x][y]==1 then**
        display.setBackground(white)
        display.setForeground(black)
      else
        display.setBackground(black)
        display.setForeground(white)
      end
      display.fill(x, y, 1, 1, " ")
    end
  end
end

-- Program Loop
clearField()
while true do
  local lastEvent = {event.pullFiltered(filter)}
  if lastEvent[1] == "touch" and lastEvent[5] == 0 then
    --State invertion
    if field[lastEvent[3]][lastEvent[4]]==1 then
      field[lastEvent[3]][lastEvent[4]] = 0
    else
      field[lastEvent[3]][lastEvent[4]] = 1
    end
    drawField()
  end
end

display and event variables are libraries. The program was run with displayWidth = 160 and displayHeight = 50


Solution

  • field[1] = field[displayWidth+1] is equivalent to field[1] = nil as you never assigned a value to field[displayWidth+1]

    Run this to see for yourself:

    clearField()
    print(field[1])
    for k,v in pairs(field) do print(v[1]) end
    

    So in your outer loop you create 10 entries for field but in the 10th run you delete field[1] which later causes the observed error as you're trying to inxex field[1] in if field[x][y]==1 then

    You could implement a __index metamethodt to get a somewhat circular array. Something like:

    local a = {1,2,3,4}
    setmetatable(a, {
      __index = function(t,i)
        local index = i%4
        index = index == 0 and 4 or index
        return t[index] end
    })
    for i = 1, 20 do print(a[i]) end