Game Development Community

Connect 4 style game

by Michael Branin · in Torque Game Builder · 01/12/2007 (10:40 am) · 5 replies

I am working with my son on a connect 4 style type of game for his computer Science project. We have figured out the board and got the pieces dropping ect but .. How would I go about checking if 4 peices in a row are matching? I have scoured every T2D board here looking for any reference as to how to check this, I have emailed people that have released games to do similar things( Marble Tactics, Phantasia ect) but so far noone has been forthcoming on how to do this in Game Builder. Can anyone help out here?

#1
01/12/2007 (10:43 am)
Look at the TDN tutorial for Tetris.
#2
01/12/2007 (10:49 am)
I did that covers filling an entire line no matter what the color of the block is. That was the first tutorial I looked at. What I need is something that says hey .. 4 checkers of the same color are lined up so we have a winner.
#3
01/12/2007 (11:02 am)
Well, assuming that you can access the color of pieces in some sort of 2D fashion, it could be done something like this (the most unoptimized example ever):

go through all the pieces
for each one, run some function from that position
 in each direction that returns true if there were four
 in a row or false if it hit an edge or the wrong color

Obviously, the "some function" would have to abstracted a bit perhaps - like horizontal, vertical, and diagonal if you wanted, but that's easy - just loops - with a counter that says how many of the same color it has found.

Hope that made sense and was the kind of direction you were looking for ;)
#4
01/12/2007 (12:38 pm)
This actually isn't a particularly trivial algorithm, so here's some direction on how I would set it up:

Assumption: this is one of the few times where a two dimensional array makes perfect sense. I am assuming that you have used an array to represent the board locations in the game, and that the upper left hand corner is "-1, -1", while the lower right hand corner is "1, 1". There are other ways to represent your board layout of course, so you may not (yet) have this set up.

First, every time a player drops a peice into the game board, add that piece to a SimSet for that player.

Setup: (note, this is just one way, and not the elegant one, to do this. it should be part of the player's network connection established callback, etc etc).
$Player1Pieces = new SimSet(Player1Pieces);
$Player2Pieces = new SimSet(Player2Pieces);
Whenever the game piece is dropped into play, you need to do the following algorithm:

"Starting at the final resting position of the newly played piece, iterate over each adjacent board position and check to see if a valid piece exists in that board position for the current player".

--no: move to next adjacent board position
--yes: using the offset direction from the newly played piece towards the current adjacent piece, check the next piece in a line. Repeat until you either have found a series of 4, or an "interrupting" piece/board position (edge of game board, other player's piece).

Ok, now, to setup properly:

--add the piece to the correct player piece simset (PlayerXPieces.add(%newPiece); )

Next, have an algorithm to iterate over adjacent board positions:

For this type of algorithm, it makes good sense to use a "local reference" coordinate system, centered on the piece that was just dropped. In other words, no matter where the piece actually is, we treat it as "0,0", and then go around the box of adjacent positions--which are simply offset by either -1, 0, or 1 for each of our two coordinates.

Please realize that this is an algorithm reference coordinate system, we'll worry about how to implement it later:

This might be hard to picture, so I'll try to do a quick ASCII diagram:

-1,-1   0,-1  1,-1
-1, 0   0,0   1, 0
-1, 1   0,1   1, 1

We can set up a nice little nested for loop to iterate over all 8 adjacent positions:

for (%XDir = -1, %XDir <= 1; %XDir++)
{
   for (%YDir = -1, %YDir <= 1; %YDir++)
   {
      // this portion of the code will be iterated 9 times, one for each adjacent spot, plus our original spot
   }
}

Now, looking at our top level algorithm, if we find an adjacent game board location that has a correctly colored game piece, then we want to continue to check in that direction, so we'll need an algorithm to do so:

--nextPosition = currentPosition + (XDir, YDir), numberInSequence = 1 (the original piece)
--if (nextPosition has correct piece), numberInSequence++, check for correct piece at NextPosition + (XDir, YDir)

This type of algorithm is most appropriately implemented using recursion, which isn't necessarily something TorqueScript handles elegantly, but we can certainly accomplish it with some global variables:

$WinTest::numberInSequence = 1; // this is our counter to see how many we have in sequence this check.
$WinTest::WinningSequence = false;

function checkNextPosition(%playerPieces, %currentLocation, %XDir, %YDir)
{
   // %playerPieces will have the ObjectID of the set of pieces for the current player--i.e. Player1Pieces, Player2Pieces
   // %currentLocation == our current coordinate being checked
   // %XDir--the direction on the X axis we need to check
   // %YDir--the direction on the Y axis we need to check
  
  // calculate our adjacent location in the proper direction:
  %nextLocationX = getWord(%currentLocation, 0) + %XDir;
  %nextLocationY = getWord(%currentLocation, 1) + %YDir;
  %nextLocation = %nextLocationX SPC %nextLocationY;
  
   // here we need a way to find out if a piece is at this location, and if so, we can check if it is of right type:
   (game specific check here, should return a piece ObjectID if it finds one)
   %nextPiece = "findPieceAtLocation(%nextLocation);"
  if (%playerPieces.isMember(%nextPiece)
  {
     // we've found a correct piece!
     $WinTest::numberInSequence++;
     if (%WinTest::numberInSequence == 4)
     {
        // they win!
        $WinTest::WinningSequence = true;
        return;
     }
     else
     {
        // they didn't win yet, but we need to check next location
        checkNextPosition(%playerPieces, %nextLocation, %XDir, %YDir ); 
     }
  }
  else
  {
     // the next adjacent location did not contain the correct color piece. Maybe it was an opponent
     // piece, maybe it was a board edge, maybe it was empty
    return;
  }
}
(cont)
#5
01/12/2007 (12:49 pm)
Ok, so now we have the (algorithm) pieces, to summarize:

--we have a way to check each adjacent location to a placement spot
--we have a way to check a line in a certain direction to see if the streak of correct pieces continues

Now we just need to put it together:

// (run this algorithm after a piece is dropped)

$WinTest::numberInSequence = 1; // this is our counter to see how many we have in sequence this check.
$WinTest::WinningSequence = false;

for (%XDir = -1, %XDir <= 1; %XDir++)
{
    if ($WinTest::WinningSequence == true)
    {
       // we don't need to keep looping, they already found a win
       break;
    }

   for (%YDir = -1, %YDir <= 1; %YDir++)
   {
      if ($WinTest::WinningSequence == true)
      {
         // we don't need to keep looping, they already found a win
         break;
      }

      if ( (%XDir != 0) ||
           (%YDir != 0) )
     {
        // we don't want to check the object at our original drop location, hence the if check
        checkNextPosition(%PlayerPieces, %dropLocation, %XDir, %YDir);
     }
   }
}

if ($WinTest::WinningSequence == true)
{
   // player has won, do cool stuff!
}

Please note: this is all from my head, and has not been tested at all. It shouldn't be cut/paste in, but should be used to understand the basic algorithm to check for win condition.