Checking Grid Array for line patterns

Hi all!

I’m working on a puzzle game that has a grid of blocks, 5 blocks wide and 6 blocks high. Sliding the blocks into rows or columns of 4 or more of the same type ‘destroys’ these blocks.

Now, the problem I’m running into is my code to check whether a (or multiple) line of 4,5 or 6 of the same blocks exists, and to handle that situation. It’s turning into quite the code block, so I’m wondering if there’s not a simpler way, maybe with regular expressions or string searching or … At the moment I’m doing a loooot of if…elseif…elseif…elseif…end code.

Does anyone have any experience in this area?

Thanks!
Thomas [import]uid: 70134 topic_id: 14746 reply_id: 314746[/import]

Maybe iterate through the rows using a for loop ? [import]uid: 84637 topic_id: 14746 reply_id: 54542[/import]

That’s what I’m doing now, but it’s pretty heavy. Especially since I need to perform this check after every move (about every second).

Here’s my code at the moment:

local function CheckGrid()  
 -- start by initialising the CheckArray grid  
 for i = 1, 30 do  
 CheckArray[i] = 0 -- this creates an array of 30 zeros, that we use for checking later on!  
 end  
  
 -- check 6 horizontal lines for quads  
 for i = 0, 5 do  
 -- read in tilerow  
 local tile1 = Array[1+i\*5]  
 local tile2 = Array[2+i\*5]  
 local tile3 = Array[3+i\*5]  
 local tile4 = Array[4+i\*5]  
 local tile5 = Array[5+i\*5]  
  
 -- now check  
 if (tile2 == tile1) and (tile3 == tile1) and (tile4 == tile1) then  
 -- first 4 tiles in row are the same, now check if the fifth is also the same  
 if (tile5 == tile1) then  
 -- five tiles the same in this row!  
 CheckArray[1+i\*5] = CheckArray[1+i\*5] +1  
 CheckArray[2+i\*5] = CheckArray[2+i\*5] +1  
 CheckArray[3+i\*5] = CheckArray[3+i\*5] +1  
 CheckArray[4+i\*5] = CheckArray[4+i\*5] +1  
 CheckArray[5+i\*5] = CheckArray[5+i\*5] +1   
 else  
 -- only 4 first tiles the same!  
 CheckArray[1+i\*5] = CheckArray[1+i\*5]+1  
 CheckArray[2+i\*5] = CheckArray[2+i\*5]+1  
 CheckArray[3+i\*5] = CheckArray[3+i\*5]+1  
 CheckArray[4+i\*5] = CheckArray[4+i\*5]+1  
 end   
 elseif (tile3 == tile2) and (tile4 == tile2) and (tile5 == tile2) then  
 -- only four last tiles the same!  
 CheckArray[2+i\*5] = CheckArray[2+i\*5]+1  
 CheckArray[3+i\*5] = CheckArray[3+i\*5]+1  
 CheckArray[4+i\*5] = CheckArray[4+i\*5]+1  
 CheckArray[5+i\*5] = CheckArray[5+i\*5]+1  
 else  
 -- none match  
 end  
 end  
  
 -- then check 5 vertical lines for quads  
 for i = 0, 4 do  
 -- read in tilecolumn  
 local tile1 = Array[1+i]  
 local tile2 = Array[6+i]  
 local tile3 = Array[11+i]  
 local tile4 = Array[16+i]  
 local tile5 = Array[21+i]  
 local tile6 = Array[26+i]  
  
 -- now check  
 if (tile2 == tile1) and (tile3 == tile1) and (tile4 == tile1) then  
 if (tile5==tile1) then  
 if (tile6==tile1) then  
 -- all 6 tiles match!!!  
 CheckArray[1+i] = 1  
 CheckArray[6+i] = 1  
 CheckArray[11+i] = 1  
 CheckArray[16+i] = 1  
 CheckArray[21+i] = 1  
 CheckArray[26+i] = 1  
 else  
 -- first 5 tiles match!!!  
 CheckArray[1+i] = 1  
 CheckArray[6+i] = 1  
 CheckArray[11+i] = 1  
 CheckArray[16+i] = 1  
 CheckArray[21+i] = 1  
 end  
 else   
 -- first 4 tiles match!!!  
 CheckArray[1+i] = 1  
 CheckArray[6+i] = 1  
 CheckArray[11+i] = 1  
 CheckArray[16+i] = 1  
 end  
 elseif (tile3 == tile2) and (tile4 == tile2) and (tile5 == tile2) then  
 if (tile6 == tile2) then  
 -- last 5 tiles match!!!  
 CheckArray[6+i] = 1  
 CheckArray[11+i] = 1  
 CheckArray[16+i] = 1  
 CheckArray[21+i] = 1  
 CheckArray[26+i] = 1  
 else  
 -- middle 4 tiles match!!!  
 CheckArray[6+i] = 1  
 CheckArray[11+i] = 1  
 CheckArray[16+i] = 1  
 CheckArray[21+i] = 1  
 end  
 elseif (tile4 == tile3) and (tile5 == tile3) and (tile6 == tile3) then  
 -- last 4 tiles match!!!  
 CheckArray[11+i] = 1  
 CheckArray[16+i] = 1  
 CheckArray[21+i] = 1  
 CheckArray[26+i] = 1  
 else  
 -- no tiles match!!!   
 end  
 end  
  
 -- Now evaluate checkarray: Did something match???  
 print("check")  
 local matchFound = false  
 for i = 1, 30 do  
 if (CheckArray[i] == 1) then  
 matchFound = true  
 end  
 end  
  
 PrintArray(CheckArray, "CheckArray")  
  
 if (matchFound == true) then  
 print("match")  
 audio.play(matchSound)  
 DestroyTiles()  
 end  
end  

[import]uid: 70134 topic_id: 14746 reply_id: 54545[/import]

ive been working on an app that does something similar to this when i get home today ill send you some sample code. it goes though a grid of 7x9 and find matches of 2x2 or bigger

[import]uid: 7911 topic_id: 14746 reply_id: 54550[/import]

@thomas,

You are on the right track , but believe me that is Massive redundant code right there. You can modularize the checking into a function/s and reduce that into lesser lines of code.

Have a look at my game RetroBalls here (iTunes) or a video about it here and see that a lot of calculations have to be made on every level for every colour of the ball and also considering that there are blocks in between.

cheers,

?:slight_smile: [import]uid: 3826 topic_id: 14746 reply_id: 54648[/import]

Hi Jstrahan and Jayantv,

Thanks for the help! I just got to work (morning in Belgium now) but will check in detail tonight!

Jayantv, that game looks cool! Is it out yet? [import]uid: 70134 topic_id: 14746 reply_id: 54679[/import]

ok if you use my code and have problems just let me know [import]uid: 7911 topic_id: 14746 reply_id: 54680[/import]

@thomas,

The game was released in July and is universal, the same one runs on all iOS devices, iPhones or iPads.

you can find it here iTunes App Store link

cheers,

?:slight_smile: [import]uid: 3826 topic_id: 14746 reply_id: 54681[/import]

ive changed it to work with your 5x6 grid and 4+ in a row match
have not tested but if it doesnt work it should be close

[blockcode]
– set a random game board each number stands different color block
gameData = {}
for a = 1, 30 do
gameData[a] = math.random( 1, 3 )
end

function fnCheckBlocks()
print( “fnCheckBlocks” )
popTable = {}
for ct = 1, 30 do
if ct%5 < 3 then – no need to check pass 2nd column for row match
if gameData[ct] == gameData[ct+1] and
gameData[ct] == gameData[ct+2] and
gameData[ct] == gameData[ct+3] then
pop1 = { 0, 1, 2, 3 }
for a = 1, #pop1 do
table.insert( popTable, #popTable+1, ct+pop1[a] )
end
end
end
if ct < 16 then --no need to check pass 3rd row for column match
if gameData[ct] == gameData[ct+5] and
gameData[ct] == gameData[ct+10] and
gameData[ct] == gameData[ct+15] then
pop2 = { 0, 5, 10, 15 }
for a = 1, #pop2 do
table.insert( popTable, #popTable+1, ct+pop2[a] )
end
end
end
end
–print table to terminal
for a = 1, #popTable do
print("popTable: "…popTable[a])
end
–sort table
table.sort( popTable )
–print sorted table to terminal
for a = 1, #popTable do
print("sorted popTable: "…popTable[a])
end
–unique table, removes double entries from table
local newTable = {}
local ct = nil
for k,v in pairs(popTable) do
if ct ~= v then
table.insert( newTable, #newTable+1, v )
end
ct = v
end
–print table to terminal without double entries
for a = 1, #popTable do
print("unique entry popTable: "…popTable[a])
end
popTable = nil
popTable = {}
popTable = newTable

– if #popTable > 0 then
– fnRemoveBlocks()
– end
end

fnCheckBlocks()

– now just make function to go though the popTable and remove the blocks
[/blockcode]
[import]uid: 7911 topic_id: 14746 reply_id: 54627[/import]

made a few changes to my code above [import]uid: 7911 topic_id: 14746 reply_id: 54693[/import]

Thanks!

I just tried your code, took some tiny tiny tiny errors out of it and now it works like a charm.

Here’s my adapted code, for detecting groups of 3 blocks (yep, I went from 4 to 3) in a horizontal row or vertical column:

-- set a random game board each number stands different color block  
gameData = {}  
for a = 1, 30 do  
 gameData[a] = math.random(5)   
end  
  
for y = 0,5 do  
 print(gameData[1+y\*5].." "..gameData[2+y\*5].." "..gameData[3+y\*5].." "..gameData[4+y\*5].." "..gameData[5+y\*5])  
end  
print("---------")  
  
  
function fnCheckBlocks()  
 popTable = {}  
 for ct = 1, 30 do  
 if (ct-1)%5 \< 3 then -- no need to check pass 3rd column for row match  
 if (gameData[ct] == gameData[ct+1]) and (gameData[ct] == gameData[ct+2]) then  
 pop1 = { 0, 1, 2}  
 for a = 1, 3 do  
 table.insert( popTable, #popTable+1, ct+pop1[a] )  
 end  
 end  
 end  
 if (ct \< 21) then --no need to check pass 4th row for column match  
 if (gameData[ct] == gameData[ct+5]) and (gameData[ct] == gameData[ct+10]) then  
 pop2 = { 0, 5, 10}  
 for a = 1, 3 do  
 table.insert( popTable, #popTable+1, ct+pop2[a] )  
 end  
 end  
 end  
 end  
  
 --sort table  
 table.sort(popTable)  
  
 ---unique table, removes double entries from table  
 local newTable = {}  
 local lastNumber = 0   
 for ct = 1, #popTable do  
 nextNumber = popTable[ct]  
 if (nextNumber ~= lastNumber) then  
 newTable[#newTable+1] = nextNumber  
 end  
 lastNumber = nextNumber  
 end  
  
 -- build Array with 1s where blocks match  
 local popGrid = {}  
 for i = 1, 30 do  
 popGrid[i] = 0  
 end  
  
 for i = 1, #newTable do  
 popGrid[newTable[i]] = 1  
 end  
  
 for y = 0,5 do  
 print(popGrid[1+y\*5].." "..popGrid[2+y\*5].." "..popGrid[3+y\*5].." "..popGrid[4+y\*5].." "..popGrid[5+y\*5])  
 end  
 print("---------")  
  
end  
  
fnCheckBlocks()  

By the way, the biggest (little) bug in your code was in the line:

if (ct-1)%5 \< 3 then -- no need to check pass 3rd column for row match  

You said ‘if ct%5 < 3’ but it needs to be ‘if (ct-1)%5 < 3’, or your detection ‘wraps around’ the grid - for lack of better words!

Thanks again - this is a wonderful forum :slight_smile:

Thomas
[import]uid: 70134 topic_id: 14746 reply_id: 54736[/import]

glad you got it to work it works great with my 2x2 system also
I figured the 4 in a row would be a bit large for the grid you were using
like I said I didn’t try it out just adopted it to fit for you [import]uid: 7911 topic_id: 14746 reply_id: 54737[/import]

Guys, how should I alter the code if my grid is 6x5?

I am totally lost within the table code :slight_smile:

Joakim [import]uid: 81188 topic_id: 14746 reply_id: 60785[/import]

No!!! Let’s have a true fun! Genetic algorithm or Neural Networks!!

http://www.neverreadpassively.com/2009/12/genetic-algorithm-in-lua.html

http://www.forums.evilmana.com/psp-lua-codebase/lua-neural-networks/ [import]uid: 12704 topic_id: 14746 reply_id: 60793[/import]

No I am totally lost…more then before… :slight_smile: [import]uid: 81188 topic_id: 14746 reply_id: 60795[/import]