Programming a Memory Game in Delphi - Final Part (4) - Coding the Algorithm

'

Recap

In part 1 of Programming a Memory Game we explained how to create the form and drawgrid at design time. In part 2 we started writing the actual code, in this the third part of the tutorial we will go into drawing the grid that the game is played on. In Part 3 - Draw the Grid we explained how to paint the TDrawGrid we will now move on and complete the.

At the end of this page you will find the full Delphi 7 source code.

The Main Algorithm

The algorithm is very simple. In this tutorial all the code can be found in the DrawGridSelectCell event. I would normally recommend structuring the program in a more object oriented manner but for the purpose of this tutorial it makes it easier to follow.

When the player clicks on a cell:

If the cell is ALREADY_MATCHED then
  Exit; // Because clicking on an ALREADY_MATCHED cell has no effect

if there are no previously visible cells then
  make it the first visible cell
else if there is a single visible cell then
begin
  make it the second visible cell;
  if it is the partner of the first one then
    make both of them ALREADY_MATCHED
end
else this means that there are two visible cells so do the following:
   make both of them invisible, and make the current one visible

Implementation Of Algorithm

In order to keep the information of which cells are currently visible (at most two of them can be visible at an instant), we need two additional variables. We also need a variable to keep the number of visible cells:

var
  FirstCell, SecondCell : integer;
  NumberOfVisibleCells : integer;

When a new game starts, NumberOfVisibleCells should be initialized:

procedure TfrmMain.itemNewGameClick(Sender: TObject);
var
  i : integer;
begin
  RandomizeThePermutationArray;
  AssignPartnerships;
  AssignImagesToCells;
  InitializeCellModes;

  for i := 0 to 19 do
    RedrawCell(i); 
 
  NumberOfVisibleCells := 0
end;

We will implement the algorithm above in the OnSelectCell event of the drawgrid.

procedure TfrmMain.DrawGridSelectCell(Sender: TObject; ACol, ARow: Integer; 
                                      var CanSelect: Boolean);
begin

end;

This event is fired before a cell is selected. The selected cell is characterized by the ACol and the ARow parameters. ACol indicates the column of the cell, and ARow the row of the cell. The CanSelect parameter can be used to prevent a cell from being selected, but we do not need this parameter.

procedure TfrmMain.DrawGridSelectCell(Sender: TObject; ACol, ARow: Integer; 
                                      var CanSelect: Boolean);
var
  index : integer;
begin
  index := LinearIndexOf(ARow, ACol);  // Calculate the linear index of the 
                                       // current cell

 // If it is an already matched cell, there is nothing to do...

  if ModeOfCell[index] = ALREADY_MATCHED then
    exit;

// If there is no visible cells, then make it the first visible one
// and draw it with its new mode, and make the number of visible cells 1 
 
 if NumberOfVisibleCells = 0 then
  begin
    FirstCell := index;
    ModeOfCell[FirstCell] := CELL_VISIBLE;
    RedrawCell(FirstCell);
    NumberOfVisibleCells := 1
  end
  else if (NumberOfVisibleCells = 1) and (FirstCell <> index) then
// If there is a single visible cell and it is different from the current cell,
// then make the current one the second visible cell and draw it with its new mode
  begin
    SecondCell := index;

    ModeOfCell[SecondCell] := CELL_VISIBLE;
    RedrawCell(SecondCell);

    // These two visible cells may be the partner of each other
    // If it is (so they match), wait a while and then make both ALREADY_MATCHED
    // and then draw them with their new modes. We wait a while (sleep) because 
    // if we don't, both of the cells will disappear quickly before the player 
    // sees the drawing of the second one. 
 
    if PartnerOf[SecondCell] = FirstCell then 
    begin
      Sleep(100);

      ModeOfCell[FirstCell] := ALREADY_MATCHED;
      RedrawCell(FirstCell);

      ModeOfCell[SecondCell] := ALREADY_MATCHED;
      RedrawCell(SecondCell);

      NumberOfVisibleCells := 0
    end
    else 
    // If they don't match, just arrange the number of visible cells accordingly
      NumberOfVisibleCells := 2
  end
  else begin // This means that there are two visible cells

   if (FirstCell <> index) and (SecondCell <> index) then
   // If current cell is different from both visible cells, then draw it,
   // if it is one of them, we don't need to redraw it again, because it is 
   // already displayed.
   begin
     ModeOfCell[index] := CELL_VISIBLE;
     RedrawCell(index);
   end;

   if FirstCell <> index then  // we check it because a visible cell can be 
                               // clicked again
   begin
     ModeOfCell[FirstCell] := CELL_INVISIBLE;
     RedrawCell(FirstCell);
   end;

   if SecondCell <> index then
   begin
     ModeOfCell[SecondCell] := CELL_INVISIBLE;
     RedrawCell(SecondCell);
   end;

   FirstCell := index;

   NumberOfVisibleCells := 1
  end
end;	   

Source Code

As promised you can download the Delphi 7 source code in its entirety

Delphi Tutorial - Programming a Memory Game - Part 1
Programming a Memory Game in Delphi - Part 2 - Starting to Code
Programming a Memory Game in Delphi - Part 3 - Drawing the Grid
Programming a Memory Game in Delphi - Part 4 - Coding the Algorithm


Google
Web www.Delphi-Central.com
Delphi Central - Delphi Programming Tutorials, Hints and Tips