Chaine de caractères oubliée [Résolu]

Signaler
Messages postés
2
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
26 octobre 2011
-
Messages postés
37
Date d'inscription
jeudi 22 octobre 2009
Statut
Membre
Dernière intervention
10 décembre 2011
-
Hello les gens =)

Ma prof de dev m'ayant donné comme devoir de grosbill pour les vacances (ouais parce-qu'elle veut quand-même un peu me tester vu que que je suis en avance sur les autres en preums année de bts) de faire un mastermind, j'ai réussi à pondre un algo dans les deux jours qui ont suivi. Jusque là ça va, juste mindfuck à souhait, par contre le problème vient lorsque je code tout ça.

Pour un mastermind à cinq pions, je demande à chaque joueur, de saisir une chaine de caractère que je vérifie afin qu'elle corresponde au format voulu (une chaine de caractère où chaque caractère est un pion d'une couleur donnée). Quand le joueur qui doit chercher le code saisit sa proposition, elle est encore une fois vérifiée, puis on compare dans deux boucles imbriquées (une correspondant à l'incrémentation du code à trouver, et une correspondant au code saisi), et à chaque couleur, si elle est bien placée (au même endroit dans les deux tableaux), elle est validée directement dans la chaîne saisie, sinon elle est laissée telle quelle en espérant que sont tour vienne au prochain cycle, ou, si la couleur n'est pas répertoriée, la boule en question est marquée comme fausse.

Seulement voilà, outre cet algo tout simple, j'ai un soucis au niveau de la vérification : le premier cycle est foireux : la chaine de caractères correspondant au code à trouver disparaît puis réapparaît (oui oui, j'ai même mis un printf pour vérifier ce que je dis, dans le premier cycle de double for imbriqués, la chaine à trouver disparaît puis revient comme par magie au deuxième cycle).

Moralité : j'ai un jeu interminable parce-que j'ai un des cycles de vérification qui disparaît.

Je poste le code au cas où :

#include 
#include <stdio.h>

#include "mmind.h"

using namespace std;

int main()
{
    char mind[5] = {0, 0, 0, 0, 0};                 //Code à trouver
    char prpt[5] = {0, 0, 0, 0, 0};                 //Code saisi par le joueur
    char colors[7] = {0, 0, 0, 0, 0, 0, 0};         //Tableau contenant le nombre de boules de chacune des 7 couleurs
    unsigned char found, good, notfound;            //Nombre de boules placées, trouvées et inconnues.
    unsigned char i, n;
    bool err, playing;                              //Booléens de test de jeu et d'erreurs de saisie.

    err = true;                                     //On déclare qu'il-y-a une erreur pour entrer dans la boucle suivante

    while (err == true)                             //Boucle tant qu'il-y a une erreur de saisie.
    {
        scanf("%s", mind);                          //On saisit le code à trouver et à vérifier
        printf("\n%s", mind);                       //puis on l'affiche pour debug.
        colors = {0, 0, 0, 0, 0, 0, 0};             //On réinitialise le nombre de boules de chaque couleur

        err = false;                                //On declare qu'il n'y-a aucune erreur, si une erreur est détectée on affecte
        for (i 0 ; i < 5 ; i ++)                  //la variable et on repart dans la boucle)
        {                                           //Dans cette boucle on vérifie chacun des 5 caractères du code.
            switch (mind[i])
            {
            case 'B':
                B++;                                //Pour chacune des couleurs, on incrémente le nombre de boules de la couleur
                break;                              //correspondante dans le tableau colors[]

            case 'R':
                R++;
                break;


            case 'N':
                N++;
                break;

            case 'V':
                V++;
                break;

            case 'J':
                J++;
                break;

            case 'O':
                O++;
                break;

            case 'G':
                G++;
                break;

            default:
                err = true;                             //Le caractère courant n'a pas été reconnu, c'est une erreur.
                break;
            }
        }
        if (err) printf("\nErreur\n");
        else printf("\nAucune erreur, code valide\n");
    }

    playing true;                 //La partie commence à partir de cet instant3




    /*Saisie du deuxième joueur
    */
    while (playing == true)         //Boucle tant que la partie est déclarée en cours
    {
        err = true;                 //On commence par déclarer une erreur pour rentrer dans la boucle suivante
        while (err == true)         //La boucle s'arrête quand il n'y a plus d'erreur.
        {
            scanf("%s", &prpt);     //Le joueur saisit son code

            err = false;            //On déclare qu'il n'y a pas d'erreur pour pouvoir en mettre une plus tard.
            for (i = 0 ; i < 5 ; i ++)
            {
                switch (prpt[i])
                {
                case 'B':

                    break;

                case 'R':

                    break;


                case 'N':

                    break;

                case 'V':

                    break;

                case 'J':

                    break;

                case 'O':

                    break;

                case 'G':

                    break;

                default:
                    err = true;
                    break;
                }
            }

            if (err) printf("\nErreur, reessayez : ");
        }

        for (n = 0 ; n < 5 ; n++)
        {
            for (i = 0 ; i < 5 ; i++)
                {
                    printf("\ni=%d ; %c | n=%d ; %c", i, prpt[i], n, mind[n]);
                    switch (prpt[i])
                    {
                        case 'B':
                            if (mind[i] == 'B' && n == i)   prpt[i]=1;
                            else if (B 0) prpt[i] 0;
                            break;

                        case 'O':
                            if (mind[n] == 'O' && n == i)   prpt[i]=1;
                            else if (O 0) prpt[i] 0;
                            break;

                        case 1:
                            printf("Correspondance deja trouvee");
                            break;

                        case 0:
                            printf("Aucune correspondance trouvee");
                            break;

                        default:
                            printf("Undefined");
                            break;


                        /* Compléter vérification */
                    }
                }
        }


        notfound    = 0;
        found       = 0;
        good        = 0;

        for(i = 0 ; i <5 ; i++)
        {
            switch(prpt[i])
            {
                case 0: notfound++;
                    break;
                case 1: found++;
                    break;
                default :good++;
                    break;
            }
        }
        printf("\nTrouves : %d ; Bons : %d ; Faux : %d", found, good, notfound);
    }

    print("\nPartie Terminee");

    return 0;
}



Je confirme, c'est très, très crade, et le switch correspondant à la vérification des couleurs est tronqué volontairement (du coup y-a que le bleu B et le orange O qui marchent).



Voilà, jdois faire partie d'un cas d'école, un effet de bord ou je ne sais quoi ^^">


Merci d'avance =)

5 réponses

Messages postés
181
Date d'inscription
mardi 6 avril 2010
Statut
Membre
Dernière intervention
7 janvier 2012
8
Salut,
y'a un truc qui m'étonne : pourquoi faire une double boucle pour vérifier la correspondance des chaines ? Parce qu'ici en faisant 2 for tu dois en plus vérifier que les itérateurs sont égaux (n et i)... Et que veut dire disparait ?

De plus les switch ne sont pas très clair en effet:

C'est exprès que les cases soit vides ? il manque quelque chose ???

        switch (prpt[i])
                {
                case 'B':

                    break;

                case 'R':

                    break;


                case 'N':

                    break;

                case 'V':

                    break;

                case 'J':

                    break;

                case 'O':

                    break;

                case 'G':

                    break;

                default:
                    err = true;
                    break;
 


Y'a aussi une petite erreur ici : print("\nPartie Terminee"); //(printf)


De plus si c'est du C++, pourquoi ne pas avoir une classe "Pion", parce qu'ici à quoi correspondent les variables R,V,B,G,J,N... ? ce sont censé être des cases de colors[], c'est pour abrèger ? Et pourquoi surcharger avec <stdio.h> alors que inclut déjà les fonctions d'entrée et de sortie standard (cin cout) ?

Sinon le
using namespace std;
est à bannir... surtout si aucune fonction de cet espace nom n'est utilisé.

Au niveau de la déclaration des variables:
unsigned char found, good, notfound;            //Nombre de boules placées, trouvées et inconnues.

Si ce sont des nombres, pourquoi les déclarer comme des caractères ? un unsigned short int serait plus explicit non ?

et pour la déclaration de mind et prpt,
mind[5] = {0};

et
prpt{0}; 

suffit pour remplir les tableaux de 0.


Sinon, encore une erreur qui peut expliquer un bug: scanf("%s", &prpt); , y'a pas de & puisque c'est un tableau (donc prpt = adresse)
donc:
 scanf("%s", prpt);


( et c'est cette ligne qui fait "disparaître" mind, mais même en la corrigeant il reste une erreur, sûrement le prpt qui écrase le mind puisque celui-ci est juste au dessus dans la pile )

Sinon, le %s n'est pas bon car les tableaux font 5 octets, et les 5 sont occupé, il n'y a donc pas de caractère prévu pour la fin de chaine, et à certains printf, il y a de forte chance pour que des caractères s'affichent en plus des chaines à afficher... il faut prévoir 6 cases dans le tableau, et laisser la dernière à 0.

C++dialement,

Pop70
Messages postés
37
Date d'inscription
jeudi 22 octobre 2009
Statut
Membre
Dernière intervention
10 décembre 2011
15
Salut,

scanf("%s", &prpt);
"%s" attend un pointeur, une adresse, or prpt en est déjà un qui vaut &prpt[0].
Il convient donc d'écrire :
scanf("%s", prpt);

Ensuite n'oublie pas qu'en C les chaîne sont null terminated.
Donc scanf("%s",var) rajoutera un zéro en fin de chaîne, ce qui fait que dans ton cas mind et prpt doivent être des tableaux de 6 caractères et non pas 5 afin d'éviter un débordement.

++
Messages postés
181
Date d'inscription
mardi 6 avril 2010
Statut
Membre
Dernière intervention
7 janvier 2012
8
A désolé, je n'avais pas vu qu'une réponse avait été faite entre temps, mais en tout cas je suis entièrement d'accord avec stagiairecpp
;)


Pop70
Messages postés
2
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
26 octobre 2011

Pour ce qui est de la classe pion et tout j'y avais pas vraiment pensée sur le coup, ça reste un truc pour les cours et on est encore dans des trucs très standards (chez moi les gens ont déjà du mal à intégrer le concept d'objet en VBS, du coup j'ai moi-même tendance à l'oublier), mais je te remercie sincèrement de ce rappel *w*

A la base le switch était pas vide, j'ai voulu tester un truc avec mais ça rien donné, je l'ai juste laissé là au cas où, vais changer pour un _gros_ if =)

Pour ce qui est du scanf j'ai du faire une mauvaise correction, je l'ai fait tourner la moitié du temps avec prpt et non &prpt, ça a pas empêché de tourner sur le coup, chais pas pourquoi j'ai fait ça, merci du rappel encore =)


Je pensais à un problème de débordement avec la chaine null-terminated, mais quand j'affiche le contenu des variables, mind contient bien ce que je lui ai inscrit, prpt aussi, mais c'est quand je rentre dans la première boucle que ça disparaît, puis mind réapparaît, j'avais pas vu cette éventualité =)


Je viens de tester en faisant simplement des tableaux à 6 espaces et non 5, étrangement ça marche du tonerre >w< Merci les gens, serai plus attentionné à l'avenir <3


btw j'avais pas fait gaffe au namespace.
Messages postés
37
Date d'inscription
jeudi 22 octobre 2009
Statut
Membre
Dernière intervention
10 décembre 2011
15
Re,

quand j'affiche le contenu des variables, mind contient bien ce que je lui ai inscrit, prpt aussi, mais c'est quand je rentre dans la première boucle que ça disparaît, puis mind réapparaît, j'avais pas vu cette éventualité

Parce que tu affichais sûrement leur valeur juste après les avoir saisies.
En mémoire les octets de prpt et de mind sont consécutifs. Comme mind est déclaré au dessus de prpt, ce dernier précèdera ce premier (toujours en mémoire je parle).
Donc en saisissant 5 caractères dans le scanf de prpt, le zéro de fin venait mettre le premier de mind à 0 qui devenait donc par la même une chaine considérée vide (jusqu'à ce qu'elle soit ressaisie, etc).

J'ai pas vérifié mais essaye ce code en saisissant "12345" pour mind, puis "6789" pour prpt, ou bien encore "123456789" pour mind... Ca devrait illustrer :
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    char mind[5] = {0, 0, 0, 0, 0};                 //Code à trouver
    char prpt[5] = {0, 0, 0, 0, 0};

    printf("\nprpt? ");
    scanf("%s", prpt);

    printf("prpt=[%s] mind=[%s]", prpt, mind);

    printf("\nmind? ");
    scanf("%s", mind);

    printf("prpt=[%s] mind=[%s]", prpt, mind);

    print("\n\n");
    system("pause");

    return 0;
}


Bonne continuation.
++