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 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
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;
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