# Classic Minesweeper Game - Logic Bug Clearing Empty Squares

Hi all.

I figured I would build the classic Minesweeper game.
I’ve a tiny logic challenge in my external module whose job it is to find adjacent empty cells and to clear their button.

Currently for testing, my buttons are semi-transparent so I can see underlaying bomb locations and numbers, so I can also see the empty cells. But once fixed I will remove the alpha and you wouldn’t see both buttons and bombs/number at the same time.

`board` is a matrix that populates an outter table or rows, before the inner table manages each column/cell in a row.
EG
`board[1][1]` would reference the cell in the top left and `board[10][10]` the cell in the bottom right

The challenge is some adhoc cells above, and some adhoc cells below (north & south) are missed.
See screenshots.

The first cell listed in the cell the user clicked on.

Here is the code:

``````function mod.clearEmptySquares(board, rowX, colY)
local rowMax = #board
local colMax = #board[1]
board[rowX][colY].info.btn = false -- receive in the box to show/hide
print("BOX["..rowX.."]["..colY.."]")

if (board[rowX][colY].info.number == 0) then

if rowX > 1 then -- ABOVE
if (colY > 1) then --LEFT
if (board[rowX-1][colY-1].info.btn == true) then
board = mod.clearEmptySquares(board, rowX-1, colY-1)
end
end
if (colY == 1) then --CENTER
if (board[rowX-1][colY].info.btn == true) then
board = mod.clearEmptySquares(board, rowX-1, colY)
end
end
if (colY < colMax) then --RIGHT
if (board[rowX-1][colY+1].info.btn == true)then
board = mod.clearEmptySquares(board, rowX-1, colY+1)
end
end
end

if rowX < rowMax then -- BELOW
if (colY > 1) then --LEFT
if (board[rowX+1][colY-1].info.btn == true) then
board = mod.clearEmptySquares(board, rowX+1, colY-1)
end
end
if (colY == 1) then --CENTER
if (board[rowX+1][colY].info.btn == true) then
board = mod.clearEmptySquares(board, rowX+1, colY)
end
end
if (colY < colMax) then -- RIGHT
if (board[rowX+1][colY+1].info.btn == true)then
board = mod.clearEmptySquares(board, rowX+1, colY+1)
end
end
end

if (colY > 1) then -- LEFT ADJACENT
if (board[rowX][colY-1].info.btn == true) then
board = mod.clearEmptySquares(board, rowX, colY-1)
end
end

if (colY < colMax) then -- RIGHT ADJACENT
if (board[rowX][colY+1].info.btn == true)then
board = mod.clearEmptySquares(board, rowX, colY+1)
end
end
end
return board
end
``````

Is that intended? Seems like maybe some copy-paste from the `> 1` tests?

Hiya, funny you say that I originally had it as ```
(colY == 1)

Code tweeked to be > =
problem persists.

``````function mod.clearEmptySquares(board, rowX, colY)
local rowMax = #board
local colMax = #board[1]
board[rowX][colY].info.btn = false -- receive in the box to show/hide
-- if board[rowX-1][colY-1].imgBomb ~= nil then
--     board[rowX-1][colY-1].imgBomb.isVisible = true
-- end
-- if board[rowX-1][colY-1].imgText ~= nil then
--     board[rowX-1][colY-1].imgText.isVisible = true
-- end

print("BOX["..rowX.."]["..colY.."]")

if (board[rowX][colY].info.number == 0) then

if rowX > 1 then -- ABOVE
if (colY > 1) then --LEFT
if (board[rowX-1][colY-1].info.btn == true) then
board = mod.clearEmptySquares(board, rowX-1, colY-1)
end
end
if (colY > 1) then --CENTER
if (board[rowX-1][colY].info.btn == true) then
board = mod.clearEmptySquares(board, rowX-1, colY)
end
end
if (colY < colMax) then --RIGHT
if (board[rowX-1][colY+1].info.btn == true)then
board = mod.clearEmptySquares(board, rowX-1, colY+1)
end
end
end

if rowX < rowMax then -- BELOW
if (colY > 1) then --LEFT
if (board[rowX+1][colY-1].info.btn == true) then
board = mod.clearEmptySquares(board, rowX+1, colY-1)
end
end
if (colY > 1) then --CENTER
if (board[rowX+1][colY].info.btn == true) then
board = mod.clearEmptySquares(board, rowX+1, colY)
end
end
if (colY < colMax) then -- RIGHT
if (board[rowX+1][colY+1].info.btn == true)then
board = mod.clearEmptySquares(board, rowX+1, colY+1)
end
end
end

if (colY > 1) then -- LEFT ADJACENT
if (board[rowX][colY-1].info.btn == true) then
board = mod.clearEmptySquares(board, rowX, colY-1)
end
end

if (colY < colMax) then -- RIGHT ADJACENT
if (board[rowX][colY+1].info.btn == true)then
board = mod.clearEmptySquares(board, rowX, colY+1)
end
end
end
return board
end
``````

Oh, well, I mean the two `CENTER` cases wouldn’t seem to need column checks, at all. As is, column 1 will be botched (I’m guessing that’s what we see in the last picture).

No… my code is design to search the row above the triggering cell. For the cells above, left, centre, right.
Then the code is designed to search the row below the triggering cell. For the cells below left, centre, right.
This just leave the two cells directly left and right of the trigger cell.
There is no column search.

This is what I meant by `CENTER`. In those two cases the column check is pointless (you don’t need to look left or right, so there’s no reason to guard) and I assume when `colY` is 1, it’s skipping the logic.

Oh ok - let me comment out and test your theory - thanks for helping by the way… if easier we can chat on discord.

so I tweaked my code to this - still problem persists with north and south cells reveals.

``````function mod.clearEmptySquares(board, rowX, colY)
local rowMax = #board
local colMax = #board[1]
board[rowX][colY].info.btn = false -- receive in the box to show/hide
print("BOX["..rowX.."]["..colY.."]")

if (board[rowX][colY].info.number == 0) then

if rowX > 1 then -- ABOVE
if (colY > 1) then --LEFT
if (board[rowX-1][colY-1].info.btn == true) then
board = mod.clearEmptySquares(board, rowX-1, colY-1)
end
if (board[rowX-1][colY].info.btn == true) then
board = mod.clearEmptySquares(board, rowX-1, colY)
end
end
-- if (colY > 1) then --CENTER
--     if (board[rowX-1][colY].info.btn == true) then
--         board = mod.clearEmptySquares(board, rowX-1, colY)
--     end
-- end
if (colY < colMax) then --RIGHT
if (board[rowX-1][colY+1].info.btn == true) then
board = mod.clearEmptySquares(board, rowX-1, colY+1)
end
end
end

if rowX < rowMax then -- BELOW
if (colY > 1) then --LEFT
if (board[rowX+1][colY-1].info.btn == true) then
board = mod.clearEmptySquares(board, rowX+1, colY-1)
end
if (board[rowX+1][colY].info.btn == true) then
board = mod.clearEmptySquares(board, rowX+1, colY)
end
end
-- if (colY > 1) then --CENTER
--     if (board[rowX+1][colY].info.btn == true) then
--         board = mod.clearEmptySquares(board, rowX+1, colY)
--     end
-- end
if (colY < colMax) then -- RIGHT
if (board[rowX+1][colY+1].info.btn == true)then
board = mod.clearEmptySquares(board, rowX+1, colY+1)
end
end
end

if (colY > 1) then -- LEFT ADJACENT
if (board[rowX][colY-1].info.btn == true) then
board = mod.clearEmptySquares(board, rowX, colY-1)
end
end

if (colY < colMax) then -- RIGHT ADJACENT
if (board[rowX][colY+1].info.btn == true)then
board = mod.clearEmptySquares(board, rowX, colY+1)
end
end
end
return board
end

``````

wouldn’t you loop from `x-1`, `x+1` and `y-1`, `y+1`?

Change that to something like

``````if rowX > 1 then -- ABOVE
if (colY > 1) then --LEFT
if (board[rowX-1][colY-1].info.btn == true) then
board = mod.clearEmptySquares(board, rowX-1, colY-1)
end
end
-- NOT inside the if statement
if (board[rowX-1][colY].info.btn == true) then
board = mod.clearEmptySquares(board, rowX-1, colY)
end
--   end
-- if (colY > 1) then --CENTER
--     if (board[rowX-1][colY].info.btn == true) then
--         board = mod.clearEmptySquares(board, rowX-1, colY)
--     end
-- end
``````

and likewise for the below case, and see what you get.

here is some pseudo code

``````for i = x-1, x+1 do
for j = y-1, y+1 do
if <in bounds i, j> then <do something> end
end
end
``````

you can then easily extend to support looping out 2 or 3 loops easily, like this

``````local n = 2
for i = x-n, x+n do
for j = y-n, y+n do
if <in bounds i, j> then <do something> end
end
end
``````
1 Like

THANK YOU SO MUCH SGS

I think with my initial code, i over thought it way to much!

Here was the resulting function code, for anyone who reads this forum post in the future and fancies learning from this

``````function mod.clearEmptySquares(board, rowX, colY)
local rowMax = #board
local colMax = #board[1]

local count = 1

if (board[rowX][colY].info.number == 0) then
for i = rowX-count, rowX+count do -- itterate matrix
for j = colY-count, colY+count do -- itterate matrix
if i >=1 and i <= rowMax then -- stay within board boundaries
if j >=1 and j <= colMax then -- stay within board boundaries

if (board[i][j].info.number >=1) then -- found clearing edge
board[i][j].info.btn = false
elseif ( i == rowX) and (j == colY) then -- found myself/trigger box
board[i][j].info.btn = false
elseif (board[i][j].info.number == 0 ) and ( board[i][j].info.btn == true ) then -- investigate box whose btn still shows
mod.clearEmptySquares(board, i, j)
end

end
end
end
end

end

return board
end
``````

FYI, you can also optimize some more here (makes it more readable too)…

``````local tile = board[i][j].info
if (tile.number >=1) then -- found clearing edge
tile.btn = false
elseif ( i == rowX) and (j == colY) then -- found myself/trigger box
tile.btn = false
elseif (tile.number == 0 ) and ( tile.btn == true ) then -- investigate box whose btn still shows
mod.clearEmptySquares(board, i, j)
end

``````
2 Likes

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.