Problème sur un pendu

a marqué ce sujet comme résolu.

Bonjour, voici mon code: j’essaye de faire un pendu mais malheureusement sans succes… lorsque l’utilisateur saisit une lettre, et une deuxieme, la deuxieme disparait…. Donc impossible de jouer …. Quelqu’un a t-il une idée ?

#include <stdlib.h>
#include <ctype.h>
 
 
int find(char *motMystere, unsigned taille, char lettre, char *motAffiche)
{
    for (unsigned i = 0; i < taille; ++i)
        if (motMystere[i] == lettre){
            printf("%c",lettre);
            motAffiche[i]= lettre;
 
        }
        else {
            printf("*");
        }
 
    return 0;
}
 
void clean_stdin(void)
{
    int c;
 
    do {
        c = getchar();
    } while (c != '\n' && c != EOF);
}
 
 
int main(){
 
    int compteur = 10;
    char lettre;
    char motMystere[] = "MARRON";
    int taille =  sizeof(motMystere)-1;
    char motAffiche[taille];
    char nvxMot;
 
    printf("Bienvenue dans un jeu de pendu");
    while (compteur != 0){
        clean_stdin();
        printf("Il vous reste %d coup(s) \n",compteur);
        printf("Quel est le mot secret ? ");
        find(motMystere,taille, lettre, motAffiche);
        printf("\n Proposez une lettre: \n");
        scanf("%c",&lettre);
        lettre = toupper(lettre);
        printf("%c",nvxMot);
        compteur--;
} //
 
 
 
    return 0;
}

Salut,

En fait, comme l’indique le nom de ta variable tu dois afficher motAffiche. En effet, tu dois juste le mettre à jour pour y remplacer les lettres trouvées, et c’est lui que tu affiches ensuite (cela signifie qu’au début, tu dois le remplir d’étoiles). Pour le moment, tu afiches la lettre si c’est la lettre qu’a entré le joueur au tour courant, donc sans prendre en compte les tours précédents. Ta fonction find doit donc juste mettre à jour motAffiche, pas afficher des trucs. Voici d’autres remarques.

  • Fais attention à ton indentation.
  • Tu as oublié d’inclure stdio.
  • Vide ton buffer après avoir demandé une saisie, pas au début de ta boucle.
  • Pourquoi retourner un entier dans find ? En fait, tu pourrais retourner un entier pour indiquer si la lettre était bien dans le mot ou pas.
  • N’hésite pas à utiliser le mot-clé const.
  • Utilise int main(void).
  • Pour la taille d’un mot, utilise strlen.
  • Pas besoin de passer la taille à la fonction find. Tu peux la récupérer dans la fonction.
  • N’utilise pas char motAffiche[taille]. Utilise l’allocation dynamique ou sinon motAffiche[7]. Ici, je prends 7 et pas 6 car il faut aussi laisser la place pour le \0 final.
  • Ton find doit être utilisé après avoir demandé une lettre (pour mettre à jour le mot affiché avec la lettre entrée).
  • Pourquoi tu affiches nvxMot ? D’ailleurs à quoi te sert nvxMot.
  • Déclare tes variables au plus près de leur utilisation.
  • Dans ta boucle principale, il faudrait aussi s’arrêter si on a trouvé le mot.

Voici une partie du code tel que tu pourrais le corriger. Bien sûr, je t’ai quand même laisser un peu de travail (par exemple, quand tu voudras des mot au hasard, il te faudra initialiser motAffiche autrement) et je le mets en spoiler comme ça tu peux ne pas le regarder ! :)

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>


int find(const char motMystere[], size_t taille, char lettre, char motAffiche[]) {
    for (size_t i = 0; i < taille; i++) {
        if (motMystere[i] == lettre)
            motAffiche[i]= lettre;
    }
    return 0;
}

void clean_stdin(void)
{
    int c;
    do {
        c = getchar();
    } while (c != '\n' && c != EOF);
}


int main(void) {
    int compteur = 10;
    char motMystere[] = "MARRON";
    char motAffiche[] = "******";
    printf("Bienvenue dans un jeu de pendu");
    while (compteur != 0) {
        char lettre;
        printf("Il vous reste %d coup(s) \n",compteur);
        printf("Quel est le mot secret ? %s\n", motAffiche);
        printf("Proposez une lettre : ");
        scanf("%c",&lettre);
        clean_stdin();
        lettre = toupper(lettre);
        find(motMystere, 6, lettre, motAffiche);
        compteur--;
    }
    return 0;
}
+0 -0

salut merci beaucoup pour to aide, jai modifiés plusieurs petites choses mais maintenant, il ne veux pas s’executer…. pourtant mon code me semble bon. As tu une idée? L’erreure : " error 1d returned 1 exit status"

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>


int find(char *motMystere, unsigned taille, char lettre, char *motAffiche)
{
    for (unsigned i = 0; i < taille; ++i)
        if (motMystere[i] == lettre){
            motAffiche[i]= lettre;

        }
    return 0;
}

void clean_stdin(void)
{
    int c;

    do {
        c = getchar();
    } while (c != '\n' && c != EOF);
}


int main(void){

    int compteur = 10;
    char lettre;
    char motMystere[] = "MARRON";
    int taille =  strlen(motMystere)-1;
    char motAffiche[taille];
    for(int i = 0; i<taille; i++)
        motAffiche[i] = '*';
    printf("Bienvenue dans un jeu de pendu");

    while (compteur != 0){

        printf("Il vous reste %d coup(s) \n",compteur);
        printf("Quel est le mot secret ? ");
        printf("\n Proposez une lettre: \n");
        scanf("%c",&lettre);
        clean_stdin();
        find(motMystere,taille,lettre,motAffiche);
        lettre = toupper(lettre);
        printf("%s \n", motAffiche);
        compteur--;
    }



    return 0;
}
+0 -0

Salut,

Quelle erreur obtiens-tu ? Ton code n’est pas encore correct, mais il compilet et s’exécute. Au niveau des trucs à changer.

  • strlen te renvoie la taille du mot (le nombre de lettres), il ne faut pas enlever 1.
  • Puisqu’une chaîne de caractères est un tableau de lettres qui se finit par le caractère \0, ton tableau motAffiche doit être de la taille taille + 1.
  • Il te faut mettre le \0 à la fin du tableau motAffiche.
  • char motAffiche[taille]; peut passer sur ton ordinateur (et c’est correct en C99), mais je te conseille toujours de le changer.

EDIT : ton erreur n’est pas dû au code. Le message d’erreur n’est pas complet, il dit quoi après ? Vérifie que le code précédent ne s’exécute pas toujours (que tu l’as bien fermé la dernière fois), et vérifie que tu as le droit d’écrire dans le répertoire (pour que le programme puisse être créé).

+0 -0

Regarde j’arrive a executer mais cela ne marche toujours pas .Je ne sais pas comment joindre une image de mon pc pour te montrer que m’affiche la cmd…. Mon code :

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>


int find(char *motMystere, unsigned taille, char lettre, char *motAffiche)
{
    for (unsigned i = 0; i < taille; ++i)
        if (motMystere[i] == lettre){
            motAffiche[i]= lettre;
        }
        else {
            printf("*");
        }
    return 0;
}

void clean_stdin(void)
{
    int c;

    do {
        c = getchar();
    } while (c != '\n' && c != EOF);
}


int main(void){

    int compteur = 10;
    char lettre;
    char motMystere[] = "MARRON";
    int taille =  strlen(motMystere);
    char motAffiche[taille +1];
    for(int i = 0; i<taille; i++)
        motAffiche[i] = '*';
    printf("Bienvenue dans un jeu de pendu \n");

    while (compteur != 0){
        find(motMystere,taille,lettre,motAffiche);
        printf("Il vous reste %d coup(s) \n",compteur);
        printf("Quel est le mot secret ? ");
        printf("\n Proposez une lettre: \n");
        scanf("%c",&lettre);
        lettre = toupper(lettre);
        clean_stdin();
        printf("%s \n", motAffiche);
        compteur--;
    }



    return 0;
}
+0 -0

Le souci, c’est que tu n’essaies pas vraiment de faire un code correct ; là si ton programme se met à fonctionner, on pourra juste dire qu’il est « tombé en marche », par chance. Quand tu écris une ligne de code, tu dois savoir pourquoi tu l’écris, pas l’écrire parce que tu penses que ça va corriger ton code. Donc, on va reprendre les choses calmement. Comment fonctionne le jeu du pendu ?

  1. On choisit un mot à faire deviner.
  2. On affiche des étoiles.
  3. On demande une lettre.
  4. On regarde si elle est dans le mot et où elle est.
  5. On retourne à l’étape 2.

Et on s’arrête si on a trouvé le mot où s’il ne reste plus d’essais.

Comment faire les différentes étapes dans ton code ? On note déjà que les étapes 2 à 5 seront dans une boucle

  1. C’est une étape facile, le mot est fixé.
  2. Dans ton code, on a motAffiche qui est le mot qu’on devra afficher. Au début, il n’a que des étoiles, mais on le met à jour quand on trouve une lettre. Par exemple, si l’utilisateur devine le « A », on remplacera la seconde étoile de motAffiche par un A, et donc quand on l’affichera on aura « *A**** » ; si ensuite il trouve le « R », on remplacera les deuxième et troisième étoile de motAffiche et donc lorsqu’on l’affichera on aura « *ARR** ».
  3. L’utilisateur tape une lettre, c’est OK dans ton code. Tu peux faire une fonction getLetter qui demande la lettre, la met en majuscule et la renvoie (et elle pourrait même demander à l’utilisateur tant qu’il n’a pas rentré de lettre, au cas où il rentre autre chose).
  4. Ça c’est le travail de la fonction find. Regarder si la lettre est dans le mot et où elle est, c’est mettre à jour motAffiche, comme ça la prochaine fois qu’il sera affiché, les lettres trouvées seront là au lieu des étoiles.

S’arrêter s’il ne reste plus d’essais, tu le fais déjà (reste à rajouter la condition « on a trouvé le mot », ça veut juste dire que motAffiche et motMystere sont pareils).

Maintenant, quels sont les problèmes dans ton code.

  • Déjà, si on regarde les étapes qu’il doit y avoir dans notre boucle, tu ne les fais pas dans le bon sens. Tu appelles find au début de la boucle, avant même d’avoir demandé une lettre à l’utilisateur.
  • Dans la fonction find, tu affiches des trucs, pourquoi ? Elle doit juste mettre à jour motAffiche avec la lettre proposée par l’utilisateur, ce qu’elle fait avec le if dans la boucle for.

Ça c’est les deux problèmes qui peuvent bien se voir grâce à la structure du programme. Mais même en corrigeant ça, motAffiche s’affichera peut-être mal (des caractères supplémentaires à la fin). C’est peut-être un problème que tu as observé d’ailleurs. Ça arrive parce que tu n’as pas mis le \0 final à la fin de motAffiche. Pourtant, ça t’a été dit plusieurs fois sur Discord, donc j’imagine que ça signifie que tu ne sais pas/n’a pas bien compris pourquoi il était important. On va donc rapidement expliquer ça.

En C, une chaîne de caractères, c’est un tableau de caractères… terminé par le caractère \0. Le truc, c’est qu’il faut savoir où la chaîne se termine. Pour ça, on pourrait avoir une structure avec le tableau et sa taille. Le C a choisi que la chaîne se terminait quand il y avait un \0. Et donc, pour afficher une chaîne de caractères, on fait quoi ? On fait une boucle while, et tant qu’on a pas de \0, on affiche le caractère et on passe au caractère suivant.

void print_string(const char s[]) {
   for(size_t i = 0; s[i] != `\0`; i++) // tant que s[i] n'est pas `\0`
       putchar(s[i]) // On affiche le caractère s[i]
}

Ça signifie que si tu oublies ce \0 à la fin de ton tableau de caractères, lorsque tu voudras afficher la chaîne de caractères correspondante, cette chaîne s’affichera, mais aussi tout ce qu’il y a après jusqu’à ce qu’on tombe sur un \0. Comme on n’a aucune garantie de ce que peut contenir la mémoire (en vrai, il y a peut-être un \0 à la case juste après la dernière case de notre tableau si on a de la (mal)chance), il ne faut pas l’oublier.

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte