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 :

Premier programme en C, qu'en pensez-vous? [Débutant(e)]


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 93
    Par défaut Premier programme en C, qu'en pensez-vous?
    Bonjour,
    je debute dans la programmation en C. J'ai réalisé ce petit et trés simple mastermind, pour mettre en pratique le code. Cependant, j'aimerais avoir vos commentaires (et critiques) sur ce programme. J'ai notamment des doutes sur la fonction de saisie.
    Merci.

    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
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
     
    #include <stdio.h>
     
    #include <stdlib.h>
    #include <time.h>
     
     
    #define COUP_MAX    10      // Nombre de coup Maximal
    #define NB_CHIFFRE  5       // Nombre de chiffre dans le code
    #define BORNE_MAX   10      // Borne superieur du hasard
     
     
    // Different entrees pour le menu d'affichage
    #define RESULTAT    'r'
    #define GAGNE       'g'
    #define PERDU       'p'
    #define MENU        'm'
     
     
    // Fonctions externes
    int hasard ();
    void saisie (int ROW);
    void teste (int i, int ROW);
    void affichage(char mode, int ROW);
    void init_res ();
     
     
    // Variables externes
    int essai[COUP_MAX][NB_CHIFFRE];        // Tableau conteant les combinaisons essayees
    char res[COUP_MAX][NB_CHIFFRE];         // Tableau contenant les resultats de chaques combinaisons
    int code[NB_CHIFFRE];                   // Tableau contenant le code a decouvrir
    int bon;                                // Indique le nombre de chiffre correctement decode
     
     
    // Programme principal
    int main()
     
    {
        int ROW;                        // Indique la ligne en cours de traitement
        int coup;                       // Indique le nombre de coup joue
        int i;
     
     
        coup = 1;
        ROW = 0;
     
        // initialise le tableau RES
        init_res ();
     
        // Generation du code aleatoire
        srand(time(NULL));
        for (i = 0; i < NB_CHIFFRE; i++)
            code[i] = hasard();
     
        // Affichage du menu
        affichage(MENU,0);
     
        // Test de l'essai
        do {
            saisie(ROW);
            bon = 0;
            for (i = 0; i < NB_CHIFFRE; i++) {
                teste(i,ROW);
            }
            affichage(RESULTAT,ROW);
     
            ROW++;
            coup++;
        }
        while (bon != NB_CHIFFRE && coup <= COUP_MAX);
     
     
        if (bon == NB_CHIFFRE)
            affichage(GAGNE,0);
        else
            affichage(PERDU,0);
     
     
        return 0;
    }
     
     
     
    // FONCTION INITIALISATION DU TABLEAU RESULTAT
    void init_res () {
     
        int i,j;
     
        for (j = 0; j < COUP_MAX; j++)
            for (i = 0; i < NB_CHIFFRE; i++) {
                res[j][i] = '.';
            }
    }
     
     
    // FONCTION HASARD
    int hasard() {
     
        return rand() % BORNE_MAX;
     
    }
     
     
    // FONCTION DE SAISIE DE LA COMBINAISON
    void saisie (int ROW) {
     
     
        int i;
        char c;
        char chaine[20];
     
        printf("\nEntrez votre combinaison : ");
        for (i = 0; (c = getchar()) != EOF && c != '\n'; i++) {
            chaine[i] = c;
        }
     
        sscanf(chaine, "%d %d %d %d %d", &essai[ROW][0], &essai[ROW][1], &essai[ROW][2], &essai[ROW][3],&essai[ROW][4] );
     
    }
     
     
    // FONCTION TEST
    void teste (int i, int ROW) {
     
        int j;
     
        if (essai[ROW][i] == code[i]) {
            bon++;
            res[ROW][i] = '#';
        }
     
        else
            for(j = 0; j < NB_CHIFFRE; j++)
                if (essai[ROW][i] == code[j])
                    res[ROW][i] = '*';
    }
     
     
    // FONCTION AFFICHAGE
    void affichage(char mode, int ROW) {
     
        int i, j;
     
        switch (mode) {
            case 'r' :
                system("clear");
                for (j = 0; j <= ROW; j++) {
                    for (i = 0; i < NB_CHIFFRE; i++)
                        printf("%d ", essai[j][i]);
                    printf("\t");
                    for (i = 0; i < NB_CHIFFRE; i++)
                        printf("%c ", res[j][i]);
                    printf("\n");
                }
                break;
     
            case 'p' :
                printf("\nPERDU, le code correct etait :\t");
                for (i = 0; i < NB_CHIFFRE; i++)
                    printf("%d ", code[i]);
                printf("\n\n");
                break;
     
            case 'g' :
                printf("\nGAGNE, le code etait bien :\t");
                for (i = 0; i < NB_CHIFFRE; i++)
                    printf("%d ", code[i]);
                printf("\n\n");
                break;
     
            case 'm' :
                printf("\t*****************************\n");
                printf("\t*                           *\n");
                printf("\t*        MASTERMIND         *\n");
                printf("\t*                           *\n");
                printf("\t*****************************\n");
                printf("\n\n");
                printf(" - Utilisez les combinaisons dans le style : a b c d e puis 'entree'\n");
                printf(" - Les nombres possibles sont compris entre 0 et 9");
                printf("\n\n");
                break;
     
        }
    }

  2. #2
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par beware Voir le message
    Bonjour,
    je debute dans la programmation en C. J'ai réalisé ce petit et trés simple mastermind, pour mettre en pratique le code. Cependant, j'aimerais avoir vos commentaires (et critiques) sur ce programme. J'ai notamment des doutes sur la fonction de saisie.
    Les fonctions et variables ne sont pas 'externes'. Les fonctions (à part main()) sont 'privées, tant qu'il n'y a qu'un seul code source.

    Il est d'ailleurs inutile de leur définir de prototype séparé (sauf cas tordus peu recommandables). Il suffit de respecter le principe "définir avant d'utiliser".

    Quand aux variables, il n'y a pas de raison qu'elles soient globales. Des structures bien étudiées permettent d'éviter ça et de conserver des interfaces lisibles. En plus, cela favorise une meilleure organisation du code.

    Les fonctions sans paramètres doivent être définies avec (void) et non ().

    La fonction 'hasard()' est naïve. Il existe de meilleures formules...

    http://emmanuel-delahaye.developpez....d/inc/random.h

    Effectivement, la saisie est faible et fragile. Il vaut mieux utiliser fgets() , puis sscanf(), mais en s'assurant que les conversions se sont bien passées (tester le retour de sscanf(), lire la doc...)
    n'est pas portable et probablement inutile. Si on peut vraiment faire de la présentation, il y a des moyens plus radicaux... (PDCurses etc.)

    Sinon, c'est bien. Version solidifiée (sans globales, mais sans structures) :
    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
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
     
    #include <stdio.h>
     
    #include <stdlib.h>
    #include <time.h>
     
    /* Nombre de coup Maximal */
    #define COUP_MAX    10
    /* Nombre de chiffre dans le code */
    #define NB_CHIFFRE  5
    /* Borne superieur du hasard */
    #define BORNE_MAX   10
     
    /* Different entrees pour le menu d'affichage */
    #define RESULTAT    'r'
    #define GAGNE       'g'
    #define PERDU       'p'
    #define MENU        'm'
     
    /* FONCTION INITIALISATION DU TABLEAU RESULTAT */
    static void init_res (char res[COUP_MAX][NB_CHIFFRE])
    {
       int j;
     
       for (j = 0; j < COUP_MAX; j++)
       {
          int i;
          for (i = 0; i < NB_CHIFFRE; i++)
          {
             res[j][i] = '.';
          }
       }
    }
     
    /* FONCTION HASARD */
    static int hasard (void)
    {
       return rand () % BORNE_MAX;
    }
     
    /* FONCTION DE SAISIE DE LA COMBINAISON */
    static void saisie (int ROW, int essai[COUP_MAX][NB_CHIFFRE])
    {
       int const N=5;
       int n;
       do
       {
          char chaine[20];
     
          printf ("Entrez votre combinaison : ");
          fgets (chaine, sizeof chaine, stdin);
     
          n = sscanf (chaine, "%d %d %d %d %d", &essai[ROW][0], &essai[ROW][1],
                      &essai[ROW][2], &essai[ROW][3], &essai[ROW][4]);
          if (n != N)
          {
             puts ("erreur");
          }
       }
       while (n != N);
    }
     
    /* FONCTION TEST */
    static void teste (int i, int ROW, int *p_bon, char res[COUP_MAX][NB_CHIFFRE],
                       int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE])
    {
       int j;
     
       if (essai[ROW][i] == code[i])
       {
          (*p_bon)++;
          res[ROW][i] = '#';
       }
     
       else
       {
          for (j = 0; j < NB_CHIFFRE; j++)
          {
             if (essai[ROW][i] == code[j])
             {
                res[ROW][i] = '*';
             }
          }
       }
     
    }
     
    /* FONCTION AFFICHAGE */
    static void affichage (char mode, int ROW, char res[COUP_MAX][NB_CHIFFRE],
                           int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE])
    {
     
       int i, j;
     
       switch (mode)
       {
       case 'r':
          for (j = 0; j <= ROW; j++)
          {
             for (i = 0; i < NB_CHIFFRE; i++)
                printf ("%d ", essai[j][i]);
             printf ("\t");
             for (i = 0; i < NB_CHIFFRE; i++)
                printf ("%c ", res[j][i]);
             printf ("\n");
          }
          break;
     
       case 'p':
          printf ("\nPERDU, le code correct etait :\t");
          for (i = 0; i < NB_CHIFFRE; i++)
             printf ("%d ", code[i]);
          printf ("\n\n");
          break;
     
       case 'g':
          printf ("\nGAGNE, le code etait bien :\t");
          for (i = 0; i < NB_CHIFFRE; i++)
             printf ("%d ", code[i]);
          printf ("\n\n");
          break;
     
       case 'm':
          printf ("\t*****************************\n");
          printf ("\t*                           *\n");
          printf ("\t*        MASTERMIND         *\n");
          printf ("\t*                           *\n");
          printf ("\t*****************************\n");
          printf ("\n\n");
          printf
             (" - Utilisez les combinaisons dans le style : a b c d e puis 'entree'\n");
          printf (" - Les nombres possibles sont compris entre 0 et 9");
          printf ("\n\n");
          break;
     
       }
    }
     
    /* Programme principal */
    int main (void)
    {
    /* Indique la ligne en cours de traitement */
       int ROW;
    /* Indique le nombre de coup joue */
       int coup;
       int i;
       int bon;
       coup = 1;
       ROW = 0;
    /* Tableau contenant les resultats de chaques combinaisons */
       char res[COUP_MAX][NB_CHIFFRE];
    /* Tableau contenant le code a decouvrir */
       int code[NB_CHIFFRE]={0};
    /* Tableau conteant les combinaisons essayees */
       int essai[COUP_MAX][NB_CHIFFRE]={{0}};
     
    /* initialise le tableau RES */
     
       init_res (res);
     
    /* Generation du code aleatoire */
     
       srand (time (NULL));
       for (i = 0; i < NB_CHIFFRE; i++)
       {
          code[i] = hasard ();
       }
     
    /* Affichage du menu */
     
       affichage (MENU, 0, res, code, essai);
     
    /* Test de l'essai */
     
       do
       {
          saisie (ROW, essai);
          bon = 0;
          for (i = 0; i < NB_CHIFFRE; i++)
          {
             teste (i, ROW, &bon, res, code, essai);
          }
          affichage (RESULTAT, ROW, res, code, essai);
     
          ROW++;
          coup++;
       }
       while (bon != NB_CHIFFRE && coup <= COUP_MAX);
     
       if (bon == NB_CHIFFRE)
          affichage (GAGNE, 0, res, code, essai);
       else
          affichage (PERDU, 0, res, code, essai);
     
       return 0;
    }
    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
     
            *****************************
            *                           *
            *        MASTERMIND         *
            *                           *
            *****************************
     
     
     - Utilisez les combinaisons dans le style : a b c d e puis 'entree'
     - Les nombres possibles sont compris entre 0 et 9
     
    Entrez votre combinaison : 0 0 0 0 0
    0 0 0 0 0       . . . . .
    Entrez votre combinaison : 1 1 1 1 1
    0 0 0 0 0       . . . . .
    1 1 1 1 1       # * # * *
    Entrez votre combinaison : 1 2 1 2 2
    0 0 0 0 0       . . . . .
    1 1 1 1 1       # * # * *
    1 2 1 2 2       # . # . .
    Entrez votre combinaison : 1 3 1 3 3
    0 0 0 0 0       . . . . .
    1 1 1 1 1       # * # * *
    1 2 1 2 2       # . # . .
    1 3 1 3 3       # . # . .
    Entrez votre combinaison : 1 4 1 4 4
    0 0 0 0 0       . . . . .
    1 1 1 1 1       # * # * *
    1 2 1 2 2       # . # . .
    1 3 1 3 3       # . # . .
    1 4 1 4 4       # # # * *
    Entrez votre combinaison : 1 4 1 5 5
    0 0 0 0 0       . . . . .
    1 1 1 1 1       # * # * *
    1 2 1 2 2       # . # . .
    1 3 1 3 3       # . # . .
    1 4 1 4 4       # # # * *
    1 4 1 5 5       # # # . .
    Entrez votre combinaison : 1 4 1 6 6
    0 0 0 0 0       . . . . .
    1 1 1 1 1       # * # * *
    1 2 1 2 2       # . # . .
    1 3 1 3 3       # . # . .
    1 4 1 4 4       # # # * *
    1 4 1 5 5       # # # . .
    1 4 1 6 6       # # # . .
    Entrez votre combinaison : 1 4 1 7 7
    0 0 0 0 0       . . . . .
    1 1 1 1 1       # * # * *
    1 2 1 2 2       # . # . .
    1 3 1 3 3       # . # . .
    1 4 1 4 4       # # # * *
    1 4 1 5 5       # # # . .
    1 4 1 6 6       # # # . .
    1 4 1 7 7       # # # # *
    Entrez votre combinaison : 1 4 1 7 8
    0 0 0 0 0       . . . . .
    1 1 1 1 1       # * # * *
    1 2 1 2 2       # . # . .
    1 3 1 3 3       # . # . .
    1 4 1 4 4       # # # * *
    1 4 1 5 5       # # # . .
    1 4 1 6 6       # # # . .
    1 4 1 7 7       # # # # *
    1 4 1 7 8       # # # # #
     
    GAGNE, le code etait bien :     1 4 1 7 8
     
     
    Press ENTER to continue.

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 875
    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 875
    Billets dans le blog
    1
    Par défaut
    Je ne connais pas "en détail" les règles du Mastermind donc ma question peut paraître stupide
    Si la combinaison est "1 4 1 7 8" et qu'on rentre "1 4 1 4 4" pourquoi les deux derniers "4" sont marqués "*" ? Je sais bien qu'ils ne sont pas à la bonne place mais étant donné que le "4" qui est à la bonne place a été marqué "correct" pourquoi les deux autres "4" sont aussi indiqués comme "présents" ???
    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]

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 93
    Par défaut
    Citation Envoyé par Emmanuel Delahaye Voir le message
    Les fonctions et variables ne sont pas 'externes'. Les fonctions (à part main()) sont 'privées, tant qu'il n'y a qu'un seul code source.
    Il est d'ailleurs inutile de leur définir de prototype séparé (sauf cas tordus peu recommandables). Il suffit de respecter le principe "définir avant d'utiliser".
    Quand aux variables, il n'y a pas de raison qu'elles soient globales. Des structures bien étudiées permettent d'éviter ça et de conserver des interfaces lisibles. En plus, cela favorise une meilleure
    organisation du code.
    En fait, c'est une maladresse de ma part. J'avais fait plusieurs fichiers sources au debut, avant de tout mettre dans le même. C'est pour ca que j'avais les variables externes. De plus, si je declare
    les fonctions de cette maniere, c'est simplement car je l'ai vu faire dans le bouquin que j'utilise : le Kernighan & Ritchie (2e Ed). Et donc je reproduis ce schema.


    Citation Envoyé par Emmanuel Delahaye Voir le message
    Les fonctions sans paramètres doivent être définies avec (void) et non ().
    Ok, c'est noté.


    Citation Envoyé par Emmanuel Delahaye Voir le message
    Effectivement, la saisie est faible et fragile. Il vaut mieux utiliser fgets() , puis sscanf(), mais en s'assurant que les conversions se sont bien passées (tester le retour de sscanf(), lire la
    doc...)
    n'est pas portable et probablement inutile. Si on peut vraiment faire de la présentation, il y a des moyens plus radicaux... (PDCurses etc.)
    D'accord. Je connaissais pas fgets. C'est donc plus sur de l'utiliser, alors allons-y. Pour ce qui est de la mise en forme, je veut pas pousser trop loin, c'est pour ca que j'utilise les "clear".


    J'ai deux autres questions :

    1 -
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    static void saisie (int ROW, int essai[COUP_MAX][NB_CHIFFRE]) {
    Pourquoi indiquer "static" devant chaque fonction?


    2 -
    Est-ce qu'il y a une difference (ou une importance) a mettre les fonctions aprés (ou avant) la fonction 'main'?


    Citation Envoyé par Sve@r Voir le message
    Je ne connais pas "en détail" les règles du Mastermind donc ma question peut paraître stupide
    Si la combinaison est "1 4 1 7 8" et qu'on rentre "1 4 1 4 4" pourquoi les deux derniers "4" sont marqués "*" ? Je sais bien qu'ils ne sont pas à la bonne place mais étant donné que le "4" qui est à
    la bonne place a été marqué "correct" pourquoi les deux autres "4" sont aussi indiqués comme "présents" ???
    Euh, faut que je me replonge dans les regles. Merci pour la remarque.

  5. #5
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    362
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 362
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Je ne connais pas "en détail" les règles du Mastermind donc ma question peut paraître stupide
    Si la combinaison est "1 4 1 7 8" et qu'on rentre "1 4 1 4 4" pourquoi les deux derniers "4" sont marqués "*" ? Je sais bien qu'ils ne sont pas à la bonne place mais étant donné que le "4" qui est à la bonne place a été marqué "correct" pourquoi les deux autres "4" sont aussi indiqués comme "présents" ???
    Oui, je confirme, le principe du Mastermind est de ne pas compter plusieurs fois la même chose :
    - 1 lettre dans le mot secret présente plusieurs fois dans le mot proposé : 1 bien placé si l'une des lettre est bien placée, 1 mal placé sinon.
    - 1 lettre proposée présente plusieurs fois dans le mot secret : 1 bien placé si la lettre est placée comme l'une de celle du mot secret, 1 mal placé sinon.

    C'est ce qui fait que l'algo est assez intéressant pour de l'initiation à la programmation...

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 93
    Par défaut
    Effectivement, vous avez raison. J'avais mal interpreté les régles du jeu. J'ai donc changé un poil la définition des testes, pour mieux y coller.

    J'ai également tenu compte des conseils d'Emmanuel.

    Voici donc la nouvelle version :

    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
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
     
    #include <stdio.h>
     
    #include <stdlib.h>
    #include <time.h>
     
     
    #define COUP_MAX    12      // Nombre de coup Maximal
    #define NB_CHIFFRE  4       // Nombre de chiffre dans le code
    #define BORNE_MAX   10      // Borne superieur du hasard
     
     
    // Different entrees pour le menu d'affichage
    #define RESULTAT    'r'
    #define GAGNE       'g'
    #define PERDU       'p'
    #define MENU        'm'
     
     
    // Fonctions
    void init_res (char res[COUP_MAX][NB_CHIFFRE]);
    int hasard(void);
    void saisie (int ROW, int essai[COUP_MAX][NB_CHIFFRE]);
    void teste (int ROW, int *p_bon,char res[COUP_MAX][NB_CHIFFRE], int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE]);
    void affichage(char mode, int ROW, char res[COUP_MAX][NB_CHIFFRE], int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE]);
     
     
     
    // Programme principal
    int main(void)
     
    {
        int essai[COUP_MAX][NB_CHIFFRE] = {{0}};        // Tableau conteant les combinaisons essayees
        char res[COUP_MAX][NB_CHIFFRE];         // Tableau contenant les resultats de chaques combinaisons
        int code[NB_CHIFFRE] = {0};                   // Tableau contenant le code a decouvrir
     
        int bon;
        int ROW;                        // Indique la ligne en cours de traitement
        int coup;                       // Indique le nombre de coup joue
        int i;
        int diese;
        int etoile;
     
     
        coup = 1;
        ROW = 0;
        diese = 0;
        etoile = 0;
     
     
        // initialise le tableau RES
        init_res (res);
     
        // Generation du code aleatoire
        srand(time(NULL));
        for (i = 0; i < NB_CHIFFRE; i++)
            code[i] = hasard();
     
     
     
     
        // Affichage du menu
        affichage(MENU,0,res,code,essai);
     
        // Test de l'essai
        do {
            saisie(ROW,essai);
            bon = 0;
            teste(ROW,&bon,res,code,essai);
            affichage(RESULTAT,ROW,res,code,essai);
            ROW++;
            coup++;
        }
        while (bon != NB_CHIFFRE && coup <= COUP_MAX);
     
     
        if (bon == NB_CHIFFRE)
            affichage(GAGNE,0,res,code,essai);
        else
            affichage(PERDU,0,res,code,essai);
     
     
        return 0;
    }
     
     
     
    // FONCTION INITIALISATION DU TABLEAU RESULTAT
    static void init_res (char res[COUP_MAX][NB_CHIFFRE]) {
     
        int j;
     
        for (j = 0; j < COUP_MAX; j++) {
            int i;
            for (i = 0; i < NB_CHIFFRE; i++)
                res[j][i] = '.';
        }
     
    }
     
     
    // FONCTION HASARD
    static int hasard(void) {
        return (int)(rand()/(double)RAND_MAX * (BORNE_MAX));
        //return rand() % BORNE_MAX;
     
    }
     
     
    // FONCTION DE SAISIE DE LA COMBINAISON
    static void saisie (int ROW, int essai[COUP_MAX][NB_CHIFFRE]) {
     
        int n;
     
        do {
            char chaine[20];
            printf("\nEntrez votre combinaison : ");
            fgets(chaine, sizeof chaine, stdin);
     
            n = sscanf(chaine, "%d %d %d %d %d", &essai[ROW][0], &essai[ROW][1], &essai[ROW][2], &essai[ROW][3],&essai[ROW][4] );
     
            if (n != NB_CHIFFRE)
                puts("ERREUR");
        }
        while (n != NB_CHIFFRE);
     
    }
     
     
    // FONCTION TEST
    static void teste (int ROW, int *p_bon, char res[COUP_MAX][NB_CHIFFRE], int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE]) {
     
        int i,j,k;
     
        k = 0;
     
        /* boucle pour les valeurs presentes et bien placees*/
        for (i = 0; i < NB_CHIFFRE; i++)
            if (essai[ROW][i] == code[i]) {
                res[ROW][k++] = '#';
                (*p_bon)++;
            }
     
        /* boucle pour les valeurs presentes mais mal placees */
        for (i = 0; i < NB_CHIFFRE; i++)
            for (j = 0; j < NB_CHIFFRE; j++)
                if (essai[ROW][i] == code[j] && j != i)
                    res[ROW][k++] = '*';
     
    }
     
     
    // FONCTION AFFICHAGE
    static void affichage(char mode, int ROW, char res[COUP_MAX][NB_CHIFFRE], int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE]) {
     
        int i, j;
     
        switch (mode) {
            case 'r' :
                 for (j = 0; j <= ROW; j++) {
                    for (i = 0; i < NB_CHIFFRE; i++)
                        printf("%d ", essai[j][i]);
                    printf("\t");
                    for (i = 0; i < NB_CHIFFRE; i++)
                        printf("%c ", res[j][i]);
                    printf("\n");
                }
                break;
     
            case 'p' :
                printf("\nPERDU, le code correct etait :\t");
                for (i = 0; i < NB_CHIFFRE; i++)
                    printf("%d ", code[i]);
                printf("\n\n");
                break;
     
            case 'g' :
                printf("\nGAGNE, le code etait bien :\t");
                for (i = 0; i < NB_CHIFFRE; i++)
                    printf("%d ", code[i]);
                printf("\n\n");
                break;
     
            case 'm' :
                printf("\t*****************************\n");
                printf("\t*                           *\n");
                printf("\t*        MASTERMIND         *\n");
                printf("\t*                           *\n");
                printf("\t*****************************\n");
                printf("\n\n");
                printf(" - Utilisez les combinaisons dans le style : a b c d puis 'entree'\n");
                printf(" - Les nombres possibles sont compris entre 0 et 9");
                printf("\n\n");
                break;
     
        }
    }

  7. #7
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Citation Envoyé par beware Voir le message
    1 -
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    static void saisie (int ROW, int essai[COUP_MAX][NB_CHIFFRE]) {
    Pourquoi indiquer "static" devant chaque fonction?
    Pour indiquer que ces fonctions sont privees a l'unite de compilation (un fichier .c, pour simplifier) en cours. Lorsqu'on divise un projet en plusieurs unites de compilations, certaines fonctions ne sont pas destinees a etre vues par les autres unites (parce qu'elles ne sont appellees qu'en interne). Pour s'assurer de cela, on qualifie les fonctions de static.

    2 -
    Est-ce qu'il y a une difference (ou une importance) a mettre les fonctions aprés (ou avant) la fonction 'main'?
    Ce qui importe, c'est que le prototype de chaque fonction est connu au moment ou l'on utilise cette fonction. On peut:
    • - lister tous les prototypes ou inclure les fichier entete qui correspondent, puis donner le code ailleurs (plus loin dans le fichier, ou dans un autre fichier)
    • - donner le prototype et le code en meme temps.

    En general, on utilise la premiere methode pour les fonctions publiques, la deuxieme pour les fonctions privees (static donc). Mais ce n'est obligatoire, c'est plutot conventionnel.

  8. #8
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par beware Voir le message
    1 -
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    static void saisie (int ROW, int essai[COUP_MAX][NB_CHIFFRE]) {
    Pourquoi indiquer "static" devant chaque fonction?
    http://emmanuel-delahaye.developpez....tes.htm#static
    2 -
    Est-ce qu'il y a une difference (ou une importance) a mettre les fonctions aprés (ou avant) la fonction 'main'?
    Les mettre avant permet de respecter le principe simple "définir avant d'utiliser" qui inclue le principe obligatoire "déclarer avant d'utiliser" et permet d'éviter des déclarations inutiles.

    Il n'y a rien d'obligatoire, c'est juste parce que moins on écrit de code, moins on a de chances de faire une erreur... (Autre principe de programmation bien connu...)

  9. #9
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    362
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 362
    Par défaut
    J'ai regardé rapidement mais je ne crois pas que ton nouveau "teste" réponde à la règle du jeu.

    Essaye de faire passer : mot secret = 10235, mot proposé = 21214, tu vas restituer : **#*_ au lieu de : bien placées = 1, mal placées = 1 (car au Mastermind, on ne restitue que le nombre de biens placées / mal placées).

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 93
    Par défaut
    Oui, tu as parfaitement raison. Je ne respectais pas vraiment la règle du jeu.
    J'ai modifié le programme, pour prendre en compte cette règle.

    En essayant tes combinaisons, j'obtiens bien, 1 # et 1 * (respectivement 1 bien placé et 1 mal placé).

    Bon, je suis pas sur que la méthode que j'ai employé soit la plus simple, ni forcement la meilleur. J'ai en effet crée un tableau des valeurs possibles (soit 0 à 9) avec pour chaque un état IN ou OUT (1 ou 0) qui me permet de contrôler que chaque valeur n'est traitée qu'une fois.

    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
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
     
    #define COUP_MAX    12      // Nombre de coup Maximal
    #define NB_CHIFFRE  5       // Nombre de chiffre dans le code
    #define BORNE_MAX   10      // Borne superieur du hasard
     
     
    // Different entrees pour le menu d'affichage
    #define RESULTAT    'r'
    #define GAGNE       'g'
    #define PERDU       'p'
    #define MENU        'm'
     
    #define IN  1
     
     
     
    // Fonctions externes
    static void init_res (char res[COUP_MAX][NB_CHIFFRE]);
    static void raz_chiffre (int chiffre[2][10]);
    static int hasard(void);
    static void saisie (int ROW, int essai[COUP_MAX][NB_CHIFFRE]);
    static void teste (int ROW, int *p_bon,char res[COUP_MAX][NB_CHIFFRE], int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE], int chiffre[2][10]);
    static void affichage(char mode, int ROW, char res[COUP_MAX][NB_CHIFFRE], int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE]);
     
     
     
    // Programme principal
    int main(void)
    {
        int essai[COUP_MAX][NB_CHIFFRE] = {{0}};            // Tableau conteant les combinaisons essayees
        char res[COUP_MAX][NB_CHIFFRE];                     // Tableau contenant les resultats de chaques combinaisons
        int code[NB_CHIFFRE] = {0};                         // Tableau contenant le code a decouvrir
        int chiffre[2][10] = {{0,1,2,3,4,5,6,7,8,9},{0}};   // Tableau de controle des valeurs jouees
     
        int bon;
        int ROW;                        // Indique la ligne en cours de traitement
        int coup;                       // Indique le nombre de coup joue
        int i;
     
        coup = 1;
        ROW = 0;
     
        // initialise le tableau RES & CODE
        init_res (res);
     
        // Generation du code aleatoire
        srand(time(NULL));
        for (i = 0; i < NB_CHIFFRE; i++) {
            code[i] = hasard();
            printf("%d ", code[i]);
        }
     
        // Affichage du menu
        affichage(MENU,0,res,code,essai);
     
        // Test de l'essai
        do {
            saisie(ROW,essai);
            bon = 0;
            teste(ROW,&bon,res,code,essai,chiffre);     // On teste le code entré
            affichage(RESULTAT,ROW,res,code,essai);     // On affiche le code essaye et son resultat
            raz_chiffre(chiffre);                       // On reinitialise le tableau de controle
            ROW++;
            coup++;
        }
        while (bon != NB_CHIFFRE && coup <= COUP_MAX);
     
     
        if (bon == NB_CHIFFRE)
            affichage(GAGNE,0,res,code,essai);
        else
            affichage(PERDU,0,res,code,essai);
     
     
        return 0;
    }
     
     
     
    // FONCTION INITIALISATION DU TABLEAU RESULTAT
    static void init_res (char res[COUP_MAX][NB_CHIFFRE]) {
     
        int j;
     
        for (j = 0; j < COUP_MAX; j++) {
            int i;
            for (i = 0; i < NB_CHIFFRE; i++)
                res[j][i] = '.';
        }
    }
     
    // FONCTION REMISE A ZERO DU CODE TEMP
    static void raz_chiffre (int chiffre[2][10]) {
     
        int i;
        for (i = 0; i < 10; i++)
            chiffre[1][i] = 0;
    }
     
     
    // FONCTION HASARD
    static int hasard(void) {
        return (int)(rand()/(double)RAND_MAX * (BORNE_MAX));
    }
     
     
    // FONCTION DE SAISIE DE LA COMBINAISON
    static void saisie (int ROW, int essai[COUP_MAX][NB_CHIFFRE]) {
     
        int n;
     
        do {
            char chaine[20];
            printf("\nEntrez votre combinaison : ");
            fgets(chaine, sizeof chaine, stdin);
     
            n = sscanf(chaine, "%d %d %d %d %d", &essai[ROW][0], &essai[ROW][1], &essai[ROW][2], &essai[ROW][3],&essai[ROW][4] );
     
            if (n != NB_CHIFFRE)
                puts("ERREUR");
        }
        while (n != NB_CHIFFRE);
     
    }
     
     
    // FONCTION TEST
    static void teste (int ROW, int *p_bon, char res[COUP_MAX][NB_CHIFFRE], int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE], int chiffre[2][10]) {
     
        int i,j,k;
     
        k = 0;
     
        /* boucle pour les valeurs presentes et bien placees*/
        for (i = 0; i < NB_CHIFFRE; i++)
            if (essai[ROW][i] == code[i]) {
                res[ROW][k++] = '#';
                chiffre[1][essai[ROW][i]] = IN;
                (*p_bon)++;
            }
     
     
        /* boucle pour les valeurs presentes mais mal placees */
        for (i = 0; i < NB_CHIFFRE; i++)
            for (j = 0; j < NB_CHIFFRE; j++)
                if (essai[ROW][i] == code[j] && j != i && chiffre[1][essai[ROW][i]] != IN) {
                    res[ROW][k++] = '*';
                    chiffre[1][essai[ROW][i]] = IN;
                }
    }
     
     
    // FONCTION AFFICHAGE
    static void affichage(char mode, int ROW, char res[COUP_MAX][NB_CHIFFRE], int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE]) {
     
        int i, j;
     
        switch (mode) {
            case 'r' :
                 for (j = 0; j <= ROW; j++) {
                    for (i = 0; i < NB_CHIFFRE; i++)
                        printf("%d ", essai[j][i]);
                    printf("\t");
                    for (i = 0; i < NB_CHIFFRE; i++)
                        printf("%c ", res[j][i]);
                    printf("\n");
                }
                break;
     
            case 'p' :
                printf("\nPERDU, le code correct etait :\t");
                for (i = 0; i < NB_CHIFFRE; i++)
                    printf("%d ", code[i]);
                printf("\n\n");
                break;
     
            case 'g' :
                printf("\nGAGNE, le code etait bien :\t");
                for (i = 0; i < NB_CHIFFRE; i++)
                    printf("%d ", code[i]);
                printf("\n\n");
                break;
     
            case 'm' :
                printf("\t*****************************\n");
                printf("\t*                           *\n");
                printf("\t*        MASTERMIND         *\n");
                printf("\t*                           *\n");
                printf("\t*****************************\n");
                printf("\n\n");
                printf(" - Utilisez les combinaisons dans le style : a b c d e puis 'entree'\n");
                printf(" - Les nombres possibles sont compris entre 0 et 9");
                printf("\n\n");
                break;
     
        }
    }

  11. #11
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    362
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 362
    Par défaut
    Citation Envoyé par beware Voir le message
    Bon, je suis pas sur que la méthode que j'ai employé soit la plus simple, ni forcement la meilleur. J'ai en effet crée un tableau des valeurs possibles (soit 0 à 9) avec pour chaque un état IN ou OUT (1 ou 0) qui me permet de contrôler que chaque valeur n'est traitée qu'une fois.
    Ta méthode a plusieurs inconvénients :
    - elle ne marche pas dans tous les cas,
    - elle consomme plus de ressources que nécessaire.

    Teste-la avec ce cas-là :
    code = 11122
    essai = 22211

    En fait, tu as besoin de beaucoup moins d'informations. Si tu remarques qu'en C, comme il a été dit plus haut, le passage de paramètres se fait par valeurs, et que la fonction "teste" reçoit "essai" et "code" en entrée, tu peux tirer profit du fait que, une fois qu'une lettre a été "consommée" comme bien / mal placée, tu peux faire en sorte de ne plus l'utiliser (je te laisse chercher un peu ).

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 93
    Par défaut
    Citation Envoyé par fremen167 Voir le message
    Ta méthode a plusieurs inconvénients :
    - elle ne marche pas dans tous les cas,
    - elle consomme plus de ressources que nécessaire.

    Teste-la avec ce cas-là :
    code = 11122
    essai = 22211

    En fait, tu as besoin de beaucoup moins d'informations. Si tu remarques qu'en C, comme il a été dit plus haut, le passage de paramètres se fait par valeurs, et que la fonction "teste" reçoit "essai" et "code" en entrée, tu peux tirer profit du fait que, une fois qu'une lettre a été "consommée" comme bien / mal placée, tu peux faire en sorte de ne plus l'utiliser (je te laisse chercher un peu ).
    C'est vrai que ma méthode utilise un tableau 2 dimensions en plus. Et d'après ce que tu me dis, il doit y avoir un moyen d'améliorer ca. Je vais y réfléchir.

    Par contre, j'ai essaye ton exemple, et j'obtiens une bonne réponse :

    [CODE
    ]Entrez votre combinaison : 2 2 2 1 1
    2 2 2 1 1 * * . . . [/CODE]

    Soit deux éléments présent mais mal placés. Si j'ai bien compris les règles du jeu, on doit bien obtenir ça.

  13. #13
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    362
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 362
    Par défaut
    Citation Envoyé par beware Voir le message
    Par contre, j'ai essaye ton exemple, et j'obtiens une bonne réponse :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Entrez votre combinaison : 2 2 2 1 1
    2 2 2 1 1       * * . . .
    Soit deux éléments présent mais mal placés. Si j'ai bien compris les règles du jeu, on doit bien obtenir ça.
    Non, on doit obtenir 4 mal placées (2 '1' et 2 '2')

  14. #14
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 93
    Par défaut
    Bon, au lieu de bricoler un peu a droite a gauche, il faut que je reprenne l'algo pour mieux coller aux regles.

  15. #15
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par beware Voir le message
    Bon, au lieu de bricoler un peu a droite a gauche, il faut que je reprenne l'algo pour mieux coller aux regles.
    Sage décision connue sous le nom de refactoring.

  16. #16
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 93
    Par défaut
    Bon, j'ai revu un peu le programme. Notamment pour respecter au mieux les règles du mastermind. J'espère que ca correspond désormais.

    J'ai également modifié la fonction aléatoire pour de plus avoir de chiffre redondant. C'est pas obligatoire dans le mastermind mais pour les tests c'est plus pratique.

    Bon alors voici le nouveau code :

    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
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
     
    #define COUP_MAX    12      // Nombre de coup Maximal
    #define NB_CHIFFRE  5       // Nombre de chiffre dans le code
    #define BORNE_MAX   10      // Borne superieur du hasard
     
     
    // Different entrees pour le menu d'affichage
    #define RESULTAT    'r'
    #define GAGNE       'g'
    #define PERDU       'p'
    #define MENU        'm'
     
    #define OK 1
     
     
     
     
    // Fonctions externes
    static void init_res (char res[COUP_MAX][NB_CHIFFRE]);
    static void hasard(int code[NB_CHIFFRE]);
    static void saisie (int ROW, int essai[COUP_MAX][NB_CHIFFRE]);
    static void teste (int ROW, int *p_bon,char res[COUP_MAX][NB_CHIFFRE], int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE]);
    static void affichage(char mode, int ROW,char res[COUP_MAX][NB_CHIFFRE], int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE]);
     
     
     
    // Programme principal
    int main(void)
    {
        int essai[COUP_MAX][NB_CHIFFRE] = {{0}};            // Tableau conteant les combinaisons essayees
        char res[COUP_MAX][NB_CHIFFRE];                     // Tableau contenant les resultats de chaques combinaisons
        int code[NB_CHIFFRE] = {0};                         // Tableau contenant le code a decouvrir
     
        int bon;
        int ROW;                        // Indique la ligne en cours de traitement
        int coup;                       // Indique le nombre de coup joue
     
        coup = 1;
        ROW = 0;
     
        // initialise le tableau RES
        init_res (res);
     
        // Generation du code aleatoire
        srand(time(NULL));
        hasard(code);
     
        // Affichage du menu
        affichage(MENU,0,res,code,essai);
     
        // Test de l'essai
        do {
            saisie(ROW,essai);
            bon = 0;
            teste(ROW,&bon,res,code,essai);             // On teste le code entré
            affichage(RESULTAT,ROW,res,code,essai);     // On affiche le code essaye et son resultat
            ROW++;
            coup++;
        }
        while (bon != NB_CHIFFRE && coup <= COUP_MAX);
     
     
        if (bon == NB_CHIFFRE)
            affichage(GAGNE,0,res,code,essai);
        else
            affichage(PERDU,0,res,code,essai);
     
     
        return 0;
    }
     
     
     
    // FONCTION INITIALISATION DU TABLEAU RESULTAT
    static void init_res (char res[COUP_MAX][NB_CHIFFRE]) {
     
        int j;
     
        for (j = 0; j < COUP_MAX; j++) {
            int i;
            for (i = 0; i < NB_CHIFFRE; i++)
                res[j][i] = '.';
        }
    }
     
     
     
    // FONCTION HASARD
    static void hasard(int code[NB_CHIFFRE]) {
        int tmp, i, pos;
     
        pos = 0;
     
        code[pos++] = (int)(rand()/(double)RAND_MAX * (BORNE_MAX));
     
        while (pos < NB_CHIFFRE){
            tmp = (int)(rand()/(double)RAND_MAX * (BORNE_MAX));
     
        /* verifier que la valeur tiree n'est pas deja presente */
            for (i = 0; i < pos; i++) {
                while (tmp == code[i]) {
                    tmp = (int)(rand()/(double)RAND_MAX * (BORNE_MAX));
                }
            }
            code[pos++] = tmp;
        }
    }
     
     
     
     
    // FONCTION DE SAISIE DE LA COMBINAISON
    static void saisie (int ROW, int essai[COUP_MAX][NB_CHIFFRE]) {
     
        int n;
     
        do {
            char chaine[20];
            printf("\nEntrez votre combinaison : ");
            fgets(chaine, sizeof chaine, stdin);
     
            n = sscanf(chaine, "%d %d %d %d %d", &essai[ROW][0], &essai[ROW][1], &essai[ROW][2], &essai[ROW][3],&essai[ROW][4] );
     
            if (n != NB_CHIFFRE)
                puts("ERREUR");
        }
        while (n != NB_CHIFFRE);
     
    }
     
     
    // FONCTION TEST
    static void teste (int ROW, int *p_bon, char res[COUP_MAX][NB_CHIFFRE], int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE]) {
     
        int i;
        int work[NB_CHIFFRE] = {0};
     
     
        /* chercher d'abord les dieses */
        for (i = 0; i < NB_CHIFFRE; i++)
            if (code[i] == essai[ROW][i]){
                res[ROW][i] = '#';
                work[i] = OK;
                (*p_bon)++;
            }
     
        /* cherche les etoiles */
        for (i = 0; i < NB_CHIFFRE; i++) {
            int j;
            int done = 0;
     
            for (j = 0; j < NB_CHIFFRE && done != 1; j++)
                    if (j != i && code[j] == essai[ROW][i] && work[j] != OK){
                        res[ROW][i] = '*';
                        work[j] = OK;
                        done++;
                    }
                }
    }
     
     
     
    // FONCTION AFFICHAGE
    static void affichage(char mode, int ROW, char res[COUP_MAX][NB_CHIFFRE], int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE]) {
     
        int i, j, k;
     
        switch (mode) {
            case 'r' :
                for (j = 0; j <= ROW; j++) {
                    k = 0;
     
                    for (i = 0; i < NB_CHIFFRE; i++)
                        printf("%d ",essai[j][i]);
     
                    printf("\t");
     
                     // DIESE
                     for (i = 0; i < NB_CHIFFRE; i++)
                        if (res[j][i] == '#') {
                            printf("%c ", res[j][i]);
                            k++;
                        }
     
                    // ETOILE
                    for (i = 0; i < NB_CHIFFRE; i++)
                        if (res[j][i] == '*') {
                            printf("%c ", res[j][i]);
                            k++;
                        }
     
                    // AUTRES
                    for (; k < NB_CHIFFRE; k++)
                        printf(". ");
     
                    printf("\n");
                }
                break;
     
            case 'p' :
                printf("\nPERDU, le code correct etait :\t");
                for (i = 0; i < NB_CHIFFRE; i++)
                    printf("%d ", code[i]);
                printf("\n\n");
                break;
     
            case 'g' :
                printf("\nGAGNE, le code etait bien :\t");
                for (i = 0; i < NB_CHIFFRE; i++)
                    printf("%d ", code[i]);
                printf("\n\n");
                break;
     
            case 'm' :
                printf("\t*****************************\n");
                printf("\t*                           *\n");
                printf("\t*        MASTERMIND         *\n");
                printf("\t*                           *\n");
                printf("\t*****************************\n");
                printf("\n\n");
                printf(" - Utilisez les combinaisons dans le style : a b c d e puis 'entree'\n");
                printf(" - Les nombres possibles sont compris entre 0 et 9");
                printf("\n\n");
                break;
     
        }
    }

  17. #17
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    362
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 362
    Par défaut
    Citation Envoyé par beware Voir le message
    J'ai également modifié la fonction aléatoire pour de plus avoir de chiffre redondant. C'est pas obligatoire dans le mastermind mais pour les tests c'est plus pratique.
    Ce n'est pas une bonne idée car ce sont justement les cas difficiles à traiter...

    Citation Envoyé par beware Voir le message
    J'espère que ca correspond désormais.
    Regarde ce que j'ai obtenu en forçant code à 11122 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Entrez votre combinaison : 2 2 1 1 1
    2 2 1 1 1       * * * * .
    Tu devrais prendre quelque cas limites et les traiter à la main pour voir comment faire ça bien. Il faut garder ta bonne résolution :
    - d'abord l'algo,
    - ensuite le coding !

  18. #18
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 93
    Par défaut
    T'es pas drole Fremen167 tu trouve toujours une faille

    Bon, j'ai revu l'algo (encore une fois). J'ai essayé plusieurs combinaisons. Ca a l'air de fonctionner mieux.

    Enfin jusqu'a que Fremen167 nous sortes une combinaison magique qui fait tout foirer

    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
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
     
    #define COUP_MAX    12      // Nombre de coup Maximal
    #define NB_CHIFFRE  5       // Nombre de chiffre dans le code
    #define BORNE_MAX   10      // Borne superieur du hasard
     
     
    // Differentes entrees du menu d'affichage
    #define ESSAI       'e'     /* Affiche la combinaison entree et le resultat associee */
    #define GAGNE       'g'     /* Affiche le message GAGNANT */
    #define PERDU       'p'     /* Affiche le message PERDANT */
    #define MENU        'm'     /* Affiche le menu principal */
     
    #define OK 1
     
     
     
     
    // Fonctions
    static void init_res (char res[COUP_MAX][NB_CHIFFRE]);
    static void hasard(int code[NB_CHIFFRE]);
    static void saisie (int ROW, int essai[COUP_MAX][NB_CHIFFRE]);
    static void teste (int ROW, int *p_bon,char res[COUP_MAX][NB_CHIFFRE], int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE]);
    static void affichage(char mode, int ROW,char res[COUP_MAX][NB_CHIFFRE], int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE]);
     
     
     
    // Programme principal
    int main(void)
    {
        int essai[COUP_MAX][NB_CHIFFRE] = {{0}};            // Tableau conteant les combinaisons essayees
        char res[COUP_MAX][NB_CHIFFRE];                     // Tableau contenant les resultats de chaques combinaisons
        int code[NB_CHIFFRE] = {0};                         // Tableau contenant le code a decouvrir
     
        int bon;
        int ROW;                        // Indique la ligne en cours de traitement
        int coup;                       // Indique le nombre de coup joue
     
        coup = 1;
        ROW = 0;
     
        // initialise le tableau RES
        init_res (res);
     
        // Generation du code aleatoire
        srand(time(NULL));
        hasard(code);
     
        // Affichage du menu
        affichage(MENU,0,res,code,essai);
     
        // Test de l'essai
        do {
            saisie(ROW,essai);
            bon = 0;
            teste(ROW,&bon,res,code,essai);             // On teste le code entré
            affichage(ESSAI,ROW,res,code,essai);     // On affiche le code essaye et son resultat
            ROW++;
            coup++;
        }
        while (bon != NB_CHIFFRE && coup <= COUP_MAX);
     
     
        if (bon == NB_CHIFFRE)
            affichage(GAGNE,0,res,code,essai);
        else
            affichage(PERDU,0,res,code,essai);
     
        return 0;
    }
     
     
     
    // FONCTION INITIALISATION DU TABLEAU RESULTAT
    static void init_res (char res[COUP_MAX][NB_CHIFFRE]) {
     
        int j;
     
        for (j = 0; j < COUP_MAX; j++) {
            int i;
            for (i = 0; i < NB_CHIFFRE; i++)
                res[j][i] = '.';
        }
    }
     
     
     
    // FONCTION HASARD
    static void hasard(int code[NB_CHIFFRE]) {
        int tmp, i, pos;
     
        pos = 0;
     
        code[pos++] = (int)(rand()/(double)RAND_MAX * (BORNE_MAX));
     
        while (pos < NB_CHIFFRE){
            tmp = (int)(rand()/(double)RAND_MAX * (BORNE_MAX));
     
        // verifier que la valeur tiree n'est pas deja presente
            for (i = 0; i < pos; i++) {
                while (tmp == code[i]) {
                    tmp = (int)(rand()/(double)RAND_MAX * (BORNE_MAX));
                }
            }
            code[pos++] = tmp;
        }
    }
     
     
     
     
    // FONCTION DE SAISIE DE LA COMBINAISON
    static void saisie (int ROW, int essai[COUP_MAX][NB_CHIFFRE]) {
     
        int n;
     
        do {
            char chaine[20];
            printf("\nEntrez votre combinaison : ");
            fgets(chaine, sizeof chaine, stdin);
     
            n = sscanf(chaine, "%d %d %d %d %d", &essai[ROW][0], &essai[ROW][1], &essai[ROW][2], &essai[ROW][3],&essai[ROW][4] );
     
            if (n != NB_CHIFFRE)
                puts("ERREUR");
        }
        while (n != NB_CHIFFRE);
    }
     
     
    // FONCTION TEST
    static void teste (int ROW, int *p_bon, char res[COUP_MAX][NB_CHIFFRE], int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE]) {
     
        int i, j;
        int done;
        int work[NB_CHIFFRE] = {0};
     
        for (i = 0; i < NB_CHIFFRE; i++) {
            done = 0;
            for (j = 0; j < NB_CHIFFRE && done != 1; j++) {
     
                if (essai[ROW][i] == code[i] && done != 1) {
                    res[ROW][i] = '#';
                    work[i] = OK;
                    done = 1;
                    (*p_bon)++;
                }
     
                else if ((essai[ROW][i] == code[j]) && (work[j] != OK) && (done != 1) && (i != j) && (essai[ROW][j] != code[j])) {
                    res[ROW][i] = '*';
                    work[j] = OK;
                    done = 1;
                }
            }
        }
    }
     
     
     
     
    // FONCTION AFFICHAGE
    static void affichage(char mode, int ROW, char res[COUP_MAX][NB_CHIFFRE], int code[NB_CHIFFRE], int essai[COUP_MAX][NB_CHIFFRE]) {
     
        int i, j, k;
     
        switch (mode) {
            case 'e' :
                for (j = 0; j <= ROW; j++) {
                    k = 0;
     
                    // AFFICHAGE DE L'ESSAI
                    for (i = 0; i < NB_CHIFFRE; i++)
                        printf("%d ",essai[j][i]);
     
                    printf("\t");
     
                    /* Affichage des caracteres present et bien places */
                     for (i = 0; i < NB_CHIFFRE; i++)
                        if (res[j][i] == '#') {
                            printf("%c ", res[j][i]);
                            k++;
                        }
     
                    /* Affichage des caracteres present mais mal places */
                    for (i = 0; i < NB_CHIFFRE; i++)
                        if (res[j][i] == '*') {
                            printf("%c ", res[j][i]);
                            k++;
                        }
     
                    /* Affichage des autres caracteres si besoin */
                    for (; k < NB_CHIFFRE; k++)
                        printf(". ");
     
                    printf("\n");
                }
                break;
     
            case 'p' :
                printf("\nPERDU, le code correct etait :\t");
                for (i = 0; i < NB_CHIFFRE; i++)
                    printf("%d ", code[i]);
                printf("\n\n");
                break;
     
            case 'g' :
                printf("\nGAGNE, le code etait bien :\t");
                for (i = 0; i < NB_CHIFFRE; i++)
                    printf("%d ", code[i]);
                printf("\n\n");
                break;
     
            case 'm' :
                printf("\n\n");
                printf("\t*****************************\n");
                printf("\t*                           *\n");
                printf("\t*        MASTERMIND         *\n");
                printf("\t*                           *\n");
                printf("\t*****************************\n");
                printf("\n\n");
                printf(" - Utilisez les combinaisons dans le style : a b c d e puis 'entree'\n");
                printf(" - Les nombres possibles sont compris entre 0 et 9");
                printf("\n\n");
                printf(" - Les caraceteres # et * vous permettent de savoir s'il y a un chiffre\n");
                printf("   de votre combinaison dans le code secret, et s'il est respectivement\n");
                printf("   bien places ou mal places.");
                printf("\n\n");
                break;
     
     
        }
    }
    Edit : j'avais oublie de remettre le flag pour le resultat correct.

  19. #19
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    362
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 362
    Par défaut
    Citation Envoyé par beware Voir le message
    T'es pas drole Fremen167 tu trouve toujours une faille

    Bon, j'ai revu l'algo (encore une fois). J'ai essayé plusieurs combinaisons. Ca a l'air de fonctionner mieux.

    Enfin jusqu'a que Fremen167 nous sortes une combinaison magique qui fait tout foirer
    Tout d'abord, bravo, ça a l'air de fonctionner dans tous les cas

    Par contre, m'en voudras-tu si je te fais quelques remarques sur ton code ?

    Tout d'abord, une remarque générale (c'est un de mes dadas) : le nom de tes variables ou fonctions doit être toujours choisi de manière à permettre une lecture intuitive.

    Par exemple, work[i], on ne voit pas trop ce que ça peut vouloir dire. Pourquoi pas utilise[i], avec un petit commentaire qui précise qu'un chiffre de "code" est dit "utilisé" s'il a matché avec un chiffre d'essai ?

    Dans ta boucle teste, i et j sont respectivement des indices sur essai et code. Tu pourrais avantageusement utiliser ind-essai et ind-code (je sais, on trouve énormément de code avec ce genre d'incides i, j , k, etc. mais ça deviens vite pénible dans de gros programmes).

    Pourquoi utilises-tu un nom symbolique (OK) pour la valeur 1, et pas un autre (KO ?) pour la valeur 0 ? Ce serait plus parlant et homogène.

    Sur l'algo teste proprement dit :
    ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    if (essai[ROW][i] == code[i] && done != 1) {
                    res[ROW][i] = '#';
                    work[i] = OK;
                    done = 1;
                    (*p_bon)++;
                }
    sens un peu la bidouille, et n'a aucune raison de figurer dans la boucle j, puisque son résultat ne dépend que de i (done te permet de conditionner la recherche de mal placées).

    Enfin ton test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ((essai[ROW][i] == code[j]) && (work[j] != OK) && (done != 1) && (i != j) && (essai[ROW][j] != code[j]))
    me semble un peu compliqué. Tu dois pouvoir faire mieux.

    Peut-être gagnerais-tu à exprimer en Français les conditions dans lesquelles un chiffre est compté comme bien / mal placé. C'est souvent un excellent exercice de s'obliger à écrire précisément en Français (j'insiste) ce qu'on doit faire.

  20. #20
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par fremen167 Voir le message
    Peut-être gagnerais-tu à exprimer en Français les conditions dans lesquelles un chiffre est compté comme bien / mal placé. C'est souvent un excellent exercice de s'obliger à écrire précisément en Français (j'insiste) ce qu'on doit faire.
    +1

Discussions similaires

  1. Deuxieme programme en C, qu'en pensez-vous?
    Par beware dans le forum Débuter
    Réponses: 6
    Dernier message: 19/03/2009, 11h54
  2. Réponses: 59
    Dernier message: 07/02/2009, 14h10
  3. Réponses: 13
    Dernier message: 11/05/2003, 13h25

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