PROGRAM LE_TIERCE;

(* Pour l'‚nonc‚, voir la proc‚dure AVERTIS.
   La diffult‚ de ce programme est de jongler de fa‡on abstraite
   avec les r‚f‚rences et les contenus des diff‚rentes cases des tableaux *)

USES CRT;

CONST NB_CHEVAUX = 10;

TYPE  INTXXX = ARRAY [1..NB_CHEVAUX] OF INTEGER;  (* XXX car le nombre de cases peut changer en fonction de la constante *)

VAR   CHEVAL, TIERCE: INTXXX; (* CHEVAL et TIERCE sont des vecteurs identiques pouvant contenir des entiers *)
      ORDRE,                  (* pour v‚rifier si le tierc‚ est gagn‚ dans l'ordre *)
      DESORDRE,               (* pour v‚rifier si le tierc‚ est gagn‚ dans le d‚sordre *)
      COMBIEN: SHORTINT;      (* pour savoir combien de chevaux participent r‚ellement … la course *)
                              (* SHORTINT est un entier court pouvant contenir des valeurs allant de
                                 -128 … +127, ce qui est assez pour le nombre de chevaux participant … une course *)
PROCEDURE AVERTIS;
          BEGIN
          WRITELN ('Le programme simule une course de chevaux (tierc‚)');
          WRITELN ('Le programme demande d''abord le nombre de chevaux participant … la course');
          WRITELN ('Le programme demande ensuite le tierc‚ de l''utilisateur');
          WRITELN ('Le programme simule alors la course de chevaux');
          WRITELN ('Le programme signale enfin … l''utilisateur s''il a gagn‚ le tierc‚ :');
          WRITELN ('     - dans l''ordre,');
          WRITELN ('     - dans le d‚sordre');
          WRITELN ('     - o— (malheureusement) pas du tout.');
          WRITELN;
          END;

PROCEDURE COMBIEN_DE_CHEVAUX (VAR COMBIEN: SHORTINT);
          BEGIN
          WRITELN ('La course peut comporter entre 4 et ',NB_CHEVAUX,' chevaux.');
          WRITE   ('Combien d‚sires-tu qu''il y ait de chevaux qui courent ? ');
          READLN  (COMBIEN);  (* Robustesse, on n'accepte qu'une valeur valide *)
          WHILE (COMBIEN < 4) OR (COMBIEN > NB_CHEVAUX) DO
                BEGIN
                WRITELN ('ERREUR! La valeur donn‚e n''est pas correcte');
                WRITE   ('Entre une nouvelle valeur correcte : ');
                READLN  (COMBIEN);
                END;
          END;

PROCEDURE INITIALISE (VAR CHEVAL, TIERCE: INTXXX; COMBIEN: SHORTINT);
          VAR i: INTEGER;

(* Les 0 qu'on va mettre dans les cases des tableaux ont deux r“les :
   1. Signaler si un cheval est d‚j… arriv‚ ou s'il a d‚j… ‚t‚ jou‚ (0 = pas encore arriv‚ ou pas jou‚)
   2. La valeur ayant pris la place du 0 signale l'ordre d'arriv‚e de ce cheval ou l'ordre d'arriv‚e pari‚ *)

          BEGIN
          FOR i := 1 TO COMBIEN DO
              BEGIN
              CHEVAL [i] := 0;
              TIERCE [i] := 0;
              END;
          END;

PROCEDURE PARIE (VAR TIERCE: INTXXX; COMBIEN: SHORTINT);
          VAR i, NUMERO: SHORTINT;

          BEGIN
          CLRSCR;
          WRITELN ('La course comporte ',COMBIEN,' chevaux.');
          FOR i := 1 TO 3 DO
              BEGIN
              WRITELN;
              WRITE  ('Quel est le num‚ro du cheval qui arrivera en ',i,'ø position ? ');
              READLN (NUMERO);  (* Robustesse ... *)
              WHILE (NUMERO < 1) OR (NUMERO > COMBIEN) DO  (* Tant qu'il joue un num‚ro qui n'existe pas *)
                    BEGIN                                  (* On lui demande un num‚ro qui existe *)
                    WRITE  ('ERREUR! Ce cheval ne court pas. Recommence : ');
                    READLN (NUMERO);
                    END;             (* Maintenant qu'on est s–r d'avoir un cheval qui existe ... *)
              IF TIERCE [NUMERO] <> 0 THEN  (* on peut v‚rifier s'il a d‚j… ‚t‚ jou‚ (sa case ne contient plus 0) *)
                 BEGIN
                 WRITELN ('Tu as d‚j… jou‚ ce cheval, Recommence.');
                 DEC (i);   (* La boucle va recommencer pour lire le mˆme num‚ro d'arriv‚e
                               il faut donc d‚cr‚menter i pour faire "patiner" la boucle et
                               redemander le mˆme num‚ro d'ordre d'arriv‚e jusqu'… ce qu'il soit correct *)
                 END
              ELSE
                  TIERCE [NUMERO] := i;  (* Si on en arrive l…, c'est que le num‚ro de cheval donn‚ est correct,
                                            (il participe … la course) et n'a pas d‚j… ‚t‚ jou‚.
                                            On remplace donc le 0 dans la case du num‚ro du cheval
                                            par son num‚ro d'ordre d'arriv‚e pari‚ *)
              END;
          CLRSCR;
(* R‚capitulatif facultatif, non n‚cessaire … l'examen *)
          WRITELN ('TON TIERCE :');
          FOR i := 1 TO 3 DO
              FOR NUMERO := 1 TO COMBIEN DO   (* On balaie le tableau pour trouver le num‚ro du cheval pari‚ en position i *)
                  IF TIERCE [NUMERO] = i THEN
                     WRITELN ('En ',i,'ø Position : le cheval num‚ro ',NUMERO:2);
          WRITELN;
          END;

PROCEDURE COURSE (VAR CHEVAL: INTXXX; COMBIEN, DEBUT, FIN: SHORTINT);
          VAR i, NUMERO: SHORTINT;

(* La course va se passer en deux parties pour des raisons de facilit‚:
   tout d'abord, on fera arriver les trois premiers chevaux, ce qui facilitera la v‚rification du tierc‚,
   ensuite, on fera arriver le reste des chevaux.
   La boucle de tirage au sort des chevaux … l'arriv‚e va donc "tourner" de DEBUT … FIN, ces deux valeurs
   ‚tant envoy‚es … cette proc‚dure par le programme principal lors de son appel (qui aura lieur deux fois) *)

          BEGIN
          FOR i := DEBUT TO FIN DO
              BEGIN
              REPEAT
                    NUMERO := RANDOM (COMBIEN) + 1;  (* tirage au sort d'un NUMERO parmi COMBIEN chevaux ... *)
              UNTIL CHEVAL [NUMERO] = 0;   (* jusqu'… ce qu'il y ait 0 dans sa case, signe qu'il n'est pas d‚j… arriv‚ *)
              CHEVAL [NUMERO] := i;        (* On retient alors la position i du cheval NUMERO *)
              WRITELN ('En ',i:2,'ø Position : le cheval num‚ro ',NUMERO:2);  (* Affichage de l'arriv‚e de ce cheval *)
              END;
          END;

PROCEDURE VERIFIE (VAR ORDRE, DESORDRE: SHORTINT; COMBIEN: SHORTINT; TIERCE, CHEVAL: INTXXX);
          VAR i: INTEGER;

(* AprŠs l'arriv‚e des 3 premiers chevaux, on va v‚rifier le tierc‚ en comparant les deux tableaux:
   TIERCE, la tableau du pari de l'utilisateur, et CHEVAUX, le tableau de tirage au sort de l'arriv‚e des chevaux.
   Si toutes les cases sont identiques 2 … 2, ORDRE sera = … COMBIEN, le tierc‚ est gagn‚ dans l'ordre.
   Sinon, si les 0 sont aux mˆmes places, DESORDRE sera = … COMBIEN-3, le tierc‚ est gagn‚ dans le d‚sordre. *)

          BEGIN
          ORDRE := 0;              (* Initialisation du compteur ORDRE *)
          DESORDRE := 0;           (* Initialisation du compteur DESORDRE *)
          FOR i := 1 TO COMBIEN DO (* On balaie toute la longueur des tableaux *)
              IF CHEVAL [i] = TIERCE [i] THEN  (* Si les deux cases ont des contenus indentiques ... *)
                 BEGIN
                 INC (ORDRE);           (* on ajoute 1 au compteur ORDRE *)
                 IF CHEVAL [i] = 0 THEN (* Si, en plus d'ˆtre ‚gales, ces cases sont = … 0, ... *)
                    INC (DESORDRE);     (* on ajoute 1 au compteur DESORDRE *)
                 END;
          END;

PROCEDURE RESULTAT (ORDRE, DESORDRE, COMBIEN: SHORTINT);
          BEGIN
          WRITELN;
          IF ORDRE = COMBIEN THEN             (* Les contenus de toutes les cases ‚taient identiques 2 … 2 *)
             WRITELN ('BRAVO!!! tu as gagn‚ le tierc‚ dans l''ordre')
          ELSE
              IF DESORDRE = COMBIEN - 3 THEN  (* Tous les 0 ‚taient aux mˆmes endroits dans les 2 tableaux *)
                 WRITELN ('PAS MAL! tu as gagn‚ le tierc‚ dans le d‚sordre')
              ELSE                            (* Ni dans l'ordre, ni dans le d‚sordre *)
                  WRITELN ('Pas de chance, tu as perdu le tierc‚.');
          END;

BEGIN (* du programme principal *)
RANDOMIZE;
CLRSCR;
AVERTIS;
COMBIEN_DE_CHEVAUX (COMBIEN);
INITIALISE (CHEVAL, TIERCE, COMBIEN);
PARIE (TIERCE, COMBIEN);
WRITELN ('LES CHEVAUX A L''ARRIVEE :');
COURSE (CHEVAL, COMBIEN, 1, 3);                     (* On fait d'abord arriver les 3 premiers chevaux *)
VERIFIE (ORDRE, DESORDRE, COMBIEN, TIERCE, CHEVAL); (* On v‚rifie le pari par rapport … l'arriv‚e *)
COURSE (CHEVAL, COMBIEN, 4, COMBIEN);               (* On fait arriver le reste des chevaux *)
RESULTAT (ORDRE, DESORDRE, COMBIEN);                (* On affiche le r‚sultat du pari tierc‚ *)
READLN;
END.
