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

Maybe iterate through the rows using a for loop ?

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
-- 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

@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,

?:)

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?

ok if you use my code and have problems just let me know

@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,

?:)

made a few changes to my code above

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
-- 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()

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

views:1795 update:2011/9/26 8:07:09
corona forums © 2003-2011