Aide pour un programme pascal

bonjour,

j'aimerais faire un programme du jeu mastermind en pascal (c'est un mini projet que je sois faire), et j'aurais besoin de votre aide pour corriger et améliorer le programme que j'ai écris , je vous signale que je suis débutant, je connais à peine les procédures, les fonctions, les tableaux les enregistrementrs ... dans mon programme j'aimerais integrer une matrice qui affiche les differentes tentatives effectuées pour trouver la combinaison secrète (cette matrice va donc être actualisée et affichée à chauqe tentative), j'aurais besoin que vous m'aidiez pour cela et que vous me montriez ce que je sois ajouter et/ou enlever pour améliorer mon programme.

Voici le programme

rogram mastermind;

Type t_combinaison=string[4];
t_frequence=array[1..6] of integer;

Procedure Initial (C:t_combinaison; T:t_frequence);
Var i,j:integer; A:char;
Begin
randomize ;
for i:=1 to 4 do
begin
random(A)
C[i]:=CouleurVersNum(A)
end;
for i:=1 to 4 do
begin
j:=CouleurVersNum(C[i]);
T[j]:=T[j]+1;
end;
end;

Function CouleurVersNum ( Coul : Char) : Integer;
Var nb : Integer;
Begin
Case Coul Of
'R': nb := 1;
'B': nb := 2;
'V': nb := 3;
'J': nb := 4;
'N': nb := 5;
'O': nb := 6;
End;
CouleurVersNum := nb
End;

Procedure Essai (Var E : t_Combinaison ; Var F : t_Frequence);
Var i, j ,nb : Integer;
Begin
For j := 1 To 6 Do
F[j] := 0;
Write('Donner une combinaison ');
ReadLn(E);
For i := 1 To 4 Do
Begin
nb := CouleurVersNum (E[i]);
F[nb] := F[nb]+1;
End;
End;

Procedure Resultat(C, E : t_Combinaison; T, F : t_Frequence);
Var i, j, nb, x, y : Integer;
Begin
x := 0;
For i := 1 To 4 Do
If C[i] = E[i]
Then Begin
x := x + 1;
nb := CouleurVersNum(C[i]);
F[nb] := F[nb]-1;
T[nb] := T[nb]-1;
End;
y := 0;
For j := 1 To 6 Do
If (T[j] > 0) AND (F[j] > 0) Then
If F[j] >= T[j]
Then y := y + T[j]
Else y := y + F[j];
WriteLn('Valeurs de x et y pour cet essai : x= ', x , ' et y = ', y);
End;

VAR C, E : t_Combinaison;
F, T : t_Frequence;
Nbessai : Integer;
BEGIN
Initial (C, T);
Nbessai := 0;
Repeat
NbEssai := NbEssai + 1;
Essai (E, F);
ResulTat ( C, E, T, F)
UNTIL (E=C) OR (NbEssai=10);
END.

Merci d'avance.

4 réponses

  1. Modérateur
    Décortiquons tout ça...

    Déjà, je fais copier-coller, et ça me met une erreur ligne 12, sur random(A)
    Vu comment tu l'utilises avec C[i]:=couleurVersNum(A) à la ligne d'après, je pense que ce que tu veux faire est plutôt C[i]:=1+random(6); mais dans ce cas C ne doit pas être un string[4] mais un array[1..4] of 0..5 (l'utilisation de chiffres plutôt que des char va te simplifier considérablement la vie et couleurVersNum ne serviras plus à rien !)

    Remarque :
    * Très vite on voit qu'on se retrouve avec des 4, des 5 des 6, et on s'y perd, si tu veux augmenter la difficulté ça va être un vrai casse-tête pour tout changer, le mieux est donc de mettre des constantes dans ton code.
    * Il est préférable de passer tes array par référence c'est à dire avec le mot clé var pour améliorer les performances
    * Randomize, doit être lancé une seule fois, juste après le BEGIN du programme.
    * Le t_ est plutôt embêtant à promener, le nom du type est suffisamment explicite !

    Voici donc à quoi pourrait ressembler le début de ton code en prenant en compte mes remarques :

    program mastermind;   
    
    const   
         NB_CHIFFRES = 4;   
         NB_COULEURS = 6;   
    
    type   
        chiffre = 1..NB_CHIFFRES;   
        couleur = 1..NB_COULEURS;   
        combinaison=array[chiffre] of couleur;   
        frequence=array[couleur] of integer;   
    
    function couleurAleatoire:couleur;   
    begin   
         result:=1+random(NB_COULEURS);  // entre 1 et NB_COULEURS inclus   
    end;   
    
    procedure initial(var c:combinaison; var f:frequence);   
    var ch:chiffre; co:couleur;   
    begin   
         for ch:=1 to NB_CHIFFRES do   
         begin   
             co:=couleurAleatoire;   
             c[ch]:=co;   
             inc(f[co]); // inc(x) <=> x:=x+1   
         end;   
    end;

    Il y a toute la suite du code encore à modifier, mais le mieux est que tu le fasses toi même (moi je sais le faire ^^) pour comprendre comment réutiliser les constantes et surtout te passer des char pour les couleurs, car avec des chiffres c'est plus simple !

    Pour ta question sur la matrice, tu peux faire quelque chose comme ça :

    const   
         NB_ESSAIS = 10;   
    
    type   
        essai = 1..NB_ESSAIS;   
    
        partie = record // enregistrement, on utilise le . pour accéder aux champs   
                 c : array[essai] of combinaison;   
                 n : essai;   
                 end;   
    
    procedure ajouterCombinaison(var p:partie; var c:combinaison);   
    begin   
         if p.n < NB_ESSAIS   
         then begin   
              inc(p.n);   
              p.c[p.n]:=c;   
              end;   
    end;   
    
    procedure afficherPartie(var p:partie)   
    var e:essai;   
    begin   
         writeln('Récapitulatifs des ',p.n,' essais');   
         for e:=1 to p.n do   
             afficherCombinaison(p.c[e]);   
    end;

    La confiance n'exclut pas le contrôle
    0
    1. dois je donc reprendre les mêmes étapes, donc les mêmes procedures et fonctions avec les modifications suggérées ?
      0
      1. Modérateur
        Bah oui, c'est bien ce que tu voulais ? Des améliorations ;-)
        0
      2. Bonsoir,

        merci d'avoir pris la peine de répondre et de m'aider

        j'aimerais poster le programme que tu ma proposé , bien sûr complété, mais j'arrive pas à e poster parce que c'est écrit
        "Veuillez écrire correctement s'il vous plaît (pas de SMS, orthographe, grammaire)"
        Comment as tu fais pour poster le programme ?
        0
      3. Modérateur
        C'est peut-être juste un bug temporaire sur le site...
        Sinon j'utilises les balises < code > le programme </ code > (mais sans les espaces bien sûr)
        0
    2. J'ai tenu compte des suggestions faites et voilà à quoi j'arrive :

      code
      program mastermind;

      const
      NB_CHIFFRES = 4;
      NB_COULEURS = 6;
      NB_ESSAIS = 10;
      type
      chiffre = 1..NB_CHIFFRES;
      couleur = 1..NB_COULEURS;
      essai = 1..NB_ESSAIS;
      combinaison=array[chiffre] of couleur;
      frequence=array[couleur] of integer;
      partie = record // enregistrement, on utilise le . pour accéder aux champs
      c : array[essai] of combinaison;
      n : essai;
      end;

      function couleurAleatoire:couleur;
      begin
      result:=1+random(NB_COULEURS); // entre 1 et NB_COULEURS inclus
      end;

      procedure initial(var c:combinaison; var f:frequence);
      var ch:chiffre; co:couleur;
      begin
      for ch:=1 to NB_CHIFFRES do
      begin
      co:=couleurAleatoire;
      c[ch]:=co;
      inc(f[co]); // inc(x) <=> x:=x+1
      end;
      end;

      procedure ajouterCombinaison(var p:partie; var c:combinaison);
      begin
      if p.n < NB_ESSAIS
      then begin
      inc(p.n);
      p.c[p.n]:=c;
      end;
      end;

      procedure afficherPartie(var p:partie)
      var e:essai;
      begin
      writeln('Récapitulatifs des ',p.n,' essais');
      for e:=1 to p.n do
      afficherCombinaison(p.c[e]);
      end;

      Procedure Essai (Var c : combinaison ; Var f : frequence);
      Var i, j ,nb : Integer;
      Begin
      For j := 1 To NB_COULEURS Do
      f[j] := 0;
      Write('Donner une combinaison ');
      ReadLn(c);
      For i := 1 To NB_CHIFFRES Do
      Begin
      nb := c[i];
      f[nb] := f[nb]+1;
      End;
      End;

      Procedure Resultat(c, d : combinaison; t, f : frequence);
      Var i, j, nb, x, y : Integer;
      Begin
      x := 0;
      For i := 1 To NB_CHIFFRES Do
      If d[i] = c[i]
      Then Begin
      x := x + 1;
      nb := C[i];
      f[nb] := f[nb]-1;
      f[nb] := t[nb]-1;
      End;
      y := 0;
      For j := 1 To NB_COULEURS Do
      If (t[j] > 0) AND (f[j] > 0) Then
      If f[j] >= t[j]
      Then y := y + t[j]
      Else y := y + f[j];
      WriteLn('Valeurs de x et y pour cet essai : x= ', x , ' et y = ', y);
      End;
      /code

      Il ne me reste que le programme principal à écrire mais je trouve que c'est dur d'ordonner tout ça, tu pourrais m'aider s'il te plaît ? ca serais très sympa vu que c'est la première fois que j'écris un programme pascal sans être guidé (vu que c'est un mini projet) et vu que je ne suis pas très doué en programmation. S'il ya d'autres remarques ou suggestions, elles sont le bienvenue !

      merci d'avance.
      0
      1. Modérateur
        Sur cette partie là, je ne vois qu'une seule grosse erreur, c'est le readln(c) alors que c est un tableau.

        Sinon, quand tu fais une boucle for i:=1 to NB_CHIFFRES par exemple, i est de type chiffre, évidemment ça marche aussi avec des integer, mais ça permet de mieux comprendre le code et d'économiser de la place en mémoire (peut-être pas en pascal, mais en théorie oui)

        De plus, il est intéressant d'utiliser inc(x), au lieu de x:=x+1, de même avec dec(x) et x:=x-1

        Sinon un gros problème mais c'est de ma faute ^^ le type essai que j'ai introduis hier porte le même nom qu'une de tes procédures, tu vas devoir renommer l'un des deux ;-)

        Je ne remets pas tout le début, c'est plus ou moins ce que j'avais mis hier :

        procedure lireCombinaison(var c:combinaison)
        var i:chiffre;
        begin
             writeln('Donner une combinaison (',NB_CHIFFRES,' chiffres entre 1 et ',NB_COULEURS,')');
        
             for i:=1 to NB_CHIFFRES do
             begin
                  write('Couleur ',i,' : ');
                  readln(c[i]);
             end;
        end;
        
        procedure essai (var c:combinaison; var f:frequence);
        var i:chiffre; j:couleur; //var i,j,nb:integer;
        begin
             for j:=1 to NB_COULEURS do
                 f[j]:=0;
        
             lireCombinaison(c);//ReadLn(c);
        
             for i := 1 to NB_CHIFFRES do
                 inc(f[c[i]]);
             (*begin
                  nb := c[i];
                  f[nb] := f[nb]+1;
             end;*)
        end;
        
        procedure resultat(var c,d:combinaison; var t,f:frequence);
        var i:chiffres; j,nb:couleur; x,y:integer;//var i, j, nb, x, y : Integer;
        begin
             x := 0;
             for i := 1 to NB_CHIFFRES do
                 if d[i]=c[i]
                 then begin
                      inc(x); //x := x + 1;
                      nb := c[i];
                      dec(f[nb]);//f[nb] := f[nb]-1;
                      dec(t[nb]);//f[nb] := t[nb]-1;
                      end;
        
             y := 0;
             for j := 1 to NB_COULEURS do
                 if (t[j]>0) and (f[j]>0)
                 then
                     if f[j]>=t[j]
                     then y := y + t[j]
                     else y := y + f[j];
        
             writeln('Valeurs de x et y pour cet essai : x= ', x , ' et y = ', y);
        end;

        Bon courage pour le programme principal, mais normalement c'est pas plus dur ^^
        0
      2. dans la procedure

        procedure afficherPartie(var p:partie) ;
        var e:essai;
        begin
        writeln('Récapitulatifs des ',p.n,' essais');
        for e:=1 to p.n do
        afficherCombinaison(p.c[e]);
        end;

        le compilateur montre qu'il ne trouve pas la procedure afficherCombinaison, peut-être tu as oublié de la mettre, mais en fait je n'ai pas compris le principe et le rôle que devrait avoir afficheCombinaison, tu peux me l'expliquer stp ?
        0
      3. Modérateur
        Oui en effet, je l'ai pas mise, je n'ai jamais dit que je mettait tout non plus ^^
        Tu as dit que tu voulais integrer une matrice qui affiche les differentes tentatives effectuées
        p:partie c'est la matrice, et chaque c:combinaison est une tentative, donc tu l'affiches comme tu veux, mais ce sera avec une boucle for pour afficher chaque couleur c[i]
        0
      4. Procedure afficherCombinaison (p.c:combinaison);
        Var e:NB_ESSAIS; n:NB_CHIFFRES;
        Begin
        For e:=1 to NB_ESSAIS do
        begin
        For n:=1 to NB_CHIFFRES do
        write (p.c[n])
        writeln;
        end;
        end;

        j'ai écris ceci mais on m'affiche plein d'erreur et je ne sais d'où elles viennet. Help please
        0
      5. Modérateur
        p.c n'est pas un nom valide pour un paramètre, c suffit, même si après tu utilises p.clors de l'appel de la fonction (remarque : le mot clé var est pas obligatoire mais il est conseillé pour les array)
        NB_ESSAIS, et NB_CHIFFRES sont des constantes, les types sont essai, et chiffre
        Mais puisque tu n'affiches qu'une seule combinaison tu n'as pas besoin de la boucle sur e

        procedure afficherCombinaison(var c:combinaison);
        var n:chiffre;
        begin
             for n:=1 to NB_CHIFFRES do
                 write(c[n],' '); // un exemple d'affichage parmi d'autres
             writeln;
        end;
        0
    3. j'ai pu ajouter des choses à mon programme principal, mais il y a un truc bizarre, c'est que quand on tape la première combinaison, p affiche une valeur bizarre qui ne correspond pas a la combinaion proposée, mais après quand je sasis une 2éme combinasion, p affiche cette fois la combinaison bizarre et la toute première que j'ai proposé, il ya donc un décalage, mais je ne sais pas ou et je ne sasi pas comment est générée cette combinaison qui apparait en premier.
      la 2ème chose, c'est que dans le programme principal, toute la partie après le until n'agit pas a l'execution comme si elle était absente, je ne sais pas pourquoi elle n'inytervien pas.

      peux-tu me dire ce qui ne va pas stp ?
      Je te mets le programme en entier au cas ou ...

      program mastermind;

      const
      NB_CHIFFRES = 4;
      NB_COULEURS = 6;
      NB_ESSAIS = 10;
      type
      chiffre = 1..NB_CHIFFRES;
      couleur = 1..NB_COULEURS;
      essai = 1..NB_ESSAIS;
      combinaison=array[chiffre] of couleur;
      frequence=array[couleur] of integer;
      partie = record // enregistrement, on utilise le . pour accéder aux champs
      c : array[essai] of combinaison;
      n : essai;
      end;

      function couleurAleatoire:couleur;
      var result:integer;
      begin
      result:=1+random(NB_COULEURS); // entre 1 et NB_COULEURS inclus
      couleurAleatoire:=result;
      end;

      procedure initial(var c:combinaison; var f:frequence);
      var ch:chiffre; co:couleur;
      begin
      for ch:=1 to NB_CHIFFRES do
      begin
      co:=couleurAleatoire;
      c[ch]:=co;
      inc(f[co]); // inc(x) <=> x:=x+1
      end;
      end;

      procedure ajouterCombinaison(var p:partie; var c:combinaison);
      begin
      if p.n < NB_ESSAIS
      then begin
      inc(p.n);
      p.c[p.n]:=c;
      end;
      end;

      procedure afficherCombinaison(var c:combinaison);
      var n:chiffre;
      begin
      for n:=1 to NB_CHIFFRES do
      write(c[n],' '); // un exemple d'affichage parmi d'autres
      writeln;
      end;

      procedure afficherPartie(var p:partie) ;
      var e:essai;
      begin
      writeln('Recapitulatifs des ',p.n,' essais');
      for e:=1 to p.n do
      afficherCombinaison(p.c[e]);
      end;

      procedure lireCombinaison(var c:combinaison);
      var i:chiffre;
      begin
      writeln('Donner une combinaison (',NB_CHIFFRES,' chiffres entre 1 et ',NB_COULEURS,')');

      for i:=1 to NB_CHIFFRES do
      begin
      write('Couleur ',i,' : ');
      readln(c[i]);
      end;
      end;

      procedure essais (var c:combinaison; var f:frequence);
      var i:chiffre; j:couleur; //var i,j,nb:integer;
      begin
      for j:=1 to NB_COULEURS do
      f[j]:=0;

      lireCombinaison(c);//ReadLn(c);

      for i := 1 to NB_CHIFFRES do
      inc(f[c[i]]);
      (*begin
      nb := c[i];
      f[nb] := f[nb]+1;
      end;*)
      end;

      procedure resultat(var c,d:combinaison; var t,f:frequence);
      var i:chiffre; j,nb:couleur; x,y:integer;//var i, j, nb, x, y : Integer;
      begin
      x := 0;
      for i := 1 to NB_CHIFFRES do
      if d[i]=c[i]
      then begin
      inc(x); //x := x + 1;
      nb := c[i];
      dec(f[nb]);//f[nb] := f[nb]-1;
      dec(t[nb]);//f[nb] := t[nb]-1;
      end;

      y := 0;
      for j := 1 to NB_COULEURS do
      if (t[j]>0) and (f[j]>0)
      then
      if f[j]>=t[j]
      then y := y + t[j]
      else y := y + f[j];

      writeln('Nombres de couleurs bien placees pour cet essai: x= ', x);
      writeln('Nombres de couleurs mal placees pour cet essai est y = ', y);
      end;

      Var c,d:combinaison;
      f,t: frequence;
      p:partie;
      e,i:integer;
      MDP:string;
      OK:boolean;
      Begin
      Writeln ('Bonjour, vous allez jouer au jeu Mastermind Version Pascal');
      Writeln ('Si vous voulez continuer sasissez le MDP : azerty');
      Readln (MDP);

      if MDP='azerty' then
      begin
      randomize;
      initial(c,t);
      e:=0;
      OK:=false;
      Repeat
      inc(e);
      ajouterCombinaison(p,c);
      essais(c,f);
      resultat(c,d,t,f);
      afficherPartie(p) ;
      For i:=1 to NB_CHIFFRES do
      begin
      if c[i]=d[i]
      then OK:=true
      end;
      until (e=NB_ESSAIS) or (OK=true);

      if OK=false
      then write ('Game Over, la combinaison secrète est:');
      for i:=1 to NB_CHIFFRES do
      write(c[i]) ;
      writeln;
      writeln ('Occurance des couleurs de la combinaison secrète :');
      for i:=1 to NB_COULEURS do
      write (i, (' ')); writeln; write (f[i], ' ');
      writeln;
      writeln;
      writeln ('Occurence des couleurs proposées lors de cette partie :');
      for i:=1 to NB_COULEURS do
      write (i, (' ')); writeln; write (t[i], ' ');
      writeln ;
      else writeln ('Veuillez donc fermer le programme, au revoir');
      end

      merci d'avance.
      0
      1. Modérateur
        Dans une fonction, lorsque l'on écrit result:= c'est pareil que quand tu dis nomFonction:=
        Mais result est plus pratique car ça te permet de changer le nom de la fonction si tu veux.

        Voici trois codes, le premier (le tien) est faux car tu redéfinis result dans les variables, et qui plus d'un type différent du résultat ! Par contre les deux derniers codes sont corrects et équivalents :

        function couleurAleatoire:couleur;
        var result:integer; // Error : Duplicate identifier RESULT
        begin
             result:=1+random(NB_COULEURS);
             couleurAleatoire:=result;
        end;
        
        function couleurAleatoire:couleur;
        begin
             result:=1+random(NB_COULEURS);
        end;
        
        function couleurAleatoire:couleur;
        var result:integer;
        begin
             couleurAleatoire:=1+random(NB_COULEURS);
        end;


        Sinon, tout à la fin du programme (qui n'a pas de . après le end), tu as un else sans if !!!
        En fait tu as surtout oublié plein de begin/end, pour le then, et les boucles for !
        Et pour l'affichage des f[i] on s'y perd car tu as mis i:integer pour tout, alors qu'il y a des types chiffre, et des types couleur, là tu utilises indifféremment les deux, et du coup je penses que ton tableau déborde, en cherchant des f[NB_COULEURS] là où on devrait avoir f[NB_CHIFFRES]

        Remarque :
        OK est un booléen, il vaut donc true, ou false, c'est inutile de faire des tests =true, ou =false
        Plutôt que de faire un long if then pour ton MDP, utilises plutôt halt pour arrêter le programme, ça t'évitera d'oublier (encore) un end.

        Je ne sais pas ce que tu utilises comme compilateur, mais toute ces erreurs auraient du t'être signalées avant que tu ne puisses lancer le programme !!!

        Maintenant que chez moi il se lance, vient le problème proprement dit qui doit entre venir de l'ordre dans lequel tu effectues ta boucle repeat until, par exemple en ajoutant la combinaison à la partie avant même que le joueur n'est joué !!!
        En plus tu as une erreur de logique avec ton OK, il suffit d'un seul bon chiffre et c'est gagné, or ce n'est pas ce que l'on devrait avoir !

        Je te laisse faire la suite car je ne comprends pas ce que sont censés faire resultat et autre, j'ai rajouté une ligne de test pour afficher la combinaison à trouver, et même en connaissant la réponse on ne peut pas gagner !!!

        Var
        c,d:combinaison;
        f,t: frequence;
        p:partie;
        e:essai;
        i:chiffre;
        j:couleur;
        MDP:string;
        OK:boolean;
        Begin
             Writeln ('Bonjour, vous allez jouer au jeu Mastermind Version Pascal');
             Writeln ('Si vous voulez continuer saisissez le MDP : azerty');
             Readln (MDP);
        
             if MDP<>'azerty'
             then halt;
        
             randomize;
             initial(c,t);
             writeln('Combinaison a deviner : ');
             afficherCombinaison(c);
        
             for e:=1 to NB_ESSAIS do
             begin
                   essais(c,f);
                   resultat(c,d,t,f);
        
                   OK:=true;
                   For i:=1 to NB_CHIFFRES do
                   begin
                        if c[i]<>d[i]
                        then OK:=false;
                   end;
        
                   if OK
                   then begin
                        writeln('Veuillez donc fermer le programme, au revoir');
                        readln;
                        halt;
                   end;
        
                   ajouterCombinaison(p,c);
                   afficherPartie(p);
             end;
        
             write ('Game Over, la combinaison secrète est:');
             for i:=1 to NB_CHIFFRES do
             write(c[i]);
             writeln;
        
             writeln ('Occurance des couleurs de la combinaison secrète :');
             for j:=1 to NB_COULEURS do
             begin
                  write(j,' ');
                  writeln;
                  write(f[j],' ');
             end;
             writeln; writeln;
        
             writeln ('Occurence des couleurs proposées lors de cette partie :');
             for j:=1 to NB_COULEURS do
             begin
                  write(j, ' ');
                  writeln;
                  write(t[j], ' ');
             end;
             writeln;
             readln;
        end.

        Enfin, mettre un "mot de passe" est absurde, il suffit d'ouvrir l'exécutable avec un bloc-note pour voir apparaître toutes les chaines de caractères, et en particulier le test MDP='azerty'...
        0
      2. en fait resultat sert a guider le joueur, en faissant la comparaison entre la combinaison secrète et celle proposé, puis il indique combien ya t-il de lettres bien placées (x) et combine mal placées (y).
        0
      3. j'ai remarqué qu'en effet même si on connait la combinaion secrete , on reussit pas a gagner, en fait il faut saisir 0000 pour gagner, pour toutes les parties , donc la combinaison secrete est généré mais n'ets pas prise en comte a la suite.
        0
      4. c'est bon j'ai réglé le problème, le programme est enfin achevé !
        Merci infiniment pour ton aide !!!
        0
      5. Modérateur
        Et c'était quoi ? Juste pour info ;-)
        0