Jeu de code mystère en C

Résolu/Fermé
Sakuude - Modifié le 12 janv. 2023 à 00:59
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 - 13 janv. 2023 à 03:19

Bonjour,

On m'a déjà beaucoup aidé pour un code mais voilà, je n'y arrive plus je suis bloqué. Donc le sujet est de générer une suite de 5 chiffres compris entre 0 et 9. Ensuite 

  • réaliser une première version du jeu où`, pour chaque chiffre donné par le joueur, vous indiquerez par un caractère si il est bien placé (’+’), présent dans le code mystère mais mal placé (’∼’), ou non présent dans le code mystère (’−’) ;

J'ai essayé une forme de code qui ne marche pas mais alors pas du tout... l'échéance est ce soir et je suis dans la mouise pour tout vous dire... Si une bonne étoile peut m'aider à comprendre réellement, merci.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LANCER     5
int main(void) {
    int tab[10];
    srand(time(NULL));
    int quitter = 0, nombreJuste,i;
    do {
        printf("Menu ...\n");
        for(int i = 0; i < 10; i++)  tab[i] = i;
        for(int i = 0; i < LANCER; i++) {
            int j = rand() % 10;
            int temp = tab[i];
            tab[i] = tab[j];
            tab[j] = temp;
        }
        for(int i = 0; i < LANCER; i++)  printf("%d ", tab[i]);
        printf("\n");
        int fini = 0;
        
        printf("Vous allez dès à présent deviner les chiffres. Si le chiffre est bien placé, ('+'), présent mais mal placé ('∼') et s'il n'est pas présent, ('-'). \n");
        printf("Donner moi un nombre entre 0 et 9\n");

        do{
            if (nombreJuste==tab[i])
            {
                tab[i]='+';
            }
        }while(!quitter);

        do {
            // Jusqu'à ce que ça soit fini ...
            fini = 1;   // Je décide que c'est fini ...
        } while(!fini);
        printf("Voulez-vous quitter? (0 = non, 1 = oui) ");
        scanf("%d", &quitter);
    } while(!quitter);
    return 0;
}


Macintosh / Safari 16.2

A voir également:

3 réponses

Je ne suis pas spécialiste en c, mais tout de même ton compilateur doit bien t'indiquer ce qui cloche non ?

do{
    if (nombreJuste==tab[i])
    {
        tab[i]='+';
    }
}while(!quitter);

D'où sort le i ? Où est-il initialisé ? où est l'incrémentation ?
Où est effectué l'affectation d'une valeur à nombreJuste ?
tab est un tableau d'entier, pourquoi veux-tu y stocker un caractère ? Il te faudra forcément un autre tableau pour stocker ces +, -, ~
De plus tu ne sortira jamais de ta boucle puisque jamais tu ne donnes une valeur à quitter permettant de sortir du while, pourquoi un while d'abord, et pourquoi la condition est la valeur de quitter ?

Tant de choses ne vont pas, que c'est mal barré pour ce soir XD

0
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LANCER     5
int main(void) {
    int tab[10];
    srand(time(NULL));
    int quitter = 0, nombreJuste,i, nombreBienPlaces, nombreEssais=0;
    char bien1=;
    do {
        printf("Menu ...\n");
        for(int i = 0; i < 10; i++)  tab[i] = i;
        for(int i = 0; i < LANCER; i++) {
            int j = rand() % 10;
            int temp = tab[i];
            tab[i] = tab[j];
            tab[j] = temp;
        }
        for(int i = 0; i < LANCER; i++)  
            printf("%d ", tab[i]);
            printf("\n");
        int fini = 0;
        
        printf("Vous allez dès à présent deviner les chiffres. Si le chiffre est bien placé, ('+'), présent mais mal placé ('∼') et s'il n'est pas présent, ('-'). \n");
        printf("Donner moi un nombre entre 0 et 9\n");

        do{
            nombreBienPlaces=0;
            nombreEssais++;
            scanf("%d", &nombreJuste);
            if (nombreJuste==tab[i] || nombreJuste==tab[i+1])
            {
                tab[i]=bien1;
                printf("%d\n", tab[i]);
                nombreBienPlaces=nombreBienPlaces+1;
            }
        }while(nombreBienPlaces==5);

        do {
            // Jusqu'à ce que ça soit fini ...
            fini = 1;   // Je décide que c'est fini ...
        } while(!fini);
        printf("Voulez-vous quitter? (0 = non, 1 = oui) ");
        scanf("%d", &quitter);
    } while(!quitter);
    return 0;
}

J'ai fais déjà des modifications mais effectivement je ne vois pas comment faire pour transformer la valeur du tableau [i] en +

0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
Modifié le 12 janv. 2023 à 01:53

Bonjour,

Tout d'abord, pardon de répondre alors que la date butoir est passée, mais j'espère que ma réponse t'aidera à progresser.

  • Concernant le tirage : il n'est pas stipulé que les nombres du code secret doivent être distincts. Tu t'es donc un peu compliqué la vie.
  • Concernant la compilation : il manque quelque chose ligne 9
  • Concernant l'indentation : tu as, vu l'indentation, sûrement oublier de mettre une accolade ouvrante à la fin de la ligne 19 et une accolade fermante entre les ligne 21 et 22
  • Concernant la structure du code : il aurait sans doute été une bonne idée de faire des fonctions pour rendre le code plus lisible et plus modulaire.
  • Concernant ta question : il suffit de créer un tableau auxiliaire que j'ai appelé code_reponse de type char[] dans lequel tu vas écrire les caractères associés à chaque chiffre proposé. Après, tu peux même te passer de ce tableau auxiliaire et afficher directement les caractères au fur et à mesure de la comparaison entre le code secret et le code saisi.

Quelques remarques préalables pour comprendre ce qui suit :

  • Comme on travaille avec des entiers positifs dans tout le code, j'ai utilisé le type size_t partout au lieu de int (et son format correspondant, %zu au lieu de %d).
  • Pour nos fonctions, on a besoin de passer des tableaux en paramètre.
    • En C, cela revient à passer l'adresse du début du tableau (tab). Comme cette adresse ne véhicule pas la taille du tableau, il faut donc également la passer en paramètre (n).
    • Pour rappel, la notation tab[i] signifie lire la i-ème valeur (conformément au type de "case" associé au tableau) en lisant la valeur qui se trouve à l'adresse tab + i fois la taille d'une case.
    • Dit autrement, il n'y a pas réellement de notion de tableau en C, c'est juste un jeu d'écriture, mais fondamentalement, il n'est question que d'adresses mémoires.

Voici à quoi peut ressembler ton code une fois modifié :

  • n correspond au nombre de chiffres impliqués dans le code
  • k correspond à la valeur maximale que peut prendre un chiffre du code secret
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void creer_code(size_t * code, size_t n, size_t k) {
    for (size_t i = 0; i < n; i++) {
        code[i] = rand() % (k + 1);
    }
}

void afficher_code(const size_t * code, size_t n) {
    for (size_t i = 0; i < n; i++) {
        printf("%zu ", code[i]);
    }
    printf("\n");
}

void afficher_code_reponse(const char * code_reponse, size_t n) {
    for (size_t i = 0; i < n; i++) {
        printf("%c ", code_reponse[i]);
    }
    printf("\n");
}

void saisir_code(size_t * code, size_t n, size_t k) {
    int ret;
    for (size_t i = 0; i < n; i++) {
        do {
            printf("Saisir le chiffre %zu / %zu: ", i + 1, n);
            ret = scanf("%zu", &code[i]);
        } while (ret != 1 || code[i] >= k || code[i] <= 0);
    }
    printf("Code saisi : ");
    afficher_code(code, n);
}

bool code_contient(const size_t * code, size_t n, size_t chiffre) {
    for (size_t i = 0; i < n; i++) {
        if (code[i] == chiffre) {
            return true;
        }
    }
    return false;
}

size_t comparer_codes(
    const size_t * code_secret,
    const size_t * code_saisi,
    char * code_reponse,
    size_t n
)  {
    size_t num_corrects = 0;
    for (size_t i = 0; i < n; i++) {
        size_t chiffre = code_saisi[i];
        if (chiffre == code_secret[i]) {
            code_reponse[i] = '+';
            num_corrects++;
        } else if (code_contient(code_secret, n, chiffre)) {
            code_reponse[i] = '~';
        } else {
            code_reponse[i] = '-';
        }
    }
    afficher_code_reponse(code_reponse, n);
    return num_corrects;
}

int lancer_partie(const size_t * code_secret, size_t n, size_t k, size_t max_essais) {
    size_t code_saisi[n];
    char code_reponse[n];
    size_t num_corrects;
    for (size_t essai = 0; essai < max_essais; essai++) {
        printf("Essai %zu / %zu\n", essai + 1, max_essais);
        saisir_code(code_saisi, n, k);
        num_corrects = comparer_codes(code_secret, code_saisi, code_reponse, n);
        if (num_corrects == n) {
            return 1; // Victoire
        }
    }
    return 0; // Défaite
}

int main() {
    size_t code_secret[5];
    srand(time(NULL));
    size_t quitter = 0, n = 5, k = 9, max_essais = 10;
    do {
        creer_code(code_secret, n, k);
        printf("Code secret : ");
        afficher_code(code_secret, n);
        lancer_partie(code_secret, n, k, max_essais);
        printf("Voulez-vous quitter? (0 = non, 1 = oui) ");
        scanf("%d", &quitter);
    } while(!quitter);
    return 0;
}

Résultat :

(mando@aldur) (~) $ gcc toto.c 
(mando@aldur) (~) $ ./a.out 
Code secret : 1 3 2 5 5 
Essai 1 / 10
Saisir le chiffre 1 / 5: 1
Saisir le chiffre 2 / 5: 2 
Saisir le chiffre 3 / 5: 3
Saisir le chiffre 4 / 5: 4
Saisir le chiffre 5 / 5: 5
Code saisi : 1 2 3 4 5 
+ ~ ~ - + 
Essai 2 / 10
Saisir le chiffre 1 / 5: 1  
Saisir le chiffre 2 / 5: 3
Saisir le chiffre 3 / 5: 2
Saisir le chiffre 4 / 5: 5
Saisir le chiffre 5 / 5: 5
Code saisi : 1 3 2 5 5 
+ + + + + 
Voulez-vous quitter? (0 = non, 1 = oui) 1

Bonne chance

0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
12 janv. 2023 à 19:06

@mamiemando StatutModérateur

Ton code est très bien.

J'aurais juste, en ligne 65, retiré cette ligne "afficher_code_reponse(code_reponse, n);" de la fonction comparer_codes() et je l'aurais intégrée à la fonction lancer_partie() qui gère une partie et à laquelle on peut laisser la responsabilité de lancer l'affichage de code_reponse.

Ainsi, la fonction de comparaison est dissociée de celle gérant l'affichage.

Cela présente aussi l'avantage, pour comparer_codes(), de pouvoir être testée indépendamment, sans que les tests ne génèrent des affichages inutiles.

On peut alors écrire :

#include <string.h>
#include <assert.h>

int main(void) {
        {
        const size_t code_secret[] = { 1, 3, 2, 5, 5 };
        size_t code_saisi[]        = { 1, 2, 3, 4, 5 };
        char code_reponse[5];
        size_t num_corrects = comparer_codes(code_secret, code_saisi, code_reponse, 5);

        char code_reponse_attendu[5] = { '+', '~', '~', '-', '+' };
        assert(memcmp(code_reponse, code_reponse_attendu, 5) == 0
                        && "trouvés 1er et dernier, mal placés 2ème et 3ème et 4ème inexistant");
        assert(num_corrects == 2);
        }
        return 0;
}
0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749 > [Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024
13 janv. 2023 à 03:19

Tu as entièrement raison, c'est un oubli de couper coller. Merci pour ta remarque.

0