3

A friend and I try to write a mine sweeper program in Lua using the Löve framework. So far the code needs to see if a box (a cell) is checked and then draw it. We are new to Lua, the program now has the flaw that it only works on the lower right box.

UPDATE: Looking at it now I see that the values of the initialized GameBoard all have the same value (i.e., GameBoard[1] till GameBoard[150] are all identical cells).

Here's the code:

conf.lua has some global variables defined:

function love.conf(t)

    -- Global variables.
    CELL_SIZE = 40
    NUM_ROWS = 15
    NUM_COLS = 10
    STATS_HEIGHT = 100
    AMOUNT_OF_CELLS = NUM_ROWS * NUM_COLS
    GRID_WIDTH = 400
    GRID_HEIGHT = 700

end

Here's the relevant failing code in main.lua (it goes wrong in the load method where the GameBoard is filled with Cells.

--  The Cell table is used for every individual square on 
--  the gameboard
Cell = {}

-- The Gameboard (150 Cell objects)
GameBoard = {}

--  The function new belongs to Cell and spawns a new object (a table)
--  with the same attributes as Cell.
function Cell:new(i, j)

--  each cell knows:
    --  its x- and y-coordinates.
    self.x_min = (i-1) * CELL_SIZE 
    self.x_max = (CELL_SIZE-1) + (i-1) * CELL_SIZE
    self.y_min = STATS_HEIGHT + (j-1) * CELL_SIZE 
    self.y_max = STATS_HEIGHT + (CELL_SIZE-1) + (j-1) * CELL_SIZE

    --  if it is a mine (determined with random number generator)
    isMine =  (math.random(1, 8) % 8 == 0) -- Roughly 0.15 (1/7) times true (is a mine)
    self.isMine = isMine

    --  do not check the mine initially
    self.checked = false

    --  return the cell object
    return self;

end


--  love.load is a love-function that is called once when the game
--  starts.
function love.load()

    -- The index of the cell on the GameBoard (ranging from 1 to 150)
    local index = 1

    --  Build a two dimensional table of Cell-objects
    for i = 1, NUM_COLS, 1 do
        for j = 1, NUM_ROWS, 1 do       
            GameBoard[ index ] = Cell:new( i, j )
            index = index + 1
        end
    end
end

The result is that all boxes have the values of the lower box with index 150 (the latest since NUM_ROWS * NUM_COLS = 150). All elements (Cells) of the table (Gameboard) have the same the x and y values set in the Cell:new method.

It would be appreciated if someone could tell us how to properly initialize and access a table of tables.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
user2609980
  • 10,264
  • 15
  • 74
  • 143
  • A comment about style: `cell.checked` instead of `cell["checked"]`, etc. – lhf Nov 01 '14 at 01:35
  • @inf Thanks for the advice. This was the first day at the language. Do you see why the code only works for the lower right corner? Can it have something to so with variable scope? – user2609980 Nov 01 '14 at 01:59

1 Answers1

3

In the function Cell:new, self is the table Cell itself, so you are returning the same table every time.

A simple fix is to create a new table instead:

function Cell:new(i, j)
    local t = {}

    t.x_min = (i-1) * CELL_SIZE 
    --omit the rest

    return t;
end

For future improvement, you may be interested in another way, which implements prototype:

function Cell:new(i, j)
    local o = {}
    setmetatable(o, self)
    self.__index = self

    self.x_min = (i-1) * CELL_SIZE 
    --omits rest

    return o;
end

Read PiL: Object-Oriented Programming for further information.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294