INFORMATIQUE

TP 10

Jeu de la Vie


1. Objectif
L'un des premiers programmes qui essayait de simuler le processus d'expansion de la vie était "Life" de J. Conway en octobre 1970.

Le principe de base de ces programmes consiste à calculer les générations successives en partant d'une population initiale.

Notre population initiale sera représentée par les cellules d'une grille. Nous utiliserons des cellules très petites et chaque cellule pourra contenir une bactérie. La présence d'une bactérie sera matérialisée par la couleur rouge.

Les règles suivantes déterminent la naissance, la survie ou la mort d'une bactérie :

2. Mise en place des composants

La liste des composants figure dans le tableau ci-dessous :

Fiche principale (Form) Name fmVie
Caption Jeu de la vie
StringGrid Name grMilieu
ColCount 100
RowCount 70
FixedCols 0
FixedRows 0
DefaultColWidth 4
DefaultRowHeight 4
Height 353
Width 505
ScrollBars ssNone
Button1 Name btInitialiser
Caption &Initialiser
Button2 Name btDepart
Caption &Départ
Enabled False
Button3 Name btStop
Caption &Stop
Enabled False
Button4 Name btQuitter
Caption &Quitter

Mettre en place, sans plus attendre le code habituel en réponse à un clic sur le bouton btQuitter.

Enregistrer tout :

Si on lance l'application, l'écran doit alors ressembler à ceci :

3. Initialisation du jeu

Il s'agit d'ensemencer, en quelque sorte, la grille avec 1000 bactéries disposées au hasard (la grille dispose de 7000 cases). La présence d'une bactérie dans la grille sera marquée par la présence du chiffre 1. Cependant, comme les cellules sont très petites (4 x 4 pixels) le contenu des cellules sera invisible. C'est la raison pour laquelle nous devrons dessiner la cellule en rouge lorsqu'elle sera " infectée " par une bactérie.
Pour cela , il nous faut agir sur l'événement OnDrawCell de la grille :

procedure TfmVie.grMilieuDrawCell(Sender: TObject; ACol, ARow: Integer;
                           Rect: TRect; State: TGridDrawState);
begin
   with grMilieu do
   begin
      if cells[ACol,ARow]='' then Canvas.brush.Color:=clWhite
                             else Canvas.Brush.Color:=clRed;
      Canvas.Brush.Style:=bsSolid;
      Canvas.Rectangle(Rect.Left-1,Rect.Top-1,Rect.Right+1,Rect.Bottom+1);
   end;
end;

Ajouter une variable globale nommée blStop de type boolean : la déclaration de cette variable doit se faire juste après la variable fmVie : TfmVie. Cette variable nous permettra d'interrompre l'évolution d'une population bactérienne.

L'initialisation du jeu se fera sur un clic sur le bouton btInitialiser. Voici ce qu'il faut mettre dans le code de la procédure btInitialiserClick :

Voici ce qu'on doit obtenir lorsqu'on clique sur le bouton Initialiser :

4. Départ du jeu

Il s'agit maintenant de calculer et d'afficher les générations successives de bactéries. Ce processus se fait dans une boucle qui s'arrête uniquement lorsqu'on clique sur le bouton Stop ou sur le bouton Quitter. On peut tout de suite taper le code de la méthode btStopClick :

procedure TfmVie.btStopClick(Sender: TObject);
begin
   blStop:=True;
   btStop.Enabled:=false;
   btDepart.Enabled:=true;
   btInitialiser.Enabled:=true;
end;

Il nous faut également modifier le code de la méthode btQuitterClick :

procedure TfmVie.btQuitterClick(Sender: TObject);
begin
   btStopClick(sender);
   Close;
end;

Pour le calcul d'une nouvelle génération, il faut procéder en 2 temps :

function NbCellulesInfectees(i,j:byte):byte;
begin
   NbCellulesInfectees:=
      TableauVie[i-1,j-1]+TableauVie[i,j-1]+TableauVie[i+1,j-1]+
      TableauVie[i-1,j]+TableauVie[i+1,j]+
      TableauVie[i-1,j+1]+TableauVie[i,j+1]+TableauVie[i+1,j+1];
end;

Cette fonction utilise la variable TableauVie qui doit être déclarée globalement, juste après la variable blStop : TableauVie : array[0..99,0..69] of byte;

La boucle principale de la méthode btDepartClick pourra être la suivante :

repeat
   for x:=1 to 99 do for y:=0 to 69 do
      if grMilieu.cells[x,y]='1' then TableauVie[x,y]:=1
                                 else TableauVie[x,y]:=0;
   for x:=1 to 98 do for y:=1 to 68 do
   begin
      n:=NbCellulesInfectees(x,y);
      if TableauVie[x,y]=1 then
      begin
         if (n<2)or(n>3) then grMilieu.cells[x,y]:=''
      end
      else if n=3 then grMilieu.cells[x,y]:='1';
   end;
   grMilieu.Refresh;
   Application.ProcessMessages;
until blStop;

L'instruction grMilieu.Refresh est indispensable pour permettre à l'application d'actualiser l'affichage de la grille. Sinon, la grille ne s'actualiserait que lorsque les calculs s'arrêteraient.

L'instruction Application.ProcessMessages est également indispensable. Elle permet d'interronmpre les calculs afin que Windows puisse gérer les éventuels événements en attente de traitement. Si on ne faisait pas cela, un clic sur le bouton Stop ne serait jamais réalisé.

Avant cette boucle principale, il faut :

Au bout quelques générations, voici ce qu'on peut obtenir :

<< TP précédent      TP suivant >>

Retour à la liste des TP