Tile-Match Logic Explained

I posted this in the TGB Private Forums as a response to someone’s question of how to ‘perform tile-match logic’, and after I posted it and took a look at how much I wrote in such a short time, I felt the need to ‘record’ it for later use (perhaps a tutorial?)

So here goes…

For the general logic, you have a number of ways to approach the matter — you can create your tiles and apply ‘customData’ to them, such as that all tiles that ‘match’ have the same customData — as TorqueScript is type-less and numbers and words are treated as the same thing, I do not think that using numeric values would increase search performance, but it’s always best to assume numerics are faster unless you know otherwise.

As for the search … in a game like Bejewelled, you would search the entire grid, over and over, and over again until you ran out of matches — every tile has to be searched, and the search should (depending on game logic, and visual appeal) start from scratch each time a match is completed —

I believe the general ‘logic’ for bejeweled follows this, where say you have the following:

ABCD
ACCC
ABDD
BCDD

You would first find the ‘A’ (top-left) match (two tiles below), remove them, then replace them with new tiles — we’ll assume the new tiles do not cause any additional matches, k?

Now, we find the ‘CCC’ match in the second row … we remove them, move all the tiles above down one row, then fill the missing tiles (assume again, no additional matches are generated by the new tiles)

This will then create a new match, causing ‘DDD’ (bottom right) … and we then remove those tiles, move the rest down, then replace them —

For a game with bejewel’s basic ‘logic’, we would scan the tile-layer repeatedly, until we stop finding matches …

You can ‘pause’ general gameplay (user interactions) by setting some sort of a ‘search in progress’ flag, that is checked for at the start of the tilelayer::onMouseDown event (or whatever triggers your user-interaction for the tile-map)

Storing the data in the tile-layer allows for an ‘easy to code’ search to take place, but may not necessarily be the best approach for performance, especially if your scanning over hundreds of things (in the case of bejeweled, I think it’s like what … 30-60 gems on screen at a time? Thats not too bad … scanning and replacing 20 matches can be done in the blink of an eye — without special ‘match’ animations, of course)

If your looking for a performance boost, it’d be best to store a reference to your tiles custom-data in an array (you can make it multidimensional if you want, or just do some fun math)

For example, if you have a “grid” that is 8×8

ABCDEFGH
HGFDSABV
AVBGFDSS
ABCDFGEH
ABCDFGEH
ABCDFGEH
ABCDFGEH

You could store the 64 tiles ‘customdata’ in a single dimension array:

[js]$tiles[0] = “A”;
$tiles[1] = “B”;

$tiles[63] = “H”;[/js]

You could then determine matches quickly with the following math:

Tile 0,0 = 0
Tile 0,1 = 1
Tile 1,0 = 8
Tile 2,0 = 16
Tile 3,3 = 26

To find the next row, just add 8 to the current row —

Here’s a coded example:

[js]%tile = %this.pickTile(%worldPosition); // returns “4 5”;
%x = getWord(%tile, 0);
%y = getWord(%tile, 1);
%idx = %x * 8 + %y – 1;[/js]

Now — in the example grid above, all 8 columns in the last 4 rows create a ‘4-part match’

Given that our ‘match’ search algorithm is at 4,0 (5th row, 1st column == “A”)

We know that checking ‘above’ is useless, since if a match from ‘above’ were made, it would have been caught by an earlier iteration of our ‘search’ algorithm, so we simply have to look in the next possible directions — (using bejeweled logic here)

[js]%x = 4;
%y = 0;
%idx = ((%x * 8) + %y) – 1;
if($tiles[%idx] $= $tiles[%idx + 1]) match(%idx, 1);
else if($tiles[%idx] $= $tiles[%idx + 8]) match(%idx, 8);[/js]

Now, this assumes we have a function called “match()” which takes two-parameters, the “start tile” and “offset tile” that match — this “match” function would then have some logic, and would be able to determine by using the difference of %startTile and %offsetIdx, like so;

[js]function match(%startTile, %offsetIdx)
{
if($tiles[%startTile] $= $tiles[%startTile + (%offsetIdx * 2)])
{
// special ‘found a 3-way match’ logic goes here
}
else
{
return false;
}
}[/js]

Now — this is by no means a “Tutorial” on how to do matching games — and it’s not even really a thorough explaination of how to find a match — but this should definately give you both a good starting point —

Oh and, remember one thing, I love testing new games … *hint hint*

Leave a Reply