Aide pour un programme pascal

Fermé
Aldores - 21 mai 2011 à 23:08
 Aldores - 24 mai 2011 à 22:20
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.
A voir également:

4 réponses

KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 019
Modifié par KX le 22/05/2011 à 01:36
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
dois je donc reprendre les mêmes étapes, donc les mêmes procedures et fonctions avec les modifications suggérées ?
0
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 019
23 mai 2011 à 21:28
Bah oui, c'est bien ce que tu voulais ? Des améliorations ;-)
0
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
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 019
23 mai 2011 à 21:55
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
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
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 019
23 mai 2011 à 23:01
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
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
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 019
23 mai 2011 à 23:29
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
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
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 019
23 mai 2011 à 23:51
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
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
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 019
24 mai 2011 à 17:12
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
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
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
c'est bon j'ai réglé le problème, le programme est enfin achevé !
Merci infiniment pour ton aide !!!
0
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 019
24 mai 2011 à 21:41
Et c'était quoi ? Juste pour info ;-)
0