Game Development Community

Matching logic question

by Takara Mitsumi · in Torque Game Builder · 04/08/2010 (9:28 pm) · 5 replies

I've been spending over 3 days trying to figure this out. I've looked over the match-3 program that someone had posted here, and I've been trying to apply some of the logic used there to make an alternate version on my own.

I'm not really doing a match-3, but the logic is supposed to be similar (and I thought it would be a lot simpler to do). Basically, depending on what color a game piece is clicked on, then all of those same color pieces that are surrounding it would disappear. You can match 2 pieces or more, as long as the colors are connected. I made a picture to illustrate this:

i39.tinypic.com/n3t07r.png
All of the red dots highlighted in yellow are supposed to be the ones that disappear when you click on a red dot in that section, because they are all connected. However, when I used/altered the match-3 code, not all of the red dots disappear when you click on a red dot. Some of the red dots that are connected still remain, as if the code isn't checking the left/right/up/down positions the further away you get from the original dot you clicked.

As I've said, I've spent 3 days nonstop on this and I can't seem to figure out what I'm doing wrong with the logic/matching part of the program. Does anyone have any ideas?


This is the main part of the match code that I've been messing with:

function Board::checkMatch(%this, %xArray, %yArray)
{


  for (%i = %xArray; %i < %this.xCount; %i++)
  {
    for (%j = %yArray; %j < %this.yCount; %j++)
    {


      //check horizontal first
      %matchCount = 0;

      %a = %i;
      %b = %j;

      //get the matching color
      %c = %this.pieces[%a,%b].pieceColor;

      //get the check start point one position to the right (i.e. don't count myself)
      %a++;
   
      //move right from the gem being checked without exceeding the right border
      while (%a < %this.xCount)
      {
        if (%this.pieces[%a,%b].pieceColor $= %c && !%this.pieces[%a,%b].isSmall)
        {
          %a++;
          %matchCount++;     
        }
        else
        {
          %a = %this.xCount;
        }
      }

      //get the check start point and move one position to the left
      %a = %i - 1;

      //move left from the gem being checked without exceeding the bounds of the left border
      while (%a >= 0)
      {
        if (%this.pieces[%a,%b].pieceColor $= %c && !%this.pieces[%a,%b].isSmall)
        {
          %a--;
          %matchCount++;
        }
        else
        {
          %a = -1;
        }
      }

      //check if at least 2 minimum matches were achieved
      //flag all the gems that match
      if (%matchCount >= 1)
      {
        //get the check start point
        %a = %i;

        //move right
        while (%a < %this.xCount)
        {
          if (%this.pieces[%a,%b].pieceColor $= %c && !%this.pieces[%a,%b].isSmall)
          {
            %this.pieces[%a,%b].match = true;
            %a++;
          }
          else
          {
            %a = %this.xCount;
          }
        }

        //get the check start point
        %a = %i - 1;

        //move left
        while (%a >= 0)
        {
          if (%this.pieces[%a,%b].pieceColor $= %c && !%this.pieces[%a,%b].isSmall) 
          {
            %this.pieces[%a,%b].match = true;
            %a--;
          }
          else
          {
            %a = -1;
          }
        }
      }
    
      //check vertical next 
      %matchCount = 0;

      //get the check start point but one position down (i.e don't count myself)
      %a = %i;
      %b = %j + 1;

      //move down from the gem being checked
      while (%b < %this.yCount)
      {
        if (%this.pieces[%a,%b].pieceColor $= %c && !%this.pieces[%a,%b].isSmall)
        {
          %b++;
          %matchCount++;
        }
        else
        {
          %b = %this.yCount;
        }
      }

      //get the check start point
      %b = %j - 1;

      //move up from the gem being checked
      while (%b >= 0)
      {
        if (%this.pieces[%a,%b].pieceColor $= %c && !%this.pieces[%a,%b].isSmall)
        {
          %b--;
          %matchCount++;
        }
        else
        {
          %b = -1;
        }
      }

      //check if minimum matches were achieved
      if (%matchCount >= 1)
      {
        //get the check start point
        %b = %j;

        //move down
        while (%b < %this.yCount)
        {
          if (%this.pieces[%a,%b].pieceColor $= %c && !%this.pieces[%a,%b].isSmall)
          {
            %this.pieces[%a,%b].match = true;
            %b++;
          }
          else
          {
            %b = %this.yCount;
          }
        }

        //get the check start point
        %b = %j - 1;

        //move up
        while (%b >= 0)
        {
          if (%this.pieces[%a,%b].pieceColor $= %c && !%this.pieces[%a,%b].isSmall)
          {
            %this.pieces[%a,%b].match = true;
            %b--;
          }
          else
          {
            %b = -1;
          }
        }
      }
    }
  }




  for (%i = 0; %i < %this.getTileCountX(); %i++)
  {
    for (%j = 0; %j < %this.getTileCountY(); %j++)
    {
      if (%this.pieces[%i,%j].match $= true)
      {
       %this.pieces[%i,%j].setSize(0,0);

      }
    }
  
  }

xArray and yArray are the x/y coordinates of the current clicked piece on the game board.


#1
04/09/2010 (1:41 am)
You're going to need to do a depth-first search from the clicked tile to find all of the tiles you need and set ".match" to true on those.
#2
04/09/2010 (6:57 am)
How do I do that? I've heard of depth-first searching, but how do I do that using TGB? Is there an example that I can look at that does this?
#3
04/09/2010 (9:49 am)
ill try to write up an example, my code for my team does this but i wasnt able to included in the community match3engine i posted. i am on very strict time constraints. basically my match cod iterates horizontal virtical and diaganal all in different functions and returns arrays of the grid positions that are a match then i have a recheck that i run before discarding them. some times the included match code finds blocks that arnt the correct color. i also added more dynamic fields to the jewels. i hope this can give you an idea of a direction to go with the matching engine
#4
04/09/2010 (12:06 pm)
Thanks. I've been researching some of it online, but I'm still running into a wall when it comes to translating this into torquescript. I have the single 'check horizontal' and 'check vertical' down, but having to do depth-searching on each game piece is something I'm still having trouble with trying to translate into torquescript logic.
#5
04/09/2010 (1:54 pm)
First, look at this recent post: www.torquepowered.com/community/forums/viewthread/111739/1#comment-729573. You'll want the stack code at the top.

Then, your general logic will be like the following:
%color = GET_COLOR_OF_TILE_CLICKED_ON;
%maxX = %this.xCount;
%maxY = %this.yCount;

%stack = new ScriptObject() { class = Stack; };

%stack.push( COORDINATES_OF_TILE_CLICKED_ON );

while( %stack.len > 0 )
{
  %top = %stack.pop();
  %x = getWord( %top, 0 ); %y = getWord( %top, 1 );
  if( %this.pieces[%x,%y].match || 
      %this.pieces[%x,%y].isSmall ) continue; // Already seen this
  if( %this.pieces[%x,%y].pieceColor == %color )
  {
    %this.pieces[%x,%y].match = true;
    if( %x > 0 )   
      %stack.push( (%x - 1) SPC %y );   
    if( %x < %maxX - 1 )   
      %stack.push( (%x + 1) SPC %y );   
    if( %y > 0 )   
      %stack.push( %x SPC (%y - 1) );   
    if( %y < %maxY - 1 )   
      %stack.push( %x SPC (%y + 1) );
  }
}

%stack.delete();

Note: I didn't actually try out this code, and a lot of it still needs filled in by, you... I'm just trying to lay out the basic steps.