[C] Le traditionnel jeu du pendu

Le traditionnel jeu du pendu [C] - C - Programmation

Marsh Posté le 08-03-2006 à 02:55:54    

Bonjour!
voila je programme un petit jeu de pendu, histoire d'apprendre un peu a manier les chaines de caracteres
c'est je pense un exercice assez banal, et je me demandai si des gens ici avaient qqs conseils a me donner pour l'amelioration du programme et de la syntaxe, parce que je l'ai fait avec mon peu de connaissances (jai meme pas encore vu les pointeurs ni les chaines de caracteres en cours, on en est encore a programmer des factorielles  :cry: )
 
j'envoie donc le code source, commenté comme il se doit :)
 
 

Code :
  1. #include<stdio.h>
  2. /*  
  3.    Compare 2 chaines et renvoie 1 si elles sont identiques, sinon 0
  4.    Prend 2 chaines de caractères en entrée
  5.    Compare les chaines, lettres par lettres
  6. */
  7. int ComparerChaine (char ch1[], char ch2[])
  8. {int i=0, test=1;
  9. while (ch1[i] && ch2[i] && test)
  10. if (ch1[i++] != ch2[i++]) test=0;
  11. return test;}
  12. /*  
  13.    Renvoie 1 si la lettre est contenue dans le mot, sinon renvoie 0
  14.    Prend en entrée une chaine de caractères et une lettre
  15.    Compare le mot lettre a lettre avec la lettre
  16. */
  17. int TestLettre (char mot[], char lettre[])
  18. {int i=0, test=0;
  19. while (mot[i])
  20. if (mot[i++] == lettre[0]) test=1;
  21. return test;}
  22. /*  
  23.    Affichage du mot incomplet, renvoie 1 si le mot est complet, sinon 0
  24.    On lui envoie le mot a trouver, et la chaine contenant les caracteres
  25.    deja trouvés.
  26.    Compare le mot lettre a lettre avec la chaine contenant les lettres
  27.    trouvées, affiche le caractere si il est dans cette chaine, affiche
  28.    un underscore et met la variable WIN a 0 sinon
  29. */
  30. int Affichage (char mot[], char trouves[])
  31. {int i=-1, win=1;
  32. while (mot[++i])
  33. {if (TestLettre(trouves,&mot[i])==1) printf("%c ",mot[i]);
  34. else {printf("_ " );win=0;} }
  35. return win;
  36. }
  37. /*  
  38.    Boucle principale :
  39.    Demande un mot qu'il faudra ensuite deviner
  40.    Tant que la chaine entrée != quit et que Affichage ne
  41.    renvoie pas 1 :
  42.    Demande un caractere ou la chaine 'quit'
  43.    /!\ pas de protection pour limiter les autres
  44.    chaines possible, bugs a prevoir /!\
  45.    Si la lettre appartient au mot, l'ajouter dans la chaine
  46.    des lettres trouvées
  47.    Incrementer le nombre d'essais
  48.    Afficher le score quand la boucle principale est terminée
  49. */
  50. main()
  51. {
  52. char mot[30], lettre[2]=" ", trouves[30]=" ";
  53. int essais=0, n=0;
  54. printf("\n\nEntrez un mot a retrouver\n\n" );scanf("%s",mot);printf("\n\n" );
  55. while ((ComparerChaine(lettre, "quit" ) != 1) && (Affichage(mot, trouves) != 1))
  56. {
  57. printf("\n\n\nEntrez une lettre ou 'quit' pour quitter\n" );
  58. scanf("%s",lettre);printf("\n\n" );
  59. if (TestLettre(mot,lettre)) trouves[n++]=lettre[0];
  60. essais++;
  61. }
  62. printf("\n\n%d essais\n",essais);
  63. return 0;
  64. }


 
 
Merci d'avance de vos reponses :)


---------------
Amon Amarth, Dark Tranquillity, Opeth, Dimmu Borgir, In Flames, Children of Bodom, Kreator, Metallica... pas d'la musique de paidai tout sa :o
Reply

Marsh Posté le 08-03-2006 à 02:55:54   

Reply

Marsh Posté le 08-03-2006 à 09:47:58    

Salut !
 
ça me paraît pas mal du tout. J'ai juste une ou deux remarques à faire :

  • dans la fonction TestLettre, ton deuxième argument devrait être un caractère (je trouverais ça plus lisible, mais ça marche aussi bien comme tu as fait)
  • toujours dans la fonction TestLettre, tu pourrais t'arrêter de parcourir la chaine dès que tu sais que ton test est faux. Par exemple:

    Code :
    1. int TestLettre (char mot[], char lettre)
    2. {
    3.   int i=0;
    4.   while (mot[i])
    5.     if (mot[i++] == lettre) return 1;
    6.   return 0;
    7. }

  • le prototype de ta fonction main doit être "int main()" ou "int main(int, char**)" (plutôt la première solution dans ton cas)
  • dans la fonction main : pourquoi tes chaines (en particulier 'trouves') sont elles initialisées avec un espace ?
  • ta chaîne 'lettre' n'est pas assez grande pour contenir le mot 'quit' -> segfault
  • comme ta chaîne 'trouves' est envoyée en premier argument de TestLettre, il faut absolument que tu t'assures qu'elle est bien terminée par un 0. Comme dans tu l'as alloué statiquement, je pense que dans la plupart des cas ton tableau est initialisé avec des 0 et ça marche, mais je ne suis pas sûr que ce soit spécifié dans la norme (quelqu'un peut-il confirmer / infirmer ?) Du coup, je verrais plutôt une fonction main dans le genre:

    Code :
    1. int main()
    2. {
    3.   char mot[30], lettre[5]="", trouves[30]="";
    4.   int essais=0, n=0;
    5.   printf("\n\nEntrez un mot a retrouver\n\n" );scanf("%s",mot);printf("\n\n" );
    6.   while( 1 )
    7.     {
    8.       printf("\n\n\nEntrez une lettre ou 'quit' pour quitter\n" );
    9.       scanf("%s",lettre);printf("\n\n" );
    10.       if( ComparerChaine(lettre, "quit" ) == 1 ) /* l'utilisateur veut quitter */
    11.         break; /* on sort de la boucle while */
    12.       if (TestLettre(mot,lettre[0]))
    13.         {
    14.           trouves[n++] = lettre[0];
    15.           trouves[n] = 0; /* on termine la chaine par un 0 */
    16.         }
    17.       essais++;
    18.       if( Affichage(mot, trouves) == 1 ) /* gagné !!! */
    19.         break;
    20.     }
    21.   printf("\n\n%d essais\n",essais);
    22.   return 0;
    23. }

  • de manière générale, tes entrées de données avec scanf sont assez fragiles, et tu ne peux pas assurer que les données entrées par l'utilisateur ne vont pas dépasser. Tu devrais gérer un peu plus proprement ce type de problèmes.


Message édité par franceso le 08-03-2006 à 09:48:57
Reply

Marsh Posté le 08-03-2006 à 12:09:07    

pour la 1ere remarque, j'en deduis donc que la commande return met fin a une fonction pour retourner a celle qui l'a appelée?
dans ce cas oui je vais quivre ton conseil :)
 
sinon j'ai pas encore vraiment compris comment nommer les fonctions... en cour, on ecrit main(), dans le bouquin que j'utilise on apelle pas mal de fonctions par int fonction() comme toi, mais qu'est-ce que sa indique?
 
si j'ai initialisé mes chaines avec un espace, c'est parce que j'ai cru comprendre qu'il valait mieu le faire plutot que de les laisser vide, en particulier si par exemple pour "trouves" ou "lettre "cette variable est utilisée en argument avant d'avoir été definie
 
while ((ComparerChaine(lettre, "quit" ) != 1) && (Affichage(mot, trouves) != 1)) dans ma fonction
 
 
sinon pour el segfault, le fait est que je n'en ai pas, j'ai aussi trouvé sa bizarre que si je definisse une chaine de caractere a 1 caractere (une lettre, donc...) je puisse entrer un mot plus long sans erreur...
je peut faire un scanf("%c",lettre) mais alors je ne pourrai plus utiliser le mot 'quit' (que je devrai eventuellement replacer par un chiffre)
 
 
pour ta remarque des scanf, comme dit j'ai aussi remarqué qqs soucis dans l'entrée des variables, mais pour l'instant j'ai rien de mieu, donc je fais avec ce que j'ai lol :)
 
quoi qu'il en soit, merci bcp pour avoi pris la peine de lire mon code et de le commenter :)
 
j'ai ma petite idée d'algorythme pour afficher le pendu en ASCII, mais je m'occuperai de sa quand j'aurai le temps :) (c a dire pas cet apres midi lol)
 
@bientot :)


---------------
Amon Amarth, Dark Tranquillity, Opeth, Dimmu Borgir, In Flames, Children of Bodom, Kreator, Metallica... pas d'la musique de paidai tout sa :o
Reply

Marsh Posté le 08-03-2006 à 13:28:46    

Une fonction doit porter un nom qui indique ce qu'elle fait pour plus de clareté lors de la relecture du code, Exemple mettre_a_blanc, additionner,...
 
Le main est une fonction particulière qui est appelée par le système pour lancer le programme, elle doit être présente pour que le programme tourne, sinon ce n'est pas un programme à part entière.
Tu as bien deduis, le return met fin à la fonction et l'exécution reprend à l'instruction suivant l'appel à la fonction.
 
J'espère ne pas avoir dit de bétises...

Reply

Marsh Posté le 08-03-2006 à 13:33:30    

reiboul a écrit :

sinon j'ai pas encore vraiment compris comment nommer les fonctions... en cour, on ecrit main(), dans le bouquin que j'utilise on apelle pas mal de fonctions par int fonction() comme toi, mais qu'est-ce que sa indique?


A part main() dont le nom est imposé (c'est par là que commence l'exécution), les autres fonctions peuvent avoir n'importe quel nom. Il est cependant d'usage de donner un nom d'action ou un verbe.
 
Détails ici :  
 
http://mapage.noos.fr/emdel/codage.htm
 
A lire en entier. Pose des questions si tu ne comprends pas.


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 08-03-2006 à 13:41:03    

Reply

Marsh Posté le 08-03-2006 à 14:26:45    

Bonjour, quelques remarques sur le code :
 

Code :
  1. #include<stdio.h>
  2. /*  
  3.    Compare 2 chaines et renvoie 1 si elles sont identiques, sinon 0
  4.    Prend 2 chaines de caractères en entrée
  5.    Compare les chaines, lettres par lettres
  6. */
  7. int ComparerChaine (char ch1[], char ch2[])
  8. {int i=0, test=1;
  9. while (ch1[i] && ch2[i] && test)
  10. if (ch1[i++] != ch2[i++]) test=0;
  11. return test;}


tu a écrit ch1[i++] != ch2[i++], ce qui revient à
ch1[0] != ch[1] puis  
ch[2] != ch[3],...  
 
ce qui ne convient pas vraiment, peut etre que tu voulais écrire ch1[i] != ch2[i++] plutot ?
(encore faut-il etre sur que le compilo évalue l'expression de gauche avant)
 
 

Code :
  1. /*  
  2.    Renvoie 1 si la lettre est contenue dans le mot, sinon renvoie 0
  3.    Prend en entrée une chaine de caractères et une lettre
  4.    Compare le mot lettre a lettre avec la lettre
  5. */
  6. int TestLettre (char mot[], char lettre[])
  7. {int i=0, test=0;
  8. while (mot[i])
  9.     if (mot[i++] == lettre[0]) test=1;
  10. return test;}


 
est-ce le while mot[i] se termine  ??
le minimum (pour moi) serait un while ( mot[i] != EOF ), mais les chaines de caracteres et moi ca fait 2, surtout en c.
 
+1 fransesco pour les scanf et return
 
 
A+

Reply

Marsh Posté le 08-03-2006 à 15:03:55    

Citation :

est-ce le while mot[i] se termine  ??


 
une chaine est terminée par un caractere nul (0 ou '\0')
 

Citation :

le minimum (pour moi) serait un while ( mot[i] != EOF )


 
ca n'a rien à faire ici EOF ?

Reply

Marsh Posté le 08-03-2006 à 15:31:13    

Citation :

ca n'a rien à faire ici EOF ?


autant pour moi c'est '\0'

Reply

Marsh Posté le 08-03-2006 à 15:40:58    

reiboul a écrit :

si j'ai initialisé mes chaines avec un espace, c'est parce que j'ai cru comprendre qu'il valait mieu le faire plutot que de les laisser vide, en particulier si par exemple pour "trouves" ou "lettre "cette variable est utilisée en argument avant d'avoir été definie

Attention, il ne faut pas confondre "chaine vide" avec "chaine non initialisée"
Tu peux tout à fait initialiser une chaine de caractères à "" (ce qui revient à dire que tu mets un zéro dans la première case du tableau) ; ça ne devrait pas poser de problèmes.
 

reiboul a écrit :

sinon pour el segfault, le fait est que je n'en ai pas, j'ai aussi trouvé sa bizarre que si je definisse une chaine de caractere a 1 caractere (une lettre, donc...) je puisse entrer un mot plus long sans erreur...

Le problème avec les segfaults, c'est qu'elles ne se déclenchent pas tout le temps. En fait, ton système ne génère une erreur de segmentation que lorsque tu essaies d'accéder à un morceau de mémoire qui ne t'appartient pas. En gros, il se peut tout à fait que tu dépasses les bornes de tes tableaux et corrompes des morceaux de mémoire ; tant que tu restes "chez toi", tu n'as pas de segfault et tu ne te rends pas compte que tu es en train de corrompre des données / morceaux de codes de ton programme.

Reply

Marsh Posté le 08-03-2006 à 15:40:58   

Reply

Marsh Posté le 08-03-2006 à 16:01:22    

franceso a écrit :


Tu peux tout à fait initialiser une chaine de caractères à "" (ce qui revient à dire que tu mets un zéro dans la première case du tableau)


 
oui mais en réalité c'est tout les éléments du tableau qui seront initialisés à 0, dans le cas de l'initialisation d'un tableau de char, "" est un sucre syntaxique (comme "hello" )

Code :
  1. char s[20] = "";


est équivalent à

Code :
  1. char s[20] = {};


et

Code :
  1. char s[] = "hello";


est équivalent à

Code :
  1. char s[] = {'h', 'e', 'l', 'l', 'o', '\0'};


 
c'est pratique à savoir car ca permet d'ajouter des caracteres en fin de chaine tout en etant sur qu'elle est terminée par un caractere nul

Reply

Marsh Posté le 08-03-2006 à 16:09:13    

skelter a écrit :

o

Code :
  1. char s[20] = {};




Tu veux bien sûr dire  

Code :
  1. char s[20] = {0};



---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 08-03-2006 à 16:17:13    

skelter a écrit :

oui mais en réalité c'est tout les éléments du tableau qui seront initialisés à 0
...
c'est pratique à savoir car ca permet d'ajouter des caracteres en fin de chaine tout en etant sur qu'elle est terminée par un caractere nul


C'est justement la question que je me posais dans le premier post : il me semblait bien que dans le cas d'une allocation statique + initialisation tous les caractères étaient initialisés à 0, mais je n'étais pas sûr que ce soit un comportement standard défini par la norme.
 
Merci pour ces précisions :jap:

Reply

Marsh Posté le 08-03-2006 à 16:27:48    

Emmanuel Delahaye a écrit :

Tu veux bien sûr dire  

Code :
  1. char s[20] = {0};



 
oui, en fait j'ai jamais utilisée cette syntaxe mais je viens de voir que ce n'est pas ansi.
 
par contre ca ne serait pas valide en c99 ?
 

Reply

Marsh Posté le 08-03-2006 à 17:05:28    

skelter a écrit :

oui, en fait j'ai jamais utilisée cette syntaxe mais je viens de voir que ce n'est pas ansi.
 
par contre ca ne serait pas valide en c99 ?


Non, pas à ma connaissance.
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 08-03-2006 à 17:05:59    

LePhasme a écrit :

Une fonction doit porter un nom qui indique ce qu'elle fait pour plus de clareté lors de la relecture du code, Exemple mettre_a_blanc, additionner,...
 
Le main est une fonction particulière qui est appelée par le système pour lancer le programme, elle doit être présente pour que le programme tourne, sinon ce n'est pas un programme à part entière.


 
oui sa, je connais, mais j'ai pas été assez clair dans ma question, en fait je parlai des 'int' par exemple que l'on place avant les noms des fonctions, par exemple 'int main()' sa correspond a quoi par rapport a 'main()'?
 
 

zyb a écrit :

Bonjour, quelques remarques sur le code :
 

Code :
  1. ...


 
tu a écrit ch1[i++] != ch2[i++], ce qui revient à
ch1[0] != ch[1] puis  
ch[2] != ch[3],...  
 
ce qui ne convient pas vraiment, peut etre que tu voulais écrire ch1[i] != ch2[i++] plutot ?
(encore faut-il etre sur que le compilo évalue l'expression de gauche avant)
 
 
est-ce le while mot[i] se termine  ??
le minimum (pour moi) serait un while ( mot[i] != EOF ), mais les chaines de caracteres et moi ca fait 2, surtout en c.
A+


 
probablement correct pour le ch1[i] != ch2[i++], je vois ce que tu veut dire et je vais rectifier sa :)
 
sinon, il me semble que le while mot[i] corresponde a un while (mot[i] != '\0') tout comme par exemple  
if test(a) printf("true" );  
equivaut a  
if (test(a)==1) printf("true" )
 
confirmation? :)
 
bon je v reprendre un peu mon code
 
par hasard y'a une fonction qui permet de vider le terminal? (comme taper 'clear' dans un terminal, quoi...)


---------------
Amon Amarth, Dark Tranquillity, Opeth, Dimmu Borgir, In Flames, Children of Bodom, Kreator, Metallica... pas d'la musique de paidai tout sa :o
Reply

Marsh Posté le 08-03-2006 à 17:07:46    

franceso a écrit :

C'est justement la question que je me posais dans le premier post : il me semblait bien que dans le cas d'une allocation statique + initialisation tous les caractères étaient initialisés à 0, mais je n'étais pas sûr que ce soit un comportement standard défini par la norme.


http://mapage.noos.fr/emdel/notes.htm#tabchar


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 08-03-2006 à 17:12:01    

zyb a écrit :


tu a écrit ch1[i++] != ch2[i++], ce qui revient à
ch1[0] != ch[1] puis  
ch[2] != ch[3],...  
 
ce qui ne convient pas vraiment, peut etre que tu voulais écrire ch1[i] != ch2[i++] plutot ?
(encore faut-il etre sur que le compilo évalue l'expression de gauche avant)


 
 
apres essai, en effet, le programme ne verifie qu'un caractere sur 2 :)
 
quand je tape qeic sa me permet de quitter le programme :) (a cause du Q et du I qui sont comparées a 'quit' :) )


---------------
Amon Amarth, Dark Tranquillity, Opeth, Dimmu Borgir, In Flames, Children of Bodom, Kreator, Metallica... pas d'la musique de paidai tout sa :o
Reply

Marsh Posté le 08-03-2006 à 17:13:00    

reiboul a écrit :

oui sa, je connais, mais j'ai pas été assez clair dans ma question, en fait je parlai des 'int' par exemple que l'on place avant les noms des fonctions, par exemple 'int main()' sa correspond a quoi par rapport a 'main()'?


  • En C90, le type retourné implicite est int. Donc c'est pareil.
  • en C99, le type retourné doit être explicite. main() ne compile pas. Il faut int main()


http://mapage.noos.fr/emdel/notes.htm#typemain
 

Citation :

par hasard y'a une fonction qui permet de vider le terminal? (comme taper 'clear' dans un terminal, quoi...)


Rien de standard.  
 
<unixoide>
essaye system ("clear" );
</unixoide>

Message cité 1 fois
Message édité par Emmanuel Delahaye le 08-03-2006 à 17:13:37

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 08-03-2006 à 17:25:11    

Emmanuel Delahaye a écrit :

  • En C90, le type retourné implicite est int. Donc c'est pareil.
  • en C99, le type retourné doit être explicite. main() ne compile pas. Il faut int main()



 
j'utilise GCC et il compile avec main() (et uassi avec int main(), ya pas de raisons :) )
 
mais donc, le int devant une fonction indique que celle si renvoie un entier?
et char fonction() dois renvoyer un caractere, etc?


---------------
Amon Amarth, Dark Tranquillity, Opeth, Dimmu Borgir, In Flames, Children of Bodom, Kreator, Metallica... pas d'la musique de paidai tout sa :o
Reply

Marsh Posté le 08-03-2006 à 17:33:48    

reiboul a écrit :

j'utilise GCC et il compile avec main()


 
en ansi pas de probleme, gcc ne gueule pas par défaut mais suivant ce que dit emmanuel essay avec l'option -std=c99

Reply

Marsh Posté le 08-03-2006 à 19:02:57    

je rajoute la p'tite fonction qui dessine le pendu en fonction des erreurs, et qui renvoie 0 quand on perd
 

Code :
  1. int DessinerPendu(int erreurs)
  2. {
  3. printf("\n\n\n" );
  4. if (erreurs <= 3) printf("\n" );
  5. else printf(" ________\n" );
  6. if (erreurs >= 5) printf(" |/     |\n" );
  7. else if (erreurs >= 3) printf(" |/\n" );
  8.  else if (erreurs >= 2) printf(" |\n" );
  9.   else printf("\n" );
  10. if (erreurs >= 6) printf(" |      O\n" );
  11. else if (erreurs >= 2) printf(" |\n" );
  12.  else printf("\n" );
  13. if (erreurs >= 7) printf(" |     /|\n" );
  14. else if (erreurs >= 2) printf(" |\n" );
  15.  else printf("\n" );
  16. if (erreurs >= 8) printf(" |     //\n" );
  17. else if (erreurs >= 2) printf(" |\n" );
  18.  else printf("\n" );
  19. if (erreurs == 1) printf("___\n" );
  20. else if (erreurs >= 2) printf("_|_\n" );
  21.  else printf("\n" );
  22. if (erreurs >= 8) return 0;
  23. else return 1;
  24. }


 
 
 
Je cherche maintenant a entrer une base de mots a choisir au hasard pour deviner
j'ai pensé faire une sorte de tableau rempli de mots, et de stocker une case aléatoire du tableau dans une chaine de caractere a retourner
 
le probleme c'est que je ne sais pas du tout comment faire sa, si qqn a des pistes, je suis preneur :)
 
sa serait donc une fonction qui ne prend rien en entrée et qui renvoie une chaine de caracteres
 
je compte l'utiliser comme &mot[0]=ChoisirMot() par exemple
 
qqn a de sidées, par hasard?


---------------
Amon Amarth, Dark Tranquillity, Opeth, Dimmu Borgir, In Flames, Children of Bodom, Kreator, Metallica... pas d'la musique de paidai tout sa :o
Reply

Marsh Posté le 08-03-2006 à 19:22:21    

printf("\n\n\n" ); -> utilises plutot puts ou fputs
printf("\n" ); -> pareil, fputc ou putchar
 

Citation :

et qui renvoie 0 quand on perd


ce n'est pas a cette fonction de faire ce test, il doit etre fait en amont et cette fonction doit etre appelée conditionnellement
 
 

Citation :

qqn a de sidées, par hasard?


 
regardes la doc sur les fonctions srand et rand pour faire du pseudo aleatoire

Reply

Marsh Posté le 08-03-2006 à 19:27:49    

la difficulté est surtout de stocker les mots et de les rappeler en fonction du nombre generé aléatoirement


---------------
Amon Amarth, Dark Tranquillity, Opeth, Dimmu Borgir, In Flames, Children of Bodom, Kreator, Metallica... pas d'la musique de paidai tout sa :o
Reply

Marsh Posté le 08-03-2006 à 19:29:03    

et en fait le pendu ne me dit pas vraiment quand je gagne/perd, il me dit juste si le pendu est complet ou non
a partir de la, si le pendu est complet, j'en deduis que le joueur a perdu


---------------
Amon Amarth, Dark Tranquillity, Opeth, Dimmu Borgir, In Flames, Children of Bodom, Kreator, Metallica... pas d'la musique de paidai tout sa :o
Reply

Marsh Posté le 09-03-2006 à 09:06:19    

reiboul a écrit :

la difficulté est surtout de stocker les mots et de les rappeler en fonction du nombre generé aléatoirement


Tu peux stocker les mots dans un fichier texte (avec par exemple un mot par ligne), et aller chercher la ligne qu'il te faut à partir du nombre aléatoire généré

Reply

Marsh Posté le 09-03-2006 à 09:12:34    

franceso a écrit :

Tu peux stocker les mots dans un fichier texte (avec par exemple un mot par ligne), et aller chercher la ligne qu'il te faut à partir du nombre aléatoire généré


+1 cf le lien donné ici:


exercice corrigé de pendu en C


---------------
D3
Reply

Marsh Posté le 09-03-2006 à 15:17:50    

je vais essayer sa mais pour l'instant, j'ai reussi a definir une liste de mots (liste de liste de caracteres) et a en selectionner une ligne (mot) selon un nombre defini aleatoirement
 
j'ai en plus un peit algorythme qui affiche le pendu hehe :)
 
je vous envoie l'algo complet du pendu, qui cherche un mot aleatoirement, qui affiche le nom incomplet et le pendu et qui fonctionne (du moins chez moi)
 
 

Code :
  1. #include<stdio.h>
  2. // time.h contient les instructions necessaires pour definir un nombre aleatoire
  3. #include<time.h>
  4. // nombre de mots de la liste
  5. #define NOMBRE_DE_MOT 16
  6. // le mot a trouver est une variable globale
  7. char mot[30]="\0";
  8. //copie lettre a lettre une chaine de caracteres dans une autre, sert a stocker le mot aleatoire dans la variable globale 'mot'
  9. /* Copier chaine de caractere */
  10. void CopierMot(char *MotAleatoire, char *mot)
  11. {
  12. int i=0;
  13. while (MotAleatoire[i] != '\0') mot[i] = MotAleatoire[i++];
  14. mot[i] = '\0';
  15. }
  16. //la liste de mot, et le choix aleatoire du mot
  17. /* Liste de mots */
  18. void ChoisirMot()
  19. {
  20. char MotAleatoire[NOMBRE_DE_MOT][30]={"bonjour","aleatoire","anticonstitutionel","farfadet","reelection","entraver","tiraillement","connaisseuse","salopette","tisonnier","attester","marine","politique","decoder","international","technique"};
  21. int aleatoire;
  22. srand(time(NULL));
  23. aleatoire = (rand() %(NOMBRE_DE_MOT));
  24. CopierMot(MotAleatoire[aleatoire], mot);
  25. }
  26. /* Renvoie la longueur d'une chaine */
  27. int LongueurChaine(char ch[])
  28. {
  29. int i=0;
  30. while (ch[i]) i++;
  31. return i;
  32. }
  33. /* Compare 2 chaines et renvoie 1 si elles sont identiques, sinon 0 */
  34. int ComparerChaine (char ch1[], char ch2[])
  35. {
  36. int i=0;
  37. if (LongueurChaine(ch1) == LongueurChaine(ch2))
  38. {while (ch1[i] && ch2[i])
  39.  {if (ch1[i] != ch2[i++]) return 0;}
  40. return 1;
  41. }
  42. }
  43. /* Renvoie 1 si la lettre est contenue dans le mot, sinon renvoie 0 */
  44. int TestLettre (char mot[], char lettre[])
  45. {
  46. int i=0;
  47. while (mot[i])
  48. if (mot[i++] == lettre[0]) return 1;
  49. return 0;
  50. }
  51. /* Affichage du mot incomplet, renvoie 1 si le mot est complet, sinon 0  
  52.    Teste lettre a lettre si la i-ieme lettre du mot est contenue dans la
  53.    liste des lettres trouvées, et l'affiche si vrai, sinon affiche _
  54.    Renvoie 0 si un _ est affiché (mot incomplet)
  55. */
  56. int Affichage (char mot[], char trouves[])
  57. {
  58. int i=-1, win=1;
  59. while (mot[++i])
  60. {if (TestLettre(trouves,&mot[i])==1)
  61.  printf("%c ",mot[i]);
  62. else
  63.  {printf("_ " );
  64.  win=0; }
  65. }
  66. return win;
  67. }
  68. /* Dessine le pendu en fonction des erreurs, renvoie 1 tant que le pendu n'est pas complet
  69.    Toute une serie de tests determinant quoi afficher, ligne par ligne, en fonction des erreurs
  70. */
  71. int DessinerPendu(int erreurs)
  72. {
  73. printf("\n\n\n" );
  74. if (erreurs <= 3) printf("\n" );
  75. else printf(" ________\n" );
  76. if (erreurs >= 5) printf(" |/     |\n" );
  77. else if (erreurs >= 3) printf(" |/\n" );
  78.  else if (erreurs >= 2) printf(" |\n" );
  79.   else printf("\n" );
  80. if (erreurs >= 6) printf(" |      O\n" );
  81. else if (erreurs >= 2) printf(" |\n" );
  82.  else printf("\n" );
  83. if (erreurs >= 7) printf(" |     /|\n" );
  84. else if (erreurs >= 2) printf(" |\n" );
  85.  else printf("\n" );
  86. if (erreurs >= 8) printf(" |     //\n" );
  87. else if (erreurs >= 2) printf(" |\n" );
  88.  else printf("\n" );
  89. if (erreurs == 1) printf("___\n" );
  90. else if (erreurs >= 2) printf("_|_\n" );
  91.  else printf("\n" );
  92. if (erreurs >= 8) return 0;
  93. else return 1;
  94. }
  95. /* Boucle principale  
  96.    Demande une lettre tant que la chaine entrée n'est pas 'quit', que le mot n'est pas affiché
  97.    en entier, et que le pendu n'est pas affiché en entier
  98.    Ajoute le caractere entré a la liste des caracteres trouvés, si ce dernier appartient au mot
  99.    Sinon, incremente les erreurs si la chaine entrée n'est pas 'quit'
  100. */
  101. int main()
  102. {
  103. char lettre[5]="\0", trouves[30]="\0";
  104. int fautes=0, n=0;
  105. ChoisirMot();
  106. while ((ComparerChaine(lettre, "quit" ) != 1) && (Affichage(mot, trouves) != 1) && (DessinerPendu(fautes) == 1))
  107. {
  108. printf("\n\n\n\n\nVous avez trouve les lettres '%s'\n\n",trouves);
  109. printf("\n\n\nEntrez une lettre ou 'quit' pour quitter\n" );
  110. scanf("%s",lettre);printf("\n\n" );
  111. if (TestLettre(mot,lettre))
  112.  trouves[n++]=lettre[0];
  113. else if (ComparerChaine(lettre, "quit" ) != 1)
  114.  fautes++;
  115. printf("\nVous avez trouvé les lettres '%s'\n\n",trouves);
  116. printf("\n\n%d fautes\n\n",fautes);}
  117. return 0;}


---------------
Amon Amarth, Dark Tranquillity, Opeth, Dimmu Borgir, In Flames, Children of Bodom, Kreator, Metallica... pas d'la musique de paidai tout sa :o
Reply

Marsh Posté le 09-03-2006 à 15:23:02    

Au fait, quel est l'intérêt de créer plein de fonctions plutôt que d'utiliser strlen, strcpy et strcmp?


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 09-03-2006 à 15:33:15    

le meme que celui qui me pousse a créer mon pendu moi meme au lieu de copier/coller les sources sur internet  :sol:   :whistle:


---------------
Amon Amarth, Dark Tranquillity, Opeth, Dimmu Borgir, In Flames, Children of Bodom, Kreator, Metallica... pas d'la musique de paidai tout sa :o
Reply

Marsh Posté le 09-03-2006 à 15:35:08    

hum, non, aucun rapport


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 09-03-2006 à 15:42:49    

bah, je prefere juste m'netrainer a ecrire mes fonctions moi meme plutot qu'a les piocher dans dans le string.h :)
c'est sur, le jour ou j'aurai a faire des programme de plusieurs dizaines de pages, je m'embeterrai plus avec des fonctions telles que 'LongueurChaine' lol :)


---------------
Amon Amarth, Dark Tranquillity, Opeth, Dimmu Borgir, In Flames, Children of Bodom, Kreator, Metallica... pas d'la musique de paidai tout sa :o
Reply

Marsh Posté le 09-03-2006 à 16:21:13    

reiboul a écrit :

bah, je prefere juste m'netrainer a ecrire mes fonctions moi meme plutot qu'a les piocher dans dans le string.h :)


[:plusun]
 
on ne comprend jamais aussi bien le fonctionnement des chaînes de caractères en C que lorsqu'on a mis au moins une fois "les mains dans le camboui" en programmant des équivalents de strcmp,strcpy,strlen,...

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed