IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Problème sur la réalisation d'un "Jeu du pendu"


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Candidat au Club
    Homme Profil pro
    Ancien chercheur en chimie en reconversion pro
    Inscrit en
    Juin 2021
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ancien chercheur en chimie en reconversion pro

    Informations forums :
    Inscription : Juin 2021
    Messages : 2
    Par défaut Problème sur la réalisation d'un "Jeu du pendu"
    Bonjour à tous,

    Je suis actuellement un cours de C et je viens de terminer la première partie du TP#2 qui consiste à réaliser un "Jeu du pendu". La première partie de ce TP est une version simplifiée où on choisi un mot fixe à faire deviner au joueur (ici, MARRON). Dans un deuxième temps je devrais ajouter une gestion de dictionnaire, mais ça c’est pour plus tard

    Il y a un corrigé dans le cours (que j’ai compris), seulement il n’utilise pas tout à fait la même méthode que j'ai choisi pour résoudre le problème.

    De mon coté, j’ai décidé de créer deux chaines de caractères : motSecret (= MARRON) et motSecretCrypte (= ******). Je remplace au fur et à mesure les * par les bons caractères entrés par le joueur. Pour faire cela j’ai utilisé des pointeurs. Comme je débute tout juste la programmation, il se peut que je n'ai pas encore tout a fait compris cet outil et que je l'utilise d’une façon peu orthodoxe ... (dans ce cas, pardonnez moi d'avance ). De plus, j'ai voulu laisser la possibilité au joueur de rejouer une partie si il le souhaite.

    Je vous met le code de mon fichier main.c ci-dessous et le lien vers mon repo Github si besoin (https://github.com/Mitsun0bu/TP_PENDU.git) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
     
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <string.h>
    #include "headers.h"
     
    #define NOMBRE_VIES_INIT 10
     
    int main()
    {
        char lettreProposee = 0 ;
        char motSecret[] = "MARRON"; // Le mot secret est fixe pour le moment
        char motSecretCrypte[] = "******";
        char* pointeurMotSecret = motSecret;
        char* pointeurMotSecretCrypte = motSecretCrypte;
        int retourMenu = 0;
        int i = 0;
        int compteurVies = NOMBRE_VIES_INIT;
     
        do
        {
            afficherMenu();
     
            // Si on revient au menu après une première partie
            if (retourMenu == 1)
            {
                // On réinitialise le "compteurVies"
                compteurVies = NOMBRE_VIES_INIT;
     
                // On remplace le ième caractère de "motSecretCrypte" par une "*" pour le re-crypter
                for (i = 0; i < 6; i++)
                {   
                    motSecretCrypte[i] = '*'; 
                } 
            }
     
            do
            {
                printf("Il vous reste %d vies !\n", compteurVies);
                printf("Quel est le mot secret ? %s", pointeurMotSecretCrypte);
                printf("\nProposez une lettre : ");
                lettreProposee = lireCaractere();
     
                if (strchr(motSecret, lettreProposee) != NULL) // Si "lettreProposée" par le joueur est trouvée dans "motSecret"
                {
                    revelationLettre(6, motSecret, lettreProposee, motSecretCrypte, pointeurMotSecret);
                }
     
                else // Autrement, la lettre proposée n'est pas trouvée dans "motSecret" et on perd donc une vie
                {
                    compteurVies --;
                }
     
                    printf("\n");
     
                } while (compteurVies != 0 && strcmp(motSecretCrypte, motSecret) != 0);
     
                if (compteurVies == 0)
                {
                    printf("Vous avez perdu !\n");
                }
     
                else if (strcmp(motSecretCrypte, motSecret) == 0)
                {
                    printf("Bravo ! Vous avez trouve le mot secret qui etait : %s !\n", pointeurMotSecretCrypte);
                }
     
                retourMenu = rejouer();
     
        } while (retourMenu == 1);
     
        return 0;
    }
     
    void afficherMenu()
    {
        printf("\n=== JEU DU PENDU ===\n");
        printf("\nBIENVENU DANS LE JEU DU PENDU!\n");
        printf("\nBUT DU JEU:\n");
        printf("\n\tDecouvrir le mot secret\n");
        printf("\nREGLES DU JEU:\n");
        printf("\n\t1) Entrez une lettre a la fois\n");
        printf("\t2) Les accents ne sont pas pris en compte\n");
        printf("\t3) Vous disposez de 10 vies pour decouvrir le mot secret\n");
        printf("\nBONNE CHANCE !!\n\n");
    }
     
    // PERMET DE RELANCER UNE PARTIE
    int rejouer()
    {
        int rejouer = 0;
     
        printf("\n--- FIN DE LA PARTIE ---\n");
        printf("\nTapez 1 pour revenir au menu principal\n");
        printf("Tapez 2 pour quitter le jeu\n");
        printf("\nVotre choix: ");
        scanf("%d", &rejouer);
     
        return rejouer;
    }
    // PERMET DE LIRE LA LETTRE ENTREE PAR LE JOUEUR DANS LA CONSOLE 
    char lireCaractere()
    {
        char caractere = 0;
     
        caractere = getchar(); // On lit le premier caractère
        caractere = toupper(caractere); // On met la lettre en majuscule si elle ne l'est pas déjà
        while (getchar() != '\n') ; // On lit les autres caractères mémorisés un à un jusqu'au \n (pour les effacer)
     
        return caractere; // On retourne le premier caractère qu'on a lu
    }
     
    // PERMET DE REVELER LA LETTRE PROPOSEE PAR LE JOUEUR SI ELLE EST JUSTE
    void revelationLettre(int tailleMots, char mot1[], char lettreAReveler, char mot2[], char *pointeurMot1)
    {
        int i = 0;
     
        for (i = 0; i < tailleMots; i++)
        {   
            if (mot1[i] == lettreAReveler) // Si la lettre correspond à la ième lettre du mot secret
            {
                mot2[i] = pointeurMot1[i]; // On copie le ième caractère pointé par "pointeurMot1" à la ième position de "mot2"
            }
        } 
    }
    Ce code fonctionne correctement lors de la première partie. Malheureusement, lorsque je rejoue une deuxième partie, la première lettre proposée par le joueur est toujours considérée comme fausse même si elle fait partie du mot recherché.. Ensuite la partie continue normalement ! Je ne comprends pas trop pourquoi il y a un problème au premier essai de la deuxième partie seulement Surtout que si j'affiche motSecret, motSecretCrypte et leurs pointeurs respectifs via des printf, ils semblent bien réinitialisés ! (voir affichage console ci-dessous)


    --- FIN DE LA PARTIE ---

    Tapez 1 pour revenir au menu principal
    Tapez 2 pour quitter le jeu

    Votre choix: 1

    === JEU DU PENDU ===

    BIENVENU DANS LE JEU DU PENDU!

    BUT DU JEU:

    Decouvrir le mot secret

    REGLES DU JEU:

    1) Entrez une lettre a la fois
    2) Les accents ne sont pas pris en compte
    3) Vous disposez de 10 vies pour decouvrir le mot secret

    BONNE CHANCE !!

    MARRON
    MARRON
    ******
    ******
    Il vous reste 10 vies !
    Quel est le mot secret ? ******
    Proposez une lettre : a

    MARRON
    MARRON
    ******
    ******
    Il vous reste 9 vies !
    Quel est le mot secret ? ******
    Proposez une lettre :
    J’aimerais bien savoir ce qui ne va pas avec ma méthode ! Si quelqu'un pouvait m'aider, ca serait top !

    Merci d'avance !

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 837
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 837
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Une minuscule et impalpable erreur: dans la fonction "rejouer()" tu fais saisir un nombre. Or tu valides ce nombre par "<return>". Le nombre est récupéré mais pas le "<return>" qui reste dans stdin.

    Ensuite, lorsque tu rentres tes lettres, c'est ce "<return>" que tu lis. Pourtant me semblait que t'avais bien pigé le souci du "<return>" car quand tu lis les caractères, tu veilles bien à purger ensuite ce qui reste. Ceci dit moi aussi je me suis laissé piéger car il m'a fallu un printf("l=[%c]\n", lettreProposee) pour voir ce qui clochait.
    Suffit de rajouter un getchar() après la saisie.

    Concernant les pointeurs ok tu t'en sors, sauf qu'ils ne servent à rien. Ben oui, placer un pointeur "pt" sur un motX et ensuite taper dans pt[i] ou taper directement dans motX[i] c'est exactement pareil. Et contrairement aux fausses idées (qui sont en fait de vraies idées mais mal comprises), cela ne va pas plus vite. Ce qui va plus vite c'est quand le pointeur est déjà placé à sa bonne position, là oui ça va plus vite de récupérer sa valeur que taper dans le tableau indexé de sa position. Bref écrire int tab[]={1, 2, 3, 4, 5}; for (i=0; i < 5; i++) printf("%d * %d=%d\n", tab[i], tab[i], tab[i] * tab[i]); ou bien int tab[]={1, 2, 3, 4, 5}; int *pt=tab; for (i=0; i < 5; i++) printf("%d * %d=%d\n", pt[i], pt[i], pt[i] * pt[i]); c'est exactement pareil, chaque appel à ...[i] positionne au début de la zone pour calculer le décalage. Sauf que dans le second cas t'as créé inutilement une seconde variable.
    Là où le pointeur est bien utilisé c'est dans un code de ce style: int tab[]={1, 2, 3, 4, 5}; int *pt; for (i=0, pt=tab; i < 5; i++, pt++) printf("%d * %d=%d\n", *pt, *pt, (*pt) * (*pt)); car là, le pointeur est bien placé et reste bien placé tout le long de l'itération. Et on se contente de récupérer sa valeur sans calculer quoi que ce soit.

    Concernant l'aspect général de ton programme c'est pas mal. Tu essayes de découper en tâches importantes qui sont ensuite dévolues à des fonctions. Sauf que le jeu pur lui aussi c'est une tâche importante donc il devrait lui-aussi avoir sa fonction. Et le main() lui doit juste se contenter de chapeauter le tout.

    Concernant la façon de gérer le mot, ta façon de faire avec un second mot de même longueur mais caché est un peu lourde. Ok ça le fait mais dès que tu voudras faire évoluer ton code (prendre un mot dans une liste) tu vas te retrouver coincé.
    Ce que je ferais moi, c'est un tableau de toutes les lettres de l'alphabet associé à un état "lettre proposée/lettre non proposée". Ensuite, une fonction dédiée à afficher le mot mystère qui afficherait chaque lettre du mot une à une. Sauf que si la lettre n'a pas été propsée, alors la fonction affiche une étoile à la place.
    Deux tableaux en parallèle, le premier qui gère les lettres et le second qui gère les états. Ainsi quand la fonction doit afficher une lettre du mot, elle commence par chercher sa position dans le tableau des lettres puis regarde l'état à cette même position dans le tableau des états. Et ensuite si tu utilises astucieusement la valeur ascii des caractères, alors le tableau des lettres ne sert plus à rien car toute lettre à laquelle on lui enlève la valeur 'A' donne alors son rang par rapport à 'A'.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Candidat au Club
    Homme Profil pro
    Ancien chercheur en chimie en reconversion pro
    Inscrit en
    Juin 2021
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ancien chercheur en chimie en reconversion pro

    Informations forums :
    Inscription : Juin 2021
    Messages : 2
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Bonjour

    Une minuscule et impalpable erreur: dans la fonction "rejouer()" tu fais saisir un nombre. Or tu valides ce nombre par "<return>". Le nombre est récupéré mais pas le "<return>" qui reste dans stdin. (...) Suffit de rajouter un getchar() après la saisie.
    Un énorme merci à toi ! Ca fait plusieurs jour que je me casse la tête là dessus

    Citation Envoyé par Sve@r Voir le message
    Bonjour

    Pourtant me semblait que t'avais bien pigé le souci du "<return>" car quand tu lis les caractères, tu veilles bien à purger ensuite ce qui reste. Ceci dit moi aussi je me suis laissé piéger car il m'a fallu un printf("l=[%c]\n", lettreProposee) pour voir ce qui clochait.
    J'ai bien compris le soucis du "<return>" mais en bon débutant naïf je pense que je me suis laissé avoir par le fait de "relancer une partie" ... Il me semblait logique de réinitialiser le compteur de vie et le "cryptage" de mot (car ce sont des variables modifiées "automatiquement" par le programme). Un peu moins de réinitialiser la saisi de l'utilisateur à la sortie d'une partie (comme si cela allait se faire par magie )


    Citation Envoyé par Sve@r Voir le message
    Concernant les pointeurs ok tu t'en sors, sauf qu'ils ne servent à rien.
    Effectivement, j'ai modifié ma fonction revelationLettre de cette façon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void revelationLettre(int tailleMots, char mot1[], char lettreAReveler, char mot2[])
    {
        int i = 0;
     
        for (i = 0; i < tailleMots; i++)
        {   
            if (mot1[i] == lettreAReveler) // Si la lettre correspond à la ième lettre du mot secret
            {
                mot2[i] = mot1[i]; // On copie le ième caractère à la ième position de "mot2"
            }
        } 
    }
    et ca fonctionne très bien ! J'avoue que je ne sais plus trop pourquoi j'ai absolument voulu utiliser des pointeurs mais je crois que j'ai sur-réfléchi quand j'ai posé le problème sur papier..

    Citation Envoyé par Sve@r Voir le message
    Concernant la façon de gérer le mot, ta façon de faire avec un second mot de même longueur mais caché est un peu lourde. Ok ça le fait mais dès que tu voudras faire évoluer ton code (prendre un mot dans une liste) tu vas te retrouver coincé.
    Encore une fois merci, tu anticipes une question que je me posais ! A savoir, si ma façon de faire n'était pas un peu difficile à améliorer pour la suite. La solution proposée se rapproche de la tienne, je vais donc l'utiliser pour la partie 2.

    En tout cas merci beaucoup de m'avoir permis de trouver l'erreur dans mon code, je suis quand même content d'avoir réussi à faire ce que je voulais au départ grâce à toi !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [HOOK] Problème(s) pour réaliser le tutoriel sur les HOOKS
    Par Rodrigue dans le forum C++Builder
    Réponses: 13
    Dernier message: 27/07/2016, 18h22
  2. Jeu en Silverlight : problème sur les objets trop rapides
    Par tom741 dans le forum Silverlight
    Réponses: 8
    Dernier message: 28/10/2010, 14h18
  3. Problème sur la réalisation d'une vue
    Par loic20h28 dans le forum Langage SQL
    Réponses: 24
    Dernier message: 29/01/2009, 09h36
  4. Problème sur la réalisation d'une requête
    Par soso78 dans le forum Access
    Réponses: 1
    Dernier message: 06/10/2005, 13h17
  5. Problème sur Request.ServerVariables("QUERY_STRING"
    Par PrinceMaster77 dans le forum ASP
    Réponses: 3
    Dernier message: 25/03/2005, 11h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo