PROGRAM LE_LOTTO;

(* Pour l'‚nonc‚ du programme, voir la proc‚dure AVERTIS
   Principe de fonctionnement du programme :
   un vecteur de bool‚ens empˆche de tirer 2 fois le mˆme num‚ro au mˆme tirage
   un vecteur d'entiers permet de comptabiliser chaque num‚ro tir‚
   Les vecteurs seront initialis‚s et ensuite les 6000 tirages auront lieu. *)

USES CRT;

TYPE BOOL42 = ARRAY [1..42] OF BOOLEAN;   (* Vecteur de 42 bool‚ens *)
     INT42  = ARRAY [1..42] OF INTEGER;   (* Vecteur de 42 entiers  *)

VAR  LOTTO: BOOL42;         (* Permet de ne pas tirer 2 fois le mˆme num‚ro au mˆme tirage *)
     COMPTEUR: INT42;       (* Permet de comptabiliser le nombre de fois o— chaque tirage a eu lieu *)
     i: INTEGER;            (* Variable pour la boucle FOR qui tournera 6000 fois *)

PROCEDURE AVERTIS;
          BEGIN
          WRITELN ('Ce programme simule 6000 tirages du lotto (6 num‚ros parmi 42 + 1 compl‚ment.)');
          WRITELN ('Il affiche alors le nombre de fois o— chaque num‚ro, de 1 … 42, a ‚t‚ tir‚,');
          WRITELN ('afin de voir si le g‚n‚rateur de nombres al‚atoires fonctionne de fa‡on correcte');
          WRITELN ;
          WRITE   ('Pour lancer le programme, tape ENTREE');
          READLN;
          CLRSCR;
          END;

PROCEDURE INITIALISE (VAR LOTTO: BOOL42; VAR COMPTEUR: INT42);
          VAR i: INTEGER;

          BEGIN
          FOR i := 1 TO 42 DO
              BEGIN
              LOTTO [i] := FALSE; (* La case … FAUX signale que le num‚ro n'a pas ‚t‚ tir‚ *)
              COMPTEUR [i] := 0;  (* Initialisation des 42 compteurs *)
              END;
          END;

PROCEDURE TIRE (LOTTO: BOOL42; VAR COMPTEUR: INT42);
          VAR i, NUMERO: INTEGER;

          BEGIN
          FOR i := 1 TO 7 DO                  (* Par tirage, 7 num‚ros *)
              BEGIN
              REPEAT                          (* On recommence si le num‚ro a d‚j… ‚t‚ tir‚ *)
                    NUMERO := RANDOM (42) + 1;(* Tirage d'un num‚ro au hasard de 1 … 42     *)
              UNTIL NOT LOTTO [NUMERO];       (* Case correspondant au num‚ro … FAUX, signe
                                                 qu'il n'a pas encore ‚t‚ tir‚ *)
              LOTTO [NUMERO] := TRUE;         (* Mise de la case … VRAI car le num‚ro est retenu *)
              INC (COMPTEUR [NUMERO]);        (* Incr‚mentation du compteur correspondant au num‚ro *)
              WRITE (NUMERO:5);               (* Affichage du num‚ro … l'‚cran *)
              END;
          END;

PROCEDURE AFFICHE (COMPTEUR: INT42);
          VAR i, X, Y: INTEGER;

(* Remarque : j'en profite pour faire des fioritures,
mais … l'examen, un affichage rudimentaire du style
FOR i := 1 TO 42 DO
    WRITELN ('Le num‚ro ',i,' a ‚t‚ tir‚ ',COMPTEUR [i],' fois');
suffira. *)

          BEGIN
          WRITE ('Pour l''affichage des r‚sultats, tape ENTREE');
          READLN;
          CLRSCR;
          FOR i := 1 TO 42 DO
              BEGIN
              IF i < 22 THEN    (* L'‚cran peut afficher 24 lignes et 80 colonnes *)
                 BEGIN          (* On fera donc 2 blocs de 21 r‚sultats *)
                 X := 1;        (* Si on est dans les 21 premiers, on affiche dans la colonne 1 *)
                 Y := i;        (* … la ligne i correspondante *)
                 END
              ELSE
                  BEGIN
                  X := 41;      (* sinon, on se place dans le second bloc (colonne 41) *)
                  Y := i - 21;  (* et on recommence 21 lignes plus haut *)
                  END;
              GOTOXY (X,Y);     (* On positionne le curseur … l'endroit calcul‚ et on affiche *)
              WRITE ('Le nombre ',i:2,' a ‚t‚ tir‚ ',COMPTEUR [i]:5,' fois.');
              END;
          END;

BEGIN (* du programme principal *)
RANDOMIZE;
CLRSCR;
AVERTIS;
INITIALISE (LOTTO, COMPTEUR);
(* Le tableau COMPTEUR ne doit ˆtre initialis‚ qu'une seule fois avant la boucle REPEAT
mais le tableau LOTTO devrait ˆtre r‚initialis‚ avant chaque tirage.
L'astuce est de ne l'initialiser qu'une seule fois et ensuite, pour chaque tirage,
de le passer … la proc‚dure sous forme d'un paramŠtre VALEUR. De cette fa‡on,
le remplacement dans les cases des FAUX par les VRAI pour signaler qu'un num‚ro a ‚t‚ tir‚
ne seront pas sauvegard‚s … la fin de la proc‚dure TIRE. Le tableau LOTTO, inchang‚,
pourra servir … nouveau afin d'ˆtre envoy‚ dans la proc‚dure TIRE. *)
FOR i := 1 TO 6000 DO
    BEGIN
    WRITE ('Tirage num‚ro ',i:4,' : ');
    TIRE (LOTTO, COMPTEUR);
    WRITELN;
    END;
AFFICHE (COMPTEUR);
READLN;
END.
