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