Mon nouveau jeu

Résolu/Fermé
jeandchanel Messages postés 135 Date d'inscription vendredi 10 juin 2016 Statut Membre Dernière intervention 31 mai 2017 - Modifié par jeandchanel le 1/11/2016 à 09:27
jeandchanel Messages postés 135 Date d'inscription vendredi 10 juin 2016 Statut Membre Dernière intervention 31 mai 2017 - 25 nov. 2016 à 07:28
Bonjour,
je suis entrain de coder un nouveau jeu dont voici le principe :

L'ordinateur génère une combinaison de 5 chiffres. Le joueur choisit un nombre entre 1 et 5, l'ordinateur vérifie si ce nombre figure dans la combinaison :
1. Si le chiffre ne s'y trouve pas, le jeu s’arrête.
2. Si le chiffre s'y trouve, le jeu peut continuer. L'ordinateur demande au joueur le nombre de fois que le chiffre figure dans la combinaison :
3. Si la proposition du joueur est fausse, le jeu s’arrête et on lui dévoile la bonne réponse,
4. Si elle est bonne, le jeu peut continuer. L'ordinateur demande alors au joueur d'indiquer la ou les positions respectives du chiffre dans la combinaison :
5. Si la proposition du joueur est fausse, le joueur perd la partie, on lui indique cela et on lui dévoile la bonne réponse,
6.Si c'est bon, le joueur gagne et on le lui fais savoir !

j'ai implémenté tout cela mais j'ai un soucis au niveau des points 4, 5 et 6. Ici, quand on a le cas "location[i] == position[i]" le message affiché est "Désolé, vous avez perdu !" et non pas "Bravo, vous avez gagne !"
voici d'ailleurs le déroulement d'une partie :


Running "/home/ubuntu/workspace/Le_Jeu_De_Cinq/cinq.c"

25154 ==> la combinaison du jeu.

Entrez le chiffre a rechercher : 4 ==> le chiffre choisit par le joueur.

Le chiffre 4 figure t-il dans la combinaison ?
1. Oui
Votre reponse : 1

Bien joue, passons a l'etape suinvante !

Le chiffre 4 figure combien de fois dans la combinaison ?
Votre reponse : 1

Bien joue, passons a l'etape suivante !

Quelle(s) est la (sont les) position(s) (respectives) du chiffre 4 ? :
5 ==> proposition du joueur (bonne proposition, voir combinaison : 25154).

Desole, vous avez perdu ! ==> Message de l'ordinateur !

Sa (ses) position(s) (respectives) est (sont) :
5 ==> affichage de la bonne position par l'ordinateur !

Voulez-vous reessayer ou quitter ?
1. Reessayer
2. Quitter

Votre choix ? :




EDIT : Ajout des balises de code (la coloration syntaxique).
Explications disponibles ici : ICI

Merci d'y penser dans tes prochains messages.
A voir également:

3 réponses

[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 4/11/2016 à 15:14
Salut Jean,

L'algorithme tu l'as déjà, c'est la description de ton programme, de sa logique et de son déroulement avec les 8 étapes que tu décris dans ton poste initial.

Si je devais écrire un tel programme, je simplifierai considérablement ton code :

- avec
int tirage[5];
comme seul tableau contenant le tirage
- sans utiliser malloc

Pour faire les opérations de 1 à 8, tes fonctions peuvent très bien travailler sur ce seul tableau où se trouve stocké le tirage aléatoire et renvoyer les résultats des vérifications.

A première vue, je verrai bien des fonctions avec les prototypes suivants :

- avec
int existe(int * tirage, int chiffre);
pour savoir si le chiffre proposé est présent ou pas
- avec
int nb_repetitions(int * tirage, int chiffre, int nbrep);
pour vérifier si pour le chiffre proposé, le nombre de répétitions est le bon
- avec
int emplacements(int * tirage, int chiffre, char places[10]);
pour vérifier les propositions, à saisir par l'utilisateur sous la forme d'une chaîne contenant 5 positions maximum, les positions étant séparées par des espaces (ou autre chose, mais c'est assez simple de demander à l'utilisateur de saisir "1 2 5" s'il veut proposer ces 3 emplacements)

Ces fonctions renvoient int, et donc 0 si la proposition est fausse, et 1 ou une autre valeur que 0 si le résultat est exact.


Dal
1
jeandchanel Messages postés 135 Date d'inscription vendredi 10 juin 2016 Statut Membre Dernière intervention 31 mai 2017
4 nov. 2016 à 17:26
Merci pour tous tes conseils Dal, j’écris les codes de toutes ces fonctions, je compile le tout et je te rend compte.
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 4/11/2016 à 17:51
OK, ait à l'esprit que ce sont des fonctions qui font des choses simples, chacune ne devrait pas faire plus de 5 à 6 lignes pour faire le boulot, hein :-)

en fait, le plus compliqué dans ton programme est de traiter la saisie de l'utilisateur et de vérifier qu'elle est cohérente par rapport à ce qui est attendu, sécurisée, sans erreurs,...

aussi, à la réflexion, pour la fonction emplacements(), on peut rendre plus générique le prototype en faisant :
int emplacements(int * tirage, int chiffre, char * places);
ce qui évite d'avoir à changer le prototype si tu changes ta taille maximale dans ton programme.
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 4/11/2016 à 18:39
en fait
int emplacements(int * tirage, int chiffre, int nbrep, char * places);
avec quelques lignes de plus de code pour vérifier que tous les emplacements ont bien été trouvés

enfin bon... pour gagner à ton jeu il faut avoir beaucoup de chance ou être un peu voyant :-P
0
jeandchanel Messages postés 135 Date d'inscription vendredi 10 juin 2016 Statut Membre Dernière intervention 31 mai 2017 > [Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024
7 nov. 2016 à 12:23
Bonjour Dal,

Il s'agit ici d'un jeu en construction. L'essentiel pour moi est que la boucle principale du jeu fonctionne correctement ensuite apres je pourrais faire des petites modifications pour que le joueur puisse gagner sans etre un "voyant" !!! A bientot .
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 16/11/2016 à 09:44
Salut Jean,

J'avais fait un code rapide il y a deux semaines, le voici un peu adapté, avec quelques commentaires, avec des fonctions
affiche_tirage()
et
perdu()
permettant d'éviter des répétitions. Pour cet exemple, il n'y pas les fonctions de saisie (tu peux faire varier les données initialisées pour tester le comportement, ou rajouter ces fonctions si tu veux).

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

#define TAILLE 5

int existe(int * tirage, int chiffre);
int nb_repetitions(int * tirage, int chiffre, int nbrep);
int emplacements(int * tirage, int chiffre, int nbrep, char * places);
void affiche_tirage(int * tirage);
void perdu(int * tirage, char * motif);

int main(void) {
    int tirage[TAILLE] = { 2, 5, 1, 5, 4 };
    int chiffre = 5;
    int nbrep = 2;
    char places[TAILLE*2] = "2 4";

    /* on devine le chiffre */
    if (existe(tirage, chiffre))
        printf("Oui, le chiffre %d existe bien dans le tirage\n",
                chiffre);
    else
        perdu(tirage, "ce chiffre n'existe pas dans le tirage");

    /* on devine le nombre de répétitions */
    if (nb_repetitions(tirage, chiffre, nbrep))
        printf("Oui, le chiffre %d est bien répété %d fois "
                "dans le tirage\n", chiffre, nbrep);
    else
        perdu(tirage, "ce n'est pas le bon nombre de répétitions");

    /* on devine les emplacements */
    if (emplacements(tirage, chiffre, nbrep, places))
        printf("Oui, vous avez bien deviné les emplacements %s\n",
                places);
    else
        perdu(tirage, "ce ne sont pas les emplacements corrects "
                "de ce chiffre");

    /* féliciter le joueur pour ses dons de voyance */
    printf("Bravo !\nLe tirage était : ");
    affiche_tirage(tirage);
    printf("\n... vos dons de voyance sont impressionnants !\n");

    return 0;
}

/* --------- fonctions --------- */

/* pour savoir si le chiffre proposé est présent ou pas */
int existe(int * tirage, int chiffre) {
    int i;

    for (i=0; i < TAILLE; i++)
        if (tirage[i] == chiffre)
            return 1;
    return 0;
}

/* pour vérifier si pour le chiffre proposé, le nombre de 
 * répétitions est le bon */
int nb_repetitions(int * tirage, int chiffre, int nbrep) {
    int i;
    int n = 0;

    for (i=0; i < TAILLE; i++)
        if (tirage[i] == chiffre)
            n++;
    return (n == nbrep);
}

/* pour vérifier les propositions, à saisir par l'utilisateur 
 * sous la forme d'une chaîne contenant 5 positions maximum, 
 * les positions étant séparées par des espaces */
int emplacements(int * tirage, int chiffre, int nbrep, char * places) {
    int trouves = 0;

    while (*places) {
        if ((*places != ' ') && (tirage[*places-'0'-1] != chiffre))
            return 0;   /* l'emplacement proposé est incorrect */
        if ((*places != ' ') && (tirage[*places-'0'-1] == chiffre))
            trouves++;  /* l'emplacement proposé est correct */
        places++;
    }
    if (trouves != nbrep)
        return 0;       /* on n'a pas trouvé tous les emplacements */
    return 1;
}

void affiche_tirage(int * tirage) {
    int i;

    for (i=0; i < TAILLE; i++)
        printf("%d", tirage[i]);
}

void perdu(int * tirage, char * motif) {
    printf("Perdu : %s\nLe tirage était : ", motif);
    affiche_tirage(tirage);
    printf("\n");
    exit(1);
}

donne :
$ gcc -Wall jeude5.c 
$ ./a.out
Oui, le chiffre 5 existe bien dans le tirage
Oui, le chiffre 5 est bien répété 2 fois dans le tirage
Oui, vous avez bien deviné les emplacements 2 4
Bravo !
Le tirage était : 25154
... vos dons de voyance sont impressionnants !

Dal
1
jeandchanel Messages postés 135 Date d'inscription vendredi 10 juin 2016 Statut Membre Dernière intervention 31 mai 2017
Modifié par jeandchanel le 24/11/2016 à 17:15
Bonsoir Dal,
Grâce a vous j'ai enfin réussi a réaliser mon jeu, Merci beaucoup !
Voici le déroulement d'une partie :

LE JEU DES DEVINETTES
Code par Jean Dechanel


Le tirage du jeu : XXXXX

Entrez le chiffre a rechercher : 1

Oui, le chiffre 1 existe bien dans le tirage


Quel est le nombre de repetitions de ce chiffre ? : 2

Oui, le chiffre 1 est bien répété 2 fois dans le tirage


Quels sont les emplacements de ce chiffre : 12


Perdu : ce ne sont pas les emplacements corrects de ce chiffre !

Le tirage était : 31133


Voulez-vous reessayer ou quitter ?
1. Reessayer
2. Quitter

Votre choix ?
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
24 nov. 2016 à 19:15
champagne !
0
jeandchanel Messages postés 135 Date d'inscription vendredi 10 juin 2016 Statut Membre Dernière intervention 31 mai 2017 > [Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024
25 nov. 2016 à 07:28
Grand Merci a vous.
0
NHenry Messages postés 15113 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 22 avril 2024 331
1 nov. 2016 à 11:21
Avec quel code ?
-1
jeandchanel Messages postés 135 Date d'inscription vendredi 10 juin 2016 Statut Membre Dernière intervention 31 mai 2017
Modifié par NHenry le 1/11/2016 à 15:12
ok pardon, voici le main.c :

#include "jeu.h"


int main(void)
{
   int i = 0, chiffre = 0,  compteur = 0, find = 0, reponse = 0, choice = 0;
   int comb[TAILLE_MAX];
   int *location = NULL, *position = NULL, *trouver = NULL, *bon = NULL;
    
   
 do
 { 
   
    trouver = malloc( TAILLE_MAX * sizeof(char) );
    bon = malloc( TAILLE_MAX * sizeof(char) );
    location = malloc( TAILLE_MAX * sizeof(char) );
    position = malloc( TAILLE_MAX * sizeof(char) );
   
   if(trouver == NULL)
   exit(EXIT_FAILURE);
   
   if(bon == NULL)
   exit(EXIT_FAILURE);
   
   if(location == NULL)
   exit(EXIT_FAILURE);
   
   if(position == NULL)
   exit(EXIT_FAILURE);
   
    combiJeu(comb);
   
   printf("\n\nEntrez le chiffre a rechercher : ");
   chiffre = lireLong();
   
    for(i = 0; comb[i]; i++)
    {
      if(chiffre == comb[i])
      {
          find = 1;
          trouver[i] = comb[i];
          position[i] = (i+1);
          compteur++;
          
      }else
           {
               trouver[i] = 0;
               position[i] = 0;
           }
    }
     
  
  
    if( compteBonsChiffres(trouver, bon) )
    {
       afficheChiffresTrouves(trouver);
       
      choice = demanderNombre(chiffre);
      
      reponse = demanderFrequence(chiffre);
      
      if( reponse == compteBonsChiffres(trouver, bon) )
      {
          
         printf("\n\nBien joue, passons a l'etape suivante !");
         
         printf("\n\nQuelle(s) est la (sont les) position(s) (respectives) de %d ? : \n", chiffre);
         
         recuperePositions(position, location);
         
         
           if( gagner(location, position, bon) )
           {
             printf("\nBravo, vous avez gagner !"); 
             
           }else
           {
               printf("\n\nDesole, vous avez perdu !");
                
               printf("\n\nSa (ses) position(s) (respectives) est (sont) : ");
               
               affichePositions(position);
            }
           
      
           
      }else
      {
          printf("\nDesole, c'est faux !");
          printf("\n%d figure %d fois dans la combinaison !", chiffre, compteBonsChiffres(trouver, bon) );
      }
      
        
       
          
    }else
    {
        
       printf("\n"
              "Desole, %d ne figure pas dans la combinaison !"
              "\n\nVous ne pouvez donc pas jouer !"
              "\n\nBien vouloir reessayer pour jouer !", chiffre);
    }
    
    free(trouver);
    free(bon);
    free(location);
    free(position);
 
    
 }while( rejouerPartie() );
 
   
  
  printf("\n\n\nPartie terminee !");
  
  

   
            
    return EXIT_SUCCESS;
}


EDIT : Ajout du LANGAGE dans les balises de code (la coloration syntaxique).
Explications disponibles ici : ICI

Merci d'y penser dans tes prochains messages.
0
jeandchanel Messages postés 135 Date d'inscription vendredi 10 juin 2016 Statut Membre Dernière intervention 31 mai 2017 > jeandchanel Messages postés 135 Date d'inscription vendredi 10 juin 2016 Statut Membre Dernière intervention 31 mai 2017
1 nov. 2016 à 17:24
C'est déjà fait !
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 2/11/2016 à 18:46
Ce code ne compile pas.. on n'a pas le .h (ni l'éventuel .c qui devrait correspondre au .h)

:-)

Sinon, pourquoi allouer dynamiquement la mémoire de tes structures (en plus pour la libérer à chaque itération) ?

Si la taille est fixée, ce n'est pas vraiment utile, et cela est source d'erreurs dans ton cas, car tu n'alloues certainement pas la bonne quantité de mémoire, puisqu'il s'agirait de pointeurs sur int, et que tu alloues de l'espace en te basant sur la taille d'un char ... et non d'un int.


Dal
0
jeandchanel Messages postés 135 Date d'inscription vendredi 10 juin 2016 Statut Membre Dernière intervention 31 mai 2017 > [Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024
3 nov. 2016 à 07:58
Bonjour Dal, voici le ficier .h

#ifndef DEF_JEU
#define DEF_JEU

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdbool.h>

#define TAILLE_MAX 5

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


int lire(char* chaine, int longueurChaine)
{
     char* positionEntree = NULL;
    
    if(fgets(chaine, longueurChaine, stdin) != NULL)
    {
        positionEntree = strchr(chaine, '\n');
        
        if(positionEntree != NULL)
        {
           *positionEntree = '\0';
        }return 1;
    }else
    {
       viderBuffer();
       return 0;
    }
    
}


long lireLong()
{
    char nombreTexte[100] = {0};
    if(lire(nombreTexte, 100))
    {
        return strtol(nombreTexte, NULL, 10);
    }else
    {
        viderBuffer();
        return 0;
    }
}


double lireDouble()
{
   char nombreTexte[100] = {0};
   char *positionVirgule = NULL;
   if(lire(nombreTexte, 100))
   {
       positionVirgule = strchr(nombreTexte, ',');
       if(positionVirgule != NULL)
       {
         *positionVirgule = '.';
       }return strtod(nombreTexte, NULL);
   }else
   {
      viderBuffer();
      return 0;
   }
}

bool rejouerPartie()
{
    long choice = 0;
    printf("\n\n"
           "Voulez-vous reessayer ou quitter ?\n"
           "1. Reessayer\n2. Quitter\n");
    do
    {
        printf("\n"
               "Votre choix ? ");
        choice = lireLong();
    }while(choice < 1 || choice > 2);
    
    return choice == 1;
}



void combiJeu(int* comb)
{
  int i, min = 1, max = 5;
  
  srand( time(NULL) );
  
  for(i = 0; i < TAILLE_MAX; i++)
  {
     comb[i] = (rand() % (max - min + 1) + min);
     printf("%d", comb[i]);
  }
   
}

int demanderNombre(int chiffre)
{
    long choice = 0;
    int i = 0;
    
     printf("\n"
            "Le chiffre %d figure t-il dans la combinaison ?"
            "\n1. Oui", chiffre);
           do
           {
              printf("\nVotre reponse : ");
              choice = lireLong();
           }while(choice < 1);
           
    return choice;
}


int demanderFrequence(int chiffre)
{
    long reponse = 0;
    int i = 0;
    
       printf("\nBien joue, passons a l'etape suinvante !");
       printf("\n\n"
              "Le chiffre %d figure combien de fois dans la combinaison ?", chiffre);
              do
              {
                 printf("\nVotre reponse : ");
                 reponse = lireLong();
              }while(reponse < 1 || reponse > 5);
              
       return reponse;       
}


int gagner(int* location, int* position, int* bon)
{
    int i = 0, win = 0;
    
    for(i = 0; i < TAILLE_MAX; i++ )
    {
       if(location[i] == position[i])
       {
          win = 1;
       }
       
    }
       
    
    return win == 1;
}



int compteBonsChiffres(int* trouver, int* bon)
{
    int i = 0, var = 0, compteur = 0;
    for(i = 0; i < TAILLE_MAX; i++)
    {
      if(trouver[i] != 0)
      {
         bon[i] = trouver[i];
         var = 1;
         compteur++;
      }else
      var = 0;
    }
    
    return compteur;
}

int boucle(int* trouver)
{
    int i = 0, find = 0;
    for(i = 0; i < TAILLE_MAX; i++)
    {
        if(trouver[i] != 0)
        {
            find = 1;
        }
    }
    
    return find == 1;
}

int afficheChiffresTrouves(int* trouver)
{
    int i = 0;
     for(i = 0; i < TAILLE_MAX; i++)
        {
           if(trouver[i] != 0)
           {
             printf("\n%d", trouver[i]);
           }
         
        }
        
        return *trouver;
}

int recuperePositions(int* position, int* location)
{
    int i = 0;
    for(i = 0; i < TAILLE_MAX; i++)
         {
           if(position[i] != 0)
           {
             location[i] = lireLong();
           }
         
         }
         
         return *location;
}

int affichePositions(int* position)
{
    int i = 0;
    for(i = 0; i < TAILLE_MAX; i++)
    {
        if(position[i] != 0)
        {
            printf("\n%d", position[i]);
        }          
    }
    
    return *position;
}

#endif 
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 3/11/2016 à 12:28
Pour éliminer le plus visible :

- comme indiqué plus haut, tes malloc devraient être basés sur une taille de int
malloc( TAILLE_MAX * sizeof(int) )
et pas
malloc( TAILLE_MAX * sizeof(char) )
... avec ton arithmétique de pointeurs basée sur un type pointeur sur int, tu vas déborder l'espace alloué dès que tu utiliseras l'indice 1 (sur ma machine
sizeof(char)
vaut 1 alors que
sizeof(int)
vaut 4)

- ta boucle en ligne 37 ne devrait pas être
for(i = 0; comb[i]; i++)
mais plutôt
for(i = 0; i < TAILLE_MAX; i++)
, cette boucle for non bornée correctement peut aussi occasionner une corruption de la mémoire allouée (avec un
i
et une zone mémoire pointée par
combi
non initialisés, l'arrêt est imprévisible)

Prend l'habitude de mettre systématiquement des
\n
à la fin de tes
printf
, pour être sûr que le texte s'affiche.. sinon, il est mis en tampon et n'est affiché qu'au prochain
\n
rencontré.

Sinon, Jean, il y a 350 lignes de code à déboguer... avec des problèmes qui existent bien avant tes étapes 4, 5 et 6... en fait.. un peu partout, des variables et du code inutile, des fonctions qui présentent un seul choix, ou qui ne font pas ce qu'elles sont sensées faire, qui renvoient des choses inutiles, etc.

Utilise un débogueur stp et exécute pas à pas ton code pour te rendre compte de ce que fait vraiment ton code.


Dal
0