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 :

Détecter une erreur


Sujet :

C

  1. #1
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2019
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2019
    Messages : 72
    Par défaut Détecter une erreur
    Bonjour,
    J'ai un petit souci sûrement bête mais qui m'ennuie beaucoup.
    Je code en C avec Code Block et j'ai une erreur que je n'arrive pas éclaircir.

    J'ai un plateau de 20 cases et une IA qui doit trouver la bonne case à jouer.
    Dans l'exemple que je teste, la seule case correcte à jouer pour gagner est la 17.

    Lorsque j'exécute le programme en mode normal, l'IA ne joue pas la case 17 mais joue soit la 10 soit la 13.
    Lorsque j'exécute le programme en mode débogage, la seule case qu'il joue est la 17.

    J'ai eu l'idée de faire écrire dans un fichier les choix de l'IA dans les 2 modes, pour comparer. Idem
    En mode normal, l'IA hésite bien entre 10 et 13.
    En mode débogage, l'IA choisit 17.

    Lorsque je renverse le plateau avec une symétrie horizontale et que, du coup, la case à jouer n'est plus la 17 mais devient la 2, le mode normal joue la bonne case et ne se trompe pas.

    Ce que je ne comprends pas, c'est pourquoi en testant le même exemple en deux modes différents, je n'ai pas le même résultat.

    Quelqu'un sait-il régler ce genre de problème ?
    Merci de votre aide.

  2. #2
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 779
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 779
    Par défaut
    Je ne sais pas si c'est encore le cas mais le mode débogage initialisait toutes les variables/ pointeurs à zéro (NULL)

    Donc commence par regarder les initialisations dans ton code

  3. #3
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2019
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2019
    Messages : 72
    Par défaut
    Merci de ta suggestion
    Il me semble que mes variables sont bien initialisées. Et que mon problème ne vienne pas de là, car dans ce cas, pourquoi dans la configuration haute, il n'y aurait jamais aucun soucis et dans la configuration basse, ça coince à chaque fois, la même erreur.

    Un des soucis que j'ai (juste un peu), c'est que j'ai (comme beaucoup d'entre vous), des variables, des pointeurs, des structures, ...
    Lorsque je lance le debugger, c'est facile avec code block de voir les valeurs des variables définie dans la fonction, mais pas celle des pointeurs utilisés. Pour cela, je dois définir à chaque fois une variable ayant pour valeur la valeur du pointeur et ensuite regarder la valeur de la variable.

    Existe-t-il un moyen d'éviter cela, ou pas ? Car cela m'oblige de déclarer une nouvelle variable pour chaque pointeur et tableau utilisé et d'insérer des actualisations à plusieurs endroit de mon programme.

  4. #4
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 315
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 315
    Billets dans le blog
    5
    Par défaut
    Bonjour.

    Attends un instant, je regarde dans ma boule de cristal...

    Sans code cela va être difficile voir impossible de répondre à la problématique. Je comprends bien qu'en utilisant un modèle d'IA le code source peut ne pas être parlant, mais quand même.

    Ceci dit, j'imagine que tu utilises un modèle par renforcement puisque tu désires trouver un chemin. Le problème vient peut-être des "récompenses" qui sont mal calibrées...

  5. #5
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2019
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2019
    Messages : 72
    Par défaut
    Merci Gerald, je suis désolé pour ta boule de cristal et j'espère qu'elle est réparable et qu'elle sera sera bientôt réparée. Elle m'a l'air bien pratique en tout cas.

    Sans autre blague, je sais bien qu'il est difficile de résoudre un problème sans avoir le code devant soi, mais ma question initiale était déjà de comprendre pourquoi entre le mode normal et le mode debugger, je n'ai pas le même comportement, et que ce comportement se répète à chaque fois à l'identique.

    Mon jeu est en fait un jeu morpion. Dans mon cas, 4*5 avec un alignement de 4 jetons identiques.
    Je ne peux pas poster l'intégralité du code et tu le comprendras aisément (2 700 lignes)

    Mais voici les fonctions peut-être utiles :

    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
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    void OrdiJoue(Case *plateau, Joueur Joueur, CaracteristiqueJeu *Jeu, DimPlateau DimJeu) //Gestion du jeu lorsque l'Ordi joue
    {
        int NumeroCaseAJouer=-1;
      /**/    int tmc[20];//Jeu->tabMeilleuresCases[Jeu->NbMeilleuresCases]=
        /**/    int i,nmc;//=NbMeilleuresCases
     
        if(Jeu->NbCasesJouees==0) //si c'est le 1er coup de la partie, alors on choisit aleatoirement
        {
            NumeroCaseAJouer=alea_entre_bornes(0, DimJeu.N*DimJeu.M-1); //choisit aleatoirement une case sur tout le plateau
        }
        else
        {
            ia(plateau, Joueur, Jeu, DimJeu); //l'ordi joue une case en analysant le jeu et cherchant la case la plus gagnante
            NumeroCaseAJouer=Jeu->tabMeilleuresCases[alea_entre_bornes(0, Jeu->NbMeilleuresCases-1)]; //on tire une case au hasard parmi les meilleures possibles
     
     for (i=0; i<20; i++)
            {
                /**/tmc[i]=Jeu->tabMeilleuresCases[i];
            }
            /**/     nmc=Jeu->NbMeilleuresCases;
     
        }
        JouerCoup(plateau, Joueur, Jeu, NumeroCaseAJouer); //Joue le coup selectionné
    }
    /**********************/
    void ia(Case *plateau, Joueur Joueur, CaracteristiqueJeu *Jeu, DimPlateau DimJeu)
    {
        int *TabDeCoef= FonctionAllocation1D(DimJeu.N*DimJeu.M, sizeof(*TabDeCoef));
        //  Info InfoZoneDeRecherche;
        Couronne InfoZoneDeRecherche[5]= {{0,DimJeu.N,DimJeu.M},{0,0,0},{0,0,0},{0,0,0},{0,0,0}}; //les InfoZoneDeRecherche est un tableau de 6 infos (CaseDepart-Largeur-Hauteur) correspondant au tableau general [0] puis aux zones de recherche [couronne 1-2-3-4]
     
        int NbCasesVides=DimJeu.N*DimJeu.M-(Jeu->NbCasesJouees);
        int MeilleurScore = -10000;
        int NbMeilleurScore=0;//nombre de fois que le MeilleurScoreeeea été atteint
        int niveau=0;//[0: ordi teste 1 jeton][1: adv teste 1 jeton][2: ordi teste 2 jetons][3: adv teste 2 jetons][4: ordi teste 3 jetons][5: adv teste 3 jetons][6: ordi teste 4 jetons][7: adv teste 4 jetons]
        int AlignementRealise = NON;//[OUI : il y a eu un alignement, on ne teste pas un niveau plus profond][NON : il n'y a pas d'alignement, on testera un niveau plus profond]
        int i,j;
        int taille=DimJeu.N*DimJeu.M-Jeu->NbCasesJouees;//dimension maximale
    //   int *ListeCasesVides= FonctionAllocation1D(taille, sizeof(*ListeCasesVides));//tableau servant a creer la ListeCaseVide, tableau grande taille N*M
     
    // DefinirZoneEtendue(*Jeu, DimJeu, &InfoZoneDeRecherche); //determine la zone a etudier (InfoZoneDeRecherche)
     
        DefinirZoneEtendue(*Jeu, DimJeu, InfoZoneDeRecherche); //determine la zone a etudier (InfoZoneDeRecherche), Jeu nest aps modifie (d'ou *) mais InfoZoneDeRecherche est modifie (tableau passe en pointeur)
        DefinirListeCaseVide(Jeu, DimJeu, InfoZoneDeRecherche);
     
        int nbcv;//NbCasesVides
        /**/    int lcv[20];//listecasesvides
        /**/    int lcv1[20];//listecasesvides
        /**/    int lcv2[20];//listecasesvides
        /**/    int lcv3[20];//listecasesvides
        /**/    int lcv4[20];//listecasesvides
        /**/    int tdc[20];//tabdecoef
        /**/    int tmc[20];//Jeu->tabMeilleuresCases[Jeu->NbMeilleuresCases]=
        /**/    int nmc;//=NbMeilleuresCases
     
     
        /**/    for (i=0; i<20; i++)
        {
            /**/lcv[i]=Jeu->ListeCasesVides[i];
            /**/lcv1[i]=Jeu->ListeCasesVides_C1[i];
            /**/lcv2[i]=Jeu->ListeCasesVides_C2[i];
            /**/lcv3[i]=Jeu->ListeCasesVides_C3[i];
            /**/lcv4[i]=Jeu->ListeCasesVides_C4[i];
        }
     
        for (i=0; i<9; i++)
            tdc[i]=TabDeCoef[i];
     
        if(Jeu->NbCasesJouees==DimJeu.N*DimJeu.M-1) //S'il ne reste plus qu'une seule case à jouer, alors on la joue: c'est ListeCasesVides[0]
        {
    //       for (i=0; i<9; i++)
    //   lcv[i]=Jeu->ListeCasesVides[i];
     
            //Jeu->tabMeilleuresCases[0]=Jeu->ListeCasesVides_C0[0]; //Choisit la derniere case vide
            TabCroissant(Jeu->HistoriqueJeton, DimJeu.N*DimJeu.M-1);//on range toutes les cases jouées dans l'ordre croisant. Il n'y a qu'une suele case vide, toutes les cases sont Hist[i]=i (avant la case restante) ou Hist[i]= i-1 (apres la case restante)
     
    //       for (i=0; i<9; i++)
    //   lcv[i]=Jeu->ListeCasesVides[i];
     
            j=0;
            while(Jeu->HistoriqueJeton[j]==j)//tant que la case est au bon rang
                j=j+1;//on pâsse a la suivante
            Jeu->tabMeilleuresCases[0]=j;
            Jeu->NbMeilleuresCases=1;
            //     *NumeroCaseAJouer=j;
    //  a=Jeu->tabMeilleuresCases[0];
        }
        else//si plusieurs choix, alors on lance on applique l'ia prevue
        {
            for (i=0; i<DimJeu.N*DimJeu.M; i++) //on rempli le tableau de -1
                TabDeCoef[i]=-1; //alors on ecrit -1 pour une "case occupée"
     
            for (i=0; i<NbCasesVides; i++) //on cherche les cases deja jouées
                TabDeCoef[Jeu->ListeCasesVides[i]]=0; //alors on ecrit 0 qui sera incrementé pour une "case à tester" et on garde //alors on ecrit -1 pour une "case occupée" a l'origine
    //TabDeCoef contient TOUTES les cases du jeu avec un coef -1 si occupée et 0 si vide de TOUT le jeu
     
            /**/       for (i=0; i<20; i++)
            {
                /**/lcv[i]=Jeu->ListeCasesVides[i];
                /**/lcv1[i]=Jeu->ListeCasesVides_C1[i];
                /**/lcv2[i]=Jeu->ListeCasesVides_C2[i];
                /**/lcv3[i]=Jeu->ListeCasesVides_C3[i];
                /**/lcv4[i]=Jeu->ListeCasesVides_C4[i];
                /**/tdc[i]=TabDeCoef[i];
            }
            /**/nbcv=NbCasesVides;
     
            while((AlignementRealise==NON)&&(niveau<(DimJeu.NbJetonsAAligner-1)*2))
            {
                SimuleCoup(niveau, *Jeu, plateau, Joueur, InfoZoneDeRecherche, DimJeu, TabDeCoef, &AlignementRealise);//*Jeu car on ne modofie pas jeu
                niveau=niveau+1;
            }
            /**/       for (i=0; i<20; i++)
                /**/   tdc[i]=TabDeCoef[i];
     
            maximumTableau(TabDeCoef, DimJeu.N*DimJeu.M, &MeilleurScore, &NbMeilleurScore); //Recherche la valeur maximale du plateau de taille DimJeu.N*DimJeu.M  ainsi que le nombre de fois qu'eelle apparait.
     
            for (j=0; j<DimJeu.N*DimJeu.M; j++)//on va chercher toutes les cases de coef ayant le MeilleurScore
            {
                if(TabDeCoef[j]==MeilleurScore)
                {
                    Jeu->tabMeilleuresCases[Jeu->NbMeilleuresCases]=j;
                    Jeu->NbMeilleuresCases=Jeu->NbMeilleuresCases+1;//faut-il conserver ?
                }
            }
            for (i=0; i<20; i++)
            {
                /**/tdc[i]=TabDeCoef[i];
                /**/tmc[i]=Jeu->tabMeilleuresCases[i];
            }
            /**/     nmc=Jeu->NbMeilleuresCases;
        }
        /**/       for (i=0; i<20; i++)
            /**/tdc[i]=TabDeCoef[i];
    // fprintf(fichierEssaiCase, "Dans IA, la liste des meilleures cases est tmc : %d.\n",tmc[0]);
      /**/ fprintf(fichierEssaiCase, "Dans IA, la liste des meilleures cases est tmc :\n");
      /**/     for (i=0; i<20; i++)
            {
          /**/      fprintf(fichierEssaiCase, "%d - %d.\n",tmc[i],Jeu->tabMeilleuresCases[i]);
            }
     
     
      fclose(fichierEssaiCase);
     
        free(TabDeCoef);
        TabDeCoef=NULL;
    //    free(TabDeTravail);
    //    TabDeTravail=NULL;
    //    free(ListeCasesVides_C0);
    //    ListeCasesVides_C0=NULL;
    //    free(ListeCasesVides_C1);
    //    ListeCasesVides_C1=NULL;
    //    free(ListeCasesVides_C2);
    //    ListeCasesVides_C2=NULL;
    }
    /**********************/
    void SimuleCoup(int niveau, CaracteristiqueJeu Jeu, Case *plateau,Joueur Joueur, Couronne InfoZoneDeRecherche[], DimPlateau DimJeu, int *TabDeCoef,int *AlignementRealise)
    {
        //niveau = nombre de jetons a ajouter à NbCasesJouees
        int i,j,k,l;
        /**/    int NbCasesVides;//=(InfoZoneDeRecherche.Hauteur)*(InfoZoneDeRecherche.Largeur)-(Jeu.NbCasesJouees);//taille du tableau ListeCV, cases vides, que l'on va creer
        Case Ordi=(Joueur.ListeJ[(Jeu.NbCasesJouees)%2]).jeton;//Rond ou Croix, niveau 0 et 2 et 4 et 6
        Case Adversaire =(Joueur.ListeJ[(Jeu.NbCasesJouees+1)%2]).jeton;//Croix ou Rond, niveau 1 et 3 et 5 et 7
        Case JoueurTeste;
        int  NbAlignements=0;//initialisation
        int *ListeCV= FonctionAllocation1D(DimJeu.N*DimJeu.M, sizeof(*ListeCV));//tableau servant a creer la ListeCaseVide utile pour le jeu (si grandes dimensions), tableau grande taille N*M
     
     
        /*       for (i=0; i<9; i++)
        {lcv[i]=Jeu->ListeCasesVides[i];
           tdc[i]=TabDeCoef[i];}
        */
     
    //     Jeu->HistoriqueJeton= FonctionAllocation1D(NouveauDimJeu.N*NouveauDimJeu.M, sizeof(Jeu->HistoriqueJeton)); //definit le nouveau HistoriqueJeu
     
        switch (niveau) //determine les boutons a afficher
        {
        case 0 :
            JoueurTeste=Ordi;
            NbCasesVides=InfoZoneDeRecherche[1].Largeur*InfoZoneDeRecherche[1].Hauteur-Jeu.NbCasesJouees;
            free(ListeCV); //on libere l'ancien HistoriqueJeu
            ListeCV=NULL;
            ListeCV= FonctionAllocation1D(NbCasesVides, sizeof(*ListeCV));//tableau servant a creer la ListeCaseVide, tableau grande taille N*M
            for (i = 0; i < NbCasesVides; i++) //on copie les bonnes cases vides dans la tableau ListeCV
                ListeCV[i]=Jeu.ListeCasesVides_C1[i];
            break;
        case 1 :
            JoueurTeste=Adversaire;
            NbCasesVides=InfoZoneDeRecherche[1].Largeur*InfoZoneDeRecherche[1].Hauteur-Jeu.NbCasesJouees;
            free(ListeCV); //on libere l'ancien HistoriqueJeu
            ListeCV=NULL;
            ListeCV= FonctionAllocation1D(NbCasesVides, sizeof(*ListeCV));//tableau servant a creer la ListeCaseVide, tableau grande taille N*M
            for (i = 0; i < NbCasesVides; i++) //on copie les bonnes cases vides dans la tableau ListeCV
                ListeCV[i]=Jeu.ListeCasesVides_C1[i];
            break;
        case 2 :
            JoueurTeste=Ordi;
            NbCasesVides=InfoZoneDeRecherche[2].Largeur*InfoZoneDeRecherche[2].Hauteur-Jeu.NbCasesJouees;
            free(ListeCV); //on libere l'ancien HistoriqueJeu
            ListeCV=NULL;
            ListeCV= FonctionAllocation1D(NbCasesVides, sizeof(*ListeCV));//tableau servant a creer la ListeCaseVide, tableau grande taille N*M
            for (i = 0; i < NbCasesVides; i++) //on copie les bonnes cases vides dans la tableau ListeCV
                ListeCV[i]=Jeu.ListeCasesVides_C2[i];
            break;
        case 3 :
            JoueurTeste=Adversaire;
            NbCasesVides=InfoZoneDeRecherche[2].Largeur*InfoZoneDeRecherche[2].Hauteur-Jeu.NbCasesJouees;
            free(ListeCV); //on libere l'ancien HistoriqueJeu
            ListeCV=NULL;
            ListeCV= FonctionAllocation1D(NbCasesVides, sizeof(*ListeCV));//tableau servant a creer la ListeCaseVide, tableau grande taille N*M
            for (i = 0; i < NbCasesVides; i++) //on copie les bonnes cases vides dans la tableau ListeCV
                ListeCV[i]=Jeu.ListeCasesVides_C2[i];
            break;
        case 4 :
            JoueurTeste=Adversaire;
            NbCasesVides=InfoZoneDeRecherche[3].Largeur*InfoZoneDeRecherche[3].Hauteur-Jeu.NbCasesJouees;
            free(ListeCV); //on libere l'ancien HistoriqueJeu
            ListeCV=NULL;
            ListeCV= FonctionAllocation1D(NbCasesVides, sizeof(*ListeCV));//tableau servant a creer la ListeCaseVide, tableau grande taille N*M
            for (i = 0; i < NbCasesVides; i++) //on copie les bonnes cases vides dans la tableau ListeCV
                ListeCV[i]=Jeu.ListeCasesVides_C3[i];
            break;
        case 5 :
            JoueurTeste=Adversaire;
            NbCasesVides=InfoZoneDeRecherche[3].Largeur*InfoZoneDeRecherche[3].Hauteur-Jeu.NbCasesJouees;
            free(ListeCV); //on libere l'ancien HistoriqueJeu
            ListeCV=NULL;
            ListeCV= FonctionAllocation1D(NbCasesVides, sizeof(*ListeCV));//tableau servant a creer la ListeCaseVide, tableau grande taille N*M
            for (i = 0; i < NbCasesVides; i++) //on copie les bonnes cases vides dans la tableau ListeCV
                ListeCV[i]=Jeu.ListeCasesVides_C3[i];
            break;
        case 6 :
            JoueurTeste=Adversaire;
            NbCasesVides=InfoZoneDeRecherche[4].Largeur*InfoZoneDeRecherche[4].Hauteur-Jeu.NbCasesJouees;
            free(ListeCV); //on libere l'ancien HistoriqueJeu
            ListeCV=NULL;
            ListeCV= FonctionAllocation1D(NbCasesVides, sizeof(*ListeCV));//tableau servant a creer la ListeCaseVide, tableau grande taille N*M
            for (i = 0; i < NbCasesVides; i++) //on copie les bonnes cases vides dans la tableau ListeCV
                ListeCV[i]=Jeu.ListeCasesVides_C4[i];
            break;
        case 7 :
            JoueurTeste=Adversaire;
            NbCasesVides=InfoZoneDeRecherche[4].Largeur*InfoZoneDeRecherche[4].Hauteur-Jeu.NbCasesJouees;
            free(ListeCV); //on libere l'ancien HistoriqueJeu
            ListeCV=NULL;
            ListeCV= FonctionAllocation1D(NbCasesVides, sizeof(*ListeCV));//tableau servant a creer la ListeCaseVide, tableau grande taille N*M
            for (i = 0; i < NbCasesVides; i++) //on copie les bonnes cases vides dans la tableau ListeCV
                ListeCV[i]=Jeu.ListeCasesVides_C4[i];
            break;
        }
     
        Jeu.NbCasesJouees=Jeu.NbCasesJouees+(niveau+1);//on va jouer 1 coup pour ordi
     
        switch(niveau)
        {
        case 0 ://test de 1 case
        case 1 :
            for (i = 0; i < NbCasesVides; i++) //pour chaque CaseVide, on teste son score
            {
                NbAlignements=0;//initialisation
                plateau[ListeCV[i]] = JoueurTeste;//On place le jeton de l'ordi
                Jeu.HistoriqueJeton[Jeu.NbCasesJouees-1]=ListeCV[i];//on actualise le dernier jeton joué
                verifFini(plateau, Joueur, DimJeu, &Jeu, &NbAlignements); //Fonction pour vérifier si la partie est terminée//on verfie s'il y a alignement
     
                if(NbAlignements!=0)//le jeton ne permet pas de gagner, il faut annuler et passer au suivant, inutile de modifier Jeu->NbCasesJouees (enlever puis le rajouter?)
                {
                    TabDeCoef[ListeCV[i]]=TabDeCoef[ListeCV[i]]+1;//on incrémente le coef de la case testee
                    *AlignementRealise=OUI;
                }
                AnnulerVerifFini(plateau, &Jeu, DimJeu);
                plateau[ListeCV[i]] = Vide;//on vide la case du plateau, inutile de liberer la derniere case de HistoriqueJeton
            }
            Jeu.HistoriqueJeton[Jeu.NbCasesJouees-1]=-1;//une fois toutes les possibilités testée, on vide le dernier jeton
            break;
        case 2 ://test de 2 cases
        case 3 :
            for (i = 0; i < NbCasesVides; i++) //pour chaque CaseVide, on teste son score
            {
                for (j = 0; j < NbCasesVides; j++) //pour chaque CaseVide, on teste son score
                {
                    if(j!=i)//si pas la meme case alors on simule sinon, on passe a la case j suivante
                    {
                        NbAlignements=0;//initialisation
                        plateau[ListeCV[i]] = JoueurTeste;//On place le jeton de l'ordi
                        plateau[ListeCV[j]] = JoueurTeste;//On place le jeton de l'ordi
                        Jeu.HistoriqueJeton[Jeu.NbCasesJouees-2]=ListeCV[i];//on actualise l'avant dernier jeton joué
                        Jeu.HistoriqueJeton[Jeu.NbCasesJouees-1]=ListeCV[j];//on actualise le dernier jeton joué
     
                        verifFini(plateau, Joueur, DimJeu, &Jeu, &NbAlignements); //Fonction pour vérifier si la partie est terminée//on verfie s'il y a alignement
     
                        if(NbAlignements!=0)//le jeton ne permet pas de gagner, il faut annuler et passer au suivant, inutile de modifier Jeu->NbCasesJouees (enlever puis le rajouter?)
                        {
                            TabDeCoef[ListeCV[i]]=TabDeCoef[ListeCV[i]]+1;//on incrémente le coef de la case testee
                            TabDeCoef[ListeCV[j]]=TabDeCoef[ListeCV[j]]+1;
                            *AlignementRealise=OUI;
                        }
                        AnnulerVerifFini(plateau, &Jeu, DimJeu);
                        plateau[ListeCV[i]] = Vide;//on vide la case du plateau
                        plateau[ListeCV[j]] = Vide;//on vide la case du plateau
                    }
                }
            }
            Jeu.HistoriqueJeton[Jeu.NbCasesJouees-2]=-1;//une fois toutes les possibilités testée, on vide l'avant dernier jeton
            Jeu.HistoriqueJeton[Jeu.NbCasesJouees-1]=-1;//une fois toutes les possibilités testée, on vide le dernier jeton
            break;
        case 4 ://test de 3 cases
        case 5 :
            for (i = 0; i < NbCasesVides; i++) //pour chaque CaseVide, on teste son score
            {
                for (j = 0; j < NbCasesVides; j++) //pour chaque CaseVide, on teste son score
                {
                    if(j!=i)//si pas la meme case alors on simule sinon, on passe a la case j suivante
                    {
                        for (k = 0; k < NbCasesVides; k++) //pour chaque CaseVide, on teste son score
                            if((k!=i)&&(k!=j))//si pas la meme case alors on simule sinon, on passe a la case j suivante
                            {
                                NbAlignements=0;//initialisation
                                plateau[ListeCV[i]] = JoueurTeste;//On place le jeton de l'ordi
                                plateau[ListeCV[j]] = JoueurTeste;//On place le jeton de l'ordi
                                plateau[ListeCV[k]] = JoueurTeste;//On place le jeton de l'ordi
                                Jeu.HistoriqueJeton[Jeu.NbCasesJouees-3]=ListeCV[i];//on actualise l'avant dernier jeton joué
                                Jeu.HistoriqueJeton[Jeu.NbCasesJouees-2]=ListeCV[j];//on actualise le dernier jeton joué
                                Jeu.HistoriqueJeton[Jeu.NbCasesJouees-1]=ListeCV[k];//on actualise le dernier jeton joué
     
                                verifFini(plateau, Joueur, DimJeu, &Jeu, &NbAlignements); //Fonction pour vérifier si la partie est terminée//on verfie s'il y a alignement
     
                                if(NbAlignements!=0)//le jeton ne permet pas de gagner, il faut annuler et passer au suivant, inutile de modifier Jeu->NbCasesJouees (enlever puis le rajouter?)
                                {
                                    TabDeCoef[ListeCV[i]]=TabDeCoef[ListeCV[i]]+1;//on incrémente le coef de la case testee
                                    TabDeCoef[ListeCV[j]]=TabDeCoef[ListeCV[j]]+1;
                                    TabDeCoef[ListeCV[k]]=TabDeCoef[ListeCV[k]]+1;
                                    *AlignementRealise=OUI;
                                }
                                AnnulerVerifFini(plateau, &Jeu, DimJeu);
                                plateau[ListeCV[i]] = Vide;//on vide la case du plateau
                                plateau[ListeCV[j]] = Vide;//on vide la case du plateau
                                plateau[ListeCV[k]] = Vide;//on vide la case du plateau
                            }
                    }
                }
            }
            Jeu.HistoriqueJeton[Jeu.NbCasesJouees-3]=-1;//une fois toutes les possibilités testée, on vide l'avant-avant dernier jeton
            Jeu.HistoriqueJeton[Jeu.NbCasesJouees-2]=-1;//une fois toutes les possibilités testée, on vide l'avant dernier jeton
            Jeu.HistoriqueJeton[Jeu.NbCasesJouees-1]=-1;//une fois toutes les possibilités testée, on vide le dernier jeton
            break;
        case 6 ://test de 4 cases
        case 7 :
            for (i = 0; i < NbCasesVides; i++) //pour chaque CaseVide, on teste son score
            {
                for (j = 0; j < NbCasesVides; j++) //pour chaque CaseVide, on teste son score
                {
                    if(j!=i)//si pas la meme case alors on simule sinon, on passe a la case j suivante
                    {
                        for (k = 0; k < NbCasesVides; k++) //pour chaque CaseVide, on teste son score
                            if((k!=i)&&(k!=j))//si pas la meme case alors on simule sinon, on passe a la case j suivante
                            {
                                for (l = 0; l < NbCasesVides; l++) //pour chaque CaseVide, on teste son score
                                    if((l!=i)&&(l!=j)&&(l!=k))//si pas la meme case alors on simule sinon, on passe a la case j suivante
                                    {
                                        NbAlignements=0;//initialisation
                                        plateau[ListeCV[i]] = JoueurTeste;//On place le jeton de l'ordi
                                        plateau[ListeCV[j]] = JoueurTeste;//On place le jeton de l'ordi
                                        plateau[ListeCV[k]] = JoueurTeste;//On place le jeton de l'ordi
                                        plateau[ListeCV[l]] = JoueurTeste;//On place le jeton de l'ordi
                                        Jeu.HistoriqueJeton[Jeu.NbCasesJouees-4]=ListeCV[i];//on actualise l'avant dernier jeton joué
                                        Jeu.HistoriqueJeton[Jeu.NbCasesJouees-3]=ListeCV[i];//on actualise l'avant dernier jeton joué
                                        Jeu.HistoriqueJeton[Jeu.NbCasesJouees-2]=ListeCV[j];//on actualise le dernier jeton joué
                                        Jeu.HistoriqueJeton[Jeu.NbCasesJouees-1]=ListeCV[k];//on actualise le dernier jeton joué
     
                                        verifFini(plateau, Joueur, DimJeu, &Jeu, &NbAlignements); //Fonction pour vérifier si la partie est terminée//on verfie s'il y a alignement
     
                                        if(NbAlignements!=0)//le jeton ne permet pas de gagner, il faut annuler et passer au suivant, inutile de modifier Jeu->NbCasesJouees (enlever puis le rajouter?)
                                        {
                                            TabDeCoef[ListeCV[i]]=TabDeCoef[ListeCV[i]]+1;//on incrémente le coef de la case testee
                                            TabDeCoef[ListeCV[j]]=TabDeCoef[ListeCV[j]]+1;
                                            TabDeCoef[ListeCV[k]]=TabDeCoef[ListeCV[k]]+1;
                                            TabDeCoef[ListeCV[k]]=TabDeCoef[ListeCV[l]]+1;
                                            *AlignementRealise=OUI;
                                        }
                                        AnnulerVerifFini(plateau, &Jeu, DimJeu);
                                        plateau[ListeCV[i]] = Vide;//on vide la case du plateau
                                        plateau[ListeCV[j]] = Vide;//on vide la case du plateau
                                        plateau[ListeCV[k]] = Vide;//on vide la case du plateau
                                        plateau[ListeCV[l]] = Vide;//on vide la case du plateau
                                    }
                            }
                    }
                }
            }
            Jeu.HistoriqueJeton[Jeu.NbCasesJouees-4]=-1;//une fois toutes les possibilités testée, on vide l'avant-avant dernier jeton
            Jeu.HistoriqueJeton[Jeu.NbCasesJouees-3]=-1;//une fois toutes les possibilités testée, on vide l'avant-avant dernier jeton
            Jeu.HistoriqueJeton[Jeu.NbCasesJouees-2]=-1;//une fois toutes les possibilités testée, on vide l'avant dernier jeton
            Jeu.HistoriqueJeton[Jeu.NbCasesJouees-1]=-1;//une fois toutes les possibilités testée, on vide le dernier jeton
            break;
        }
     
        Jeu.NbCasesJouees=Jeu.NbCasesJouees-(niveau+1);//on annule le jeton joué pour l'ordi
     
        free(ListeCV);
        ListeCV=NULL;
    }
    toutes les lignes /**/ sont des lignes pour pouvoir afficher la valeur des pointeurs lors du débogage
    Les paramètres OrdiJoue(Case *plateau, Joueur Joueur, CaracteristiqueJeu *Jeu, DimPlateau DimJeu) contiennent les dimensions du jeu (longueur, largeur, nombre de jetons à aligner, ...)
    Dis moi si tu veux plus de détails.
    je sais que je peux raccourcir la 1ere partie de la fonction SimuleCoup, mais je n'y arrive pas pour la fin de la fonction.

  6. #6
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 315
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 315
    Billets dans le blog
    5
    Par défaut
    Effectivement il y a du monde . Ça triture pas mal avec les tableaux. Dans la fonction ia(); tu initialises cinq tableaux lcv[] mais vu ton code leur première initialisation ne sert à rien puisque qu'ils ne sont jamais utilisés en dehors des conditions qui suivent.

    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
     /**/    int lcv[20];//listecasesvides
      /**/    int lcv1[20];//listecasesvides
      /**/    int lcv2[20];//listecasesvides
      /**/    int lcv3[20];//listecasesvides
      /**/    int lcv4[20];//listecasesvides
     
    ...
     
    /**/    for (i=0; i<20; i++)
        {
          /**/lcv[i]=Jeu->ListeCasesVides[i];
          /**/lcv1[i]=Jeu->ListeCasesVides_C1[i];
          /**/lcv2[i]=Jeu->ListeCasesVides_C2[i];
          /**/lcv3[i]=Jeu->ListeCasesVides_C3[i];
          /**/lcv4[i]=Jeu->ListeCasesVides_C4[i];
        }
    Ce code peut être supprimé ou mis en commentaire s'il doit être utilisé ultérieurement. D'ailleurs tu les initialises plus loin dans une condition mais ils ne sont jamais utilisés après. Un reliquat d'essai peut être. Pense à commenter tous les codes en trop pour avoir un minimum de chose sous les yeux. Ça aide au débogage.

    Pour la fonction SimuleCoup(); je ne comprends pas pourquoi tu ne transmets pas un pointeur pour CaracteristiqueJeu. En faisant cela tu crées une copie dans ta fonction. Les modifications effectuées ne se répercutent pas ailleurs.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void SimuleCoup(int niveau, CaracteristiqueJeu Jeu, Case *plateau,Joueur Joueur, Couronne InfoZoneDeRecherche[], DimPlateau DimJeu, int *TabDeCoef,int *AlignementRealise)
    Crée des fonctions temporaires pour afficher le contenu de tes différents tableaux. À chaque manipulation d'un d'entre-eux affiche son contenu avant et après manipulation, ça t'aidera à voir où ton code ne fait pas ce que tu attends.

  7. #7
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2019
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2019
    Messages : 72
    Par défaut
    Je vais essayer de t'en dire un peu plus.
    1er point
    Ma version du morpion est un morpion classique 3*3 mais on peut modifier les dimensions jusqu'à 30*30 avec 3-4-5 jetons à aligner.
    L'exemple de mon pb est le cas 4*5 soit 20 cases et alignement de 4 à obtenir.
    Je crée plusieurs listes de cases vides : celles de tout le jeu, puis celles des couronnes 1-2-3-4 (c'est pour cela que j'ai plusieurs listes que je cherche à réduire)
    Imaginons que le jeu soit le suivant et que O doive jouer.
    .O..X...2...3..4
    .O..X...7...8..9
    10.11.12.13.14
    15.16.17.18.19

    Les cases avec les chiffres représentent les cases vides.
    J'aurais ListeCasesVides = 2,3,4,7,8,9,10,11,12,13,14,15,16,17,18,19.
    O se demande s'il peut gagner en jouant une seule fois. Au lieu de tester toutes ces cases, il ne va s'intéresser qu'à la 1ere couronne (2,7,10,11,12), oui, O gagne en jouant 10. et les listecouronnes2-3-4 ont été inutile.

    Si par contre le jeu est :
    .X..O...2...3..4
    .O..X...7...8..9
    10.11.12.13.14
    15.16.17.18.19
    O ne peut pas gagner avec 1 seul jeton, mais X pourrait en jouant 12 donc O doit bloquer le 12.
    si ni O, ni X gagnent en 1 jeton, le peuvent-ils en 2, 3 ou 4 jetons d'où la création des ListeCasesVides des couronnes ce qui se fait avec les fonctions DefinirZoneEtendue(*Jeu, DimJeu, InfoZoneDeRecherche) et DefinirListeCaseVide(Jeu, DimJeu, InfoZoneDeRecherche) pour obtenir mes 5 listes en questions.

    De plus pour
    012
    34X
    6XO
    O sait que la position 0 est plus avantageuse que 1 ou 4 car 0 permet 2 alignements immédiat donc imbattable.

    C'est le tableau TabDeCoef qui répertorie les coefficients de chaque case puis la fonction OrdiJoue choisi parmi les meilleures
    2eme point
    Détails sur mon pb.
    Je teste

    .0..1...2...3..4
    .5..6...7...8..9
    10.X.X.13.14
    15.O.17.O.19

    La meilleure case est évidemment la 17 car il y aura ensuite 3 jetons alignés et libres de chaque côté pour finir un alignement de 4.
    En mode debugger, la meilleure case trouvée est 17. Super. et O la joue.
    En mode normal, les meilleures cases trouvées sont 10 et 13.
    D'où la ligne /**/ fprintf(fichierEssaiCase, "Dans IA, la liste des meilleures cases est tmc :\n");

    C'est le but initial de mon message, pourquoi pas la même liste selon le mode ?

    2eme point
    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
     
    typedef struct DimPlateau DimPlateau;
    struct DimPlateau
    {
        int N;//dim horizontale
        int M;//dim verticale
        int DimCase; //Taille des cases carrées
        int NbJetonsAAligner;
        jeu TypeJeu;
    };
     
    struct CaracteristiqueJeu
    {
        int NumeroJEnCours;//0 ou 1
        int NbCasesJouees;
        int *HistoriqueJeton; //liste les cases des jetons deja joués
        int *ListeCasesVides; //liste les numeros de cases vides
     //   int *ListeCasesVides_C0; //liste les numeros de cases vides
        int *ListeCasesVides_C1; //liste les numeros de cases vides
        int *ListeCasesVides_C2; //liste les numeros de cases vides
        int *ListeCasesVides_C3;
        int *ListeCasesVides_C4;
        int taille;
        int *tabMeilleuresCases; //liste les cases qui ont le meilleur score pour l'ia
        int NbMeilleuresCases;
        int PartieFinie;
    };
    3eme point
    Les /**/ ne sont que des "pseudo commentaires" pour moi, ce sont les lignes et les variables que j'ai ajouté pour afficher la valeur des pointeurs ou tableau. Par exemple lcv m'affiche la liste des cases vides et c'est pour cela que lcv est actualisé mais pas utilisé car à terme, ce sera supprimé.

    4eme point
    Je ne comprends pas très bien ce que tu voudrais que j'essaie avec "Pour la fonction SimuleCoup(); je ne comprends pas pourquoi tu ne transmets pas un pointeur pour CaracteristiqueJeu. En faisant cela tu crées une copie dans ta fonction. Les modifications effectuées ne se répercutent pas ailleurs."
    A quoi cela me servirait-il?
    La fonction SimuleCoup sert à savoir si l'ordi ou l'adversaire gagne en jouant 1,2,... jetons et quels sont les cases les plus intéressantes.
    5eme point
    J'avais dit que je pouvais raccourcir la 1ere partie de la fonction SimuleCoup (1er switch), mais je n'y arrive pas pour la fin de la fonction (2eme switch).
    Car cela revient un peu à faire les combinaisons de caractères d'une liste sauf que des fois on cherche les combinaisons de 1 caractère (1 seule for) et des fois de 3 caractères (3 for imbriqués)

  8. #8
    Membre Expert
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    707
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 95
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 707
    Par défaut
    Salut tout le monde.

    Coucou foetus

    Citation Envoyé par chamludo Voir le message
    Ce que je ne comprends pas, c'est pourquoi en testant le même exemple en deux modes différents, je n'ai pas le même résultat.
    Une différence de comportement d'un programme en mode debug et release, toute chose égale par ailleurs évidemment, peut être due à l'optimiseur.
    Si ça se confirme par sa désactivation (option de compilation/optimisation -O0 pour gcc et clang), il est possible qu'il y ait des variables dont le compilateur n'a pas le contrôle total. Dans ce cas, il faut les qualifier de "volatile".

    Une deuxième piste, c'est de faire un deuxième programme avec le strict minimum et qui reproduise le problème. Son analyse en sera facilitée.

  9. #9
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 315
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 315
    Billets dans le blog
    5
    Par défaut
    Je comprends bien ta philosophie de recherche du meilleur coup mais j'ai du mal à traduire ton code source évidemment.

    Après une lecture un peu plus fouillée tu modifies Jeu dans SimuleCoup() mais tu as besoin de ne mas modifier l'original. Je comprends mieux le pourquoi du comment. Malheureusement tu vas perdre en performance (temps d'exécution). Mais parfois on ne peut pas faire autrement .

    Plus généralement l'option -g lors de la compilation ne change rien au comportement de l'exécutable. Par contre l'option -O peut générer des problèmes. Pour ma part j'ajoute -Wall -Wextra -Wall -g -Wunused. C'est très verbeux mais tu travailles avec précision. L'idéal étant d'avoir une compilation sans aucun message (plus facile à dire qu'à faire). Maintenant ça ne te montrera pas des erreurs d’algorithme ou de gestion mémoire hasardeuse.

    Après relecture de ton premier post tu écris ceci :

    J'ai eu l'idée de faire écrire dans un fichier les choix de l'IA dans les 2 modes, pour comparer. Idem
    En mode normal, l'IA hésite bien entre 10 et 13.
    En mode débogage, l'IA choisit 17.

    Lorsque je renverse le plateau avec une symétrie horizontale et que, du coup, la case à jouer n'est plus la 17 mais devient la 2, le mode normal joue la bonne case et ne se trompe pas.

    Ce que je ne comprends pas, c'est pourquoi en testant le même exemple en deux modes différents, je n'ai pas le même résultat.
    Ça ressemble fortement à un problème d'algorithme. Peut-être un problème d'incrémentation de variable dans la fonction de recherche ?

  10. #10
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2019
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2019
    Messages : 72
    Par défaut
    Pour être tout à fait honnête, je n'y connais pas grand chose en configuration du compilateur et vos deux derniers messages sont assez obscurs pour moi.
    Je code avec Codeblock 20.03, encore configuré en anglais.
    Dans le menu Project->BuildOptions->CompilerSettings, rien n'est coché sauf :
    Debugging - Produce debugging symbol [-g]
    Warning - Enable all common compiler warnings (overrides many other settings) [-Wall]

    kaitlyn, j'ai bien un onglet Optimization, avec 12 lignes, mais je ne sais pas quoi cocher pour tester ton conseil.

    gerald3d, je viens de rajouter : enable extra compiler warnings [-Wextra], qui m'a découvert deux paramètres inutilisés que je viens de supprimer
    "Pour ma part j'ajoute -Wall -Wextra -Wall -g -Wunused", pourquoi y a-t-il deux fois "-Wall", je ne trouve pas "-Wunused". Sont-ce des cases à cocher ou des mots à écrire quelque part ?

  11. #11
    Membre Expert
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    707
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 95
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 707
    Par défaut
    Le plus simple est que tu fasses un "rebuild" (bouton ou menu Build->Rebuild) de ton projet.
    Quand la construction est finie, dans la fenêtre du bas, tu sélectionnes l'onglet "build log".
    Ensuite tu nous communiques toutes les options qui commencent par le symbole "moins" (-blablabla).

  12. #12
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2019
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2019
    Messages : 72
    Par défaut
    gcc.exe -Wextra -Wall -Wunreachable-code -g -Iinclude -c "C:\Users\Utilisateur\ProgrammeCodeBlocks\Programme-Essai\morpion-12-NveauIA-SansTournoi-NvelNvel-NbCasesVides-EnCourssssssssssssssssssss - Copie \Affichage.c" -o obj\Debug\Affichage.o

    gcc.exe -Wextra -Wall -Wunreachable-code -g -Iinclude -c "C:\Users\Utilisateur\ProgrammeCodeBlocks\Programme-Essai\morpion-12-NveauIA-SansTournoi-NvelNvel-NbCasesVides-EnCourssssssssssssssssssss - Copie \ia.c" -o obj\Debug\ia.o

    J'espère que cela peut t'aider

  13. #13
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 315
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 315
    Billets dans le blog
    5
    Par défaut
    Sans résoudre ton problème dans SimuleCoup() lors de la déclaration de ListeCV tu fais dans la foulée une allocation. Elle ne sert à rien à ce moment. Lors du premier switch quelque soit le choix tu la désalloues pour l'allouer à nouveau.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int *ListeCV= FonctionAllocation1D(DimJeu.N*DimJeu.M, sizeof(*ListeCV));
    Ne sachant pas si niveau peut prendre une autre valeur que celles testées alloue ListeCV après le premier switch si nécessaire.

  14. #14
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2019
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2019
    Messages : 72
    Par défaut
    En effet, j'ai fais ce que tu m'as dit et cela ne modifie en rien le pb.
    Comme l'alignement max est de 5 jetons et que l'on part du principe que l'ordi essaie de compléter ou de bloquer une combinaison commencée, donc avec 1 jeton minimum, la valeur max de jetons à ajouter est 4 et niveau =0->7. Pas dautre valeur possibles.
    Si niveau = 0 (ordi gagne avec 1 jeton, c'est à jouer) ou 1 (adv gagne avec 1 jeton, c'est à bloquer)
    Si niveau = 2 (ordi gagne avec 2 jetons, c'est à jouer) ou 3 (adv gagne avec 2 jetons, c'est à bloquer)
    Si niveau = 4 ou 5
    Si niveau = 6 ou 7

    Dans cette fonction ListeCV prend juste la liste les bonnes cases à tester selon le niveau.

  15. #15
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 315
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 315
    Billets dans le blog
    5
    Par défaut
    Histoire d'aller au bout de ma lecture peux-tu nous montrer la fonction FonctionAllocation1D() ?

  16. #16
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2019
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2019
    Messages : 72
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void *FonctionAllocation1D(unsigned short dimension, size_t size)
    {
        void *tableau=calloc(dimension, size); //Ce tableau doit etre dynamique et initialisé à 0
        if (tableau != NULL) return tableau;
     
        fprintf(fichierErreur, "Erreur d'allocation du tableau 1D : %s\n", SDL_GetError());
        exit(EXIT_FAILURE); //quitter le programme
    }
    Est-ce que mon type d'erreur porte est un Heisenbug ?

    Bug informatique dont le nom est basé sur le principe d'incertitude d'Heisenberg défini en physique quantique : observer une structure modifie son état.

    En pratique, on retrouve l'un des trois cas suivants :

    le programme tourne sous le débogueur, mais pas sur la ligne de commande
    le programme marche quand on rajoute des printf() pour déboguer, mais pas quand on les enlève
    le programme fonctionne quand des techniques de contrôle de bug sont appliquées, mais pas quand on retire ces contrôles pour une version de production.
    Souvent, ce genre de bug provient d'une variable qui est utilisée avant d'être assignée. Elle est donc dans un état indéfini lorsque le programme est lancé.

    Une autre source d'Heisenbug provient d'une politique "laxiste" de gestion de la mémoire, propice aux fuites de mémoires et à l'écrasement éventuel de données. Il convient d'être très strict sur la manière dont la mémoire dynamique est manipulée.

  17. #17
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 779
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 779
    Par défaut
    Citation Envoyé par chamludo Voir le message
    le programme marche quand on rajoute des printf() pour déboguer, mais pas quand on les enlève
    le programme fonctionne quand des techniques de contrôle de bug sont appliquées, mais pas quand on retire ces contrôles pour une version de production.
    Ces *bugs* ne sont pas magiques ... mais difficile à tracer
    Attention je ne connais pas ton code, donc je ne peux dire si mon explication s'applique à ton code ou c'est autre chose

    En gros, c'est lorsque tu as 2 ou plusieurs *tâches* en parallèle qui s'exécutent. Et en mettant des printf, tu ralentis 1 *tâche* et tu es dans 1 ordre sans bug
    Race condition, lien Wikipédia en anglais
    Après ce n'est pas facile à trouver parce que du code système peut être asynchrone ou non réentrant

    Cela rejoint le voliatile de kaitlyn
    [..] volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation.[...]
    Citation Envoyé par chamludo Voir le message
    Souvent, ce genre de bug provient d'une variable qui est utilisée avant d'être assignée. Elle est donc dans un état indéfini lorsque le programme est lancé
    c'est ton deuxième message, réponse à ma suggestion : *Il me semble que mes variables sont bien initialisées. Et que mon problème ne vienne pas de là*

  18. #18
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 315
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 315
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par chamludo Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void *FonctionAllocation1D(unsigned short dimension, size_t size)
    {
        void *tableau=calloc(dimension, size); //Ce tableau doit etre dynamique et initialisé à 0
        if (tableau != NULL) return tableau;
     
        fprintf(fichierErreur, "Erreur d'allocation du tableau 1D : %s\n", SDL_GetError());
        exit(EXIT_FAILURE); //quitter le programme
    }
    Tu encapsule calloc() dans une fonction qui traite les erreurs éventuelles. Pourquoi pas. Mais tu ne devrais pas quitter le programme ici. C'est brutal . Il vaudrait mieux que tu retournes NULL. C'est la fonction appelante qui doit gérer le problème et qui doit propager cette erreur jusqu'à la fonction main(). Ça semble un peu lourd dit comme ça mais ça permet de désallouer toute la mémoire avant de quitter.

    Ta fonction pourrait alors prendre cette allure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void *FonctionAllocation1D(unsigned short dimension, size_t size)
    {
      void *tableau=calloc(dimension, size); //Ce tableau doit etre dynamique et initialisé à 0
     
      if (tableau == NULL)
        fprintf(fichierErreur, "Erreur d'allocation du tableau 1D : %s\n", SDL_GetError());
     
      return tableau;
    }
    En partant de ce principe la fonction Simulecoup() doit retourner un booléen :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    #include <stdbool.h>
     
    bool SimuleCoup(int niveau, CaracteristiqueJeu Jeu, Case *plateau,Joueur Joueur, Couronne InfoZoneDeRecherche[], DimPlateau DimJeu, int *TabDeCoef,int *AlignementRealise)
    Dans le code source tu testes le retour de l'allocation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (!(ListeCV= FonctionAllocation1D(NbCasesVides, sizeof(*ListeCV)))
      return false;
    Et à la sortie normale de la fonction tu retournes "return true;". Tu utilises ce principe en remontant tout le long du code pour arriver à la fonction main().

    --------------------------------------

    Pour ton histoire d'incertitude crée un tableau local ListeCV. Pour l'instant tu peux te le permettre puisque tu fais des essais sur des petits tableaux. Ça te permettra d'enlever le doute sur le problème d'allocation dans le tas.

  19. #19
    Membre Expert
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    707
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 95
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 707
    Par défaut
    Salut tout le monde

    Citation Envoyé par chamludo Voir le message
    J'espère que cela peut t'aider
    Non, c'est toi que tu aides, mais pas en fournissant les options du mode debug.

  20. #20
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2019
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2019
    Messages : 72
    Par défaut
    Pour Kaitlyn
    gcc.exe -Wextra -Wall -O2 -Iinclude -c "C:\Users\Utilisateur\ProgrammeCodeBlocks\Programme-Essai\morpion-12-NveauIA-SansTournoi-NvelNvel-NbCasesVides-EnCourssssssssssssssssssss - Copie - Copie - Copie\Affichage.c" -o obj\Release\Affichage.o

    gcc.exe -Wextra -Wall -O2 -Iinclude -c "C:\Users\Utilisateur\ProgrammeCodeBlocks\Programme-Essai\morpion-12-NveauIA-SansTournoi-NvelNvel-NbCasesVides-EnCourssssssssssssssssssss - Copie - Copie - Copie\ia.c" -o obj\Release\ia.o


    Cela est-il mieux?

Discussions similaires

  1. gestion d'une erreur
    Par Jeannotc dans le forum Bases de données
    Réponses: 8
    Dernier message: 25/06/2004, 18h04
  2. C++Builder fait une erreur de calcul
    Par gandf dans le forum C++Builder
    Réponses: 7
    Dernier message: 03/01/2004, 22h27
  3. [VB6] Source D'une erreur
    Par krest dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 16/07/2003, 17h33
  4. [procédure PG] Une erreur mystérieuse...ou pas
    Par doohan dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 09/07/2003, 17h16
  5. Ne pas formater une erreur
    Par Sylvain Leray dans le forum XMLRAD
    Réponses: 2
    Dernier message: 18/03/2003, 14h13

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