Bonjour à tous,
Je vous écris ce message pour vous demander de l'aide au sujet d'un problème .

Je programme un jeu de morpion de taille variable.
J’ai une version qui fonctionne parfaitement.
Je voulais apporter une modification pour simplifier un peu le code et maintenant, le programme ne fonctionne plus correctement.

Voici l’idée générale :
Je définis mes variables, définie 3 tableaux dynamiques
Dans le main, si je clique sur ModifierLesDimensions, cela m’ouvre une nouvelle page dans laquelle je peux modifier les dimensions. Pour sortir de cette page, soit je clique Annuler, soit je clique Valider.
Lorsque je veux valider, je reviens dans le main, vide mes tableaux avec leurs anciennes dimensions, redimensionne les tableaux aux nouvelles dimensions, vide les plateaux avec les nouvelles dimensions puis joue normalement.

Voici mon code qui fonctionne

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
 
int main(int argc, char **argv)
{
    SDL_Surface *ecran=NULL;
    int N=3;
    int M=3;
    int NbJetonsAAligner=3;
    int AncienN=N;
    int AncienM=M;
    int AncienNbJetonsAAligner=NbJetonsAAligner;//on aligne 3 jetons au depart
    Case *plateau;//les Case étant Vide, Crois, Rond
    int *HistoriqueJeton= FonctionAllocation1D(N*M);//Ce tableau doit etre dynamique, efectue le test de bonne attribution
    int *ListeCasesVides= FonctionAllocation1D(N*M);//Tableau qui contient les numeros de toutes les cases vides au debut puis -1 pour les cases occupées.
    int NbCasesJouees=0;
    ...
...
    videJeu(plateau, N, M, ListeJoueurs, &joueurEnCours, &PartieFinie, &NbCasesJouees, HistoriqueJeton, ListeCasesVides);//Vide le plateau de jeu
 
    switch(...)
    {
       case CONFIGDIMENSION:
          joueurEnCours=ListeJoueurs[NbCasesJouees%2];
          AncienN=N;
          AncienM=M;
          AncienNbJetonsAAligner=NbJetonsAAligner;
          ConfigDimension(ecran, police,TypeJeu,PlateauJeuLarg, PlateauJeuHaut, joueurEnCours, &Jeton, &N, &M, &NbJetonsAAligner, &ConfigModifiee);//on ouvre la configuration pour determiner le nombre de lignes et de colonnes du plateau de jeu et le nombre de jetons a aligner pour gagner
          if(ConfigModifiee==OUI)//si on modifie les dimensions du plateau de jeu
               {
                     videJeu(plateau, AncienN, AncienM, ListeJoueurs, &joueurEnCours, &PartieFinie, &NbCasesJouees, HistoriqueJeton, ListeCasesVides);//Vide le plateau de jeu APRES d'avoir modifier les dimensions, pour tout remettre a zero
                     free(plateau);
                     plateau=NULL;
                     plateau=malloc(N*M*sizeof(*plateau));//on realloue un plateau aux nouvelles dimensions
                     if(plateau==NULL)//si erreur d'allocation
                         {
                               free(plateau);//liberation du plateau
                               fprintf(stderr, "Erreur de creation du tableau plateau");
                               exit(EXIT_FAILURE);//quitter le programme
                         }
 
                     free(HistoriqueJeton);//on libere HistoriqueJeu
                     HistoriqueJeton=NULL;
                     HistoriqueJeton= FonctionAllocation1D(N*M);//Ce tableau doit etre dynamique, efectue le test de bonne attribution
 
                     free(ListeCasesVides);//on libere HistoriqueJeu
                     ListeCasesVides=NULL;
                     ListeCasesVides= FonctionAllocation1D(N*M);//Tableau qui contient les numeros de toutes les cases vides au debut puis -1 pour les cases occupées.
 
                     videJeu(plateau, N, M, ListeJoueurs, &joueurEnCours, &PartieFinie, &NbCasesJouees, HistoriqueJeton, ListeCasesVides);//Vide le plateau de jeu AVANT d'avoir modifier les dimensions, sinon, on ne vide pas tout le tableau
                     PlateauJeuLarg=PlateauLarg/maximumEntre(N, M)*N;//Dimension reelle de la zone de jeu quand on personnalise les dimensions
                     PlateauJeuHaut=PlateauHaut/maximumEntre(N, M)*M;
                     ConfigModifiee=NON;
               }
...
    }
   ...
}
Avec
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
 
void videJeu(Case *plateau, int N, int M, Joueur ListeJoueurs[], Joueur *joueurEnCours, int *PartieFinie, int *NbCasesJouees, int *HistoriqueJeton, int *ListeCasesVides)//Fonction pour vider le plateau de jeu
{
    int i;
 
    for(i=0; i<N*M; i++)//On vide le plateau
    {
        plateau[i] = Vide;//toutes les cases sont vides
        HistoriqueJeton[i] = -1;//on reinitialise le tableau a -1
        ListeCasesVides[i]=i;//on liste toutes les cases vides du tableau, c'est a dire toute les cases
    }
    *joueurEnCours=ListeJoueurs[0];
    *NbCasesJouees = 0;
    *PartieFinie = NON;//On commence une nouvelle partie
}
et
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
 
int *FonctionAllocation1D(int dimension)
{
    int *tableau=malloc(dimension*sizeof(*tableau));//Ce tableau doit etre dynamique
    int i;
    if(tableau==NULL)//si erreur d'allocation
    {
        free(tableau);//liberation du tableau 
        fprintf(stderr, "Erreur de creation du tableau ");
        exit(EXIT_FAILURE);//quitter le programme
    }
 
    for (i=0; i<dimension; i++) //On initialise le tableau avec 0
    {
        tableau[i]=0;
    }
 
    return tableau;
}
J’ai voulu remplacer une partie entre les lignes 27 et 52 par une fonction qui gère tout cela (car j’aurai besoin de la réutiliser dans une autre fonction, donc je voulais simplifier plutôt que de réécrire la vingtaine de lignes)
Le main que j’obtiens deviens …

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
 
case CONFIGDIMENSION:
                    joueurEnCours=ListeJoueurs[NbCasesJouees%2];
                    AncienN=N;
                    AncienM=M;
                    AncienNbJetonsAAligner=NbJetonsAAligner;
                    ConfigDimension(ecran, police,TypeJeu,PlateauJeuLarg, PlateauJeuHaut, joueurEnCours, &Jeton, &N, &M, &NbJetonsAAligner, &ConfigModifiee);//on ouvre la configuration pour determiner le nombre de lignes et de colonnes du plateau de jeu et le nombre de jetons a aligner pour gagner
                    if(ConfigModifiee==OUI)//si on modifie les dimensions du plateau de jeu
                    {
                        ModificationConfigDimension(AncienN, AncienM, N,M, plateau, ListeJoueurs,&joueurEnCours, &PartieFinie, &NbCasesJouees, HistoriqueJeton, ListeCasesVides);
                        ConfigModifiee=NON;
                        PlateauJeuLarg=PlateauLarg/maximumEntre(N, M)*N;//Dimension reelle de la zone de jeu quand on personnalise les dimensions
                        PlateauJeuHaut=PlateauHaut/maximumEntre(N, M)*M;
 
                    }
avec
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
 
void ModificationConfigDimension(int AncienN,int AncienM,int NouveauN,int NouveauM,Case *plateau, Joueur ListeJoueurs[], Joueur *joueurEnCours, int *PartieFinie, int *NbCasesJouees, int *HistoriqueJeton, int *ListeCasesVides)
{
    //si seul le NbJetonAAligner a changé, alors on vide le plateau
//si N ou M a changé, il faut tout vider et faire les realloc puis vider le jeu
 
    if((AncienN !=NouveauN)||(AncienM!=NouveauM))
    {
        videJeu(plateau, AncienN, AncienM, ListeJoueurs, joueurEnCours, PartieFinie, NbCasesJouees, HistoriqueJeton, ListeCasesVides);//Vide le plateau de jeu AVANT d'avoir modifier les dimensions, pour tout remettre a zero
        free(plateau);
        plateau=NULL;
        plateau=malloc(NouveauN*NouveauM*sizeof(*plateau));//on realloue un plateau aux nouvelles dimensions
        if(plateau==NULL)//si erreur d'allocation
        {
            free(plateau);//liberation du plateau
            fprintf(stderr, "Erreur de creation du tableau plateau");
            exit(EXIT_FAILURE);//quitter le programme
        }
 
        free(HistoriqueJeton);//on libere HistoriqueJeu
        HistoriqueJeton=NULL;
        HistoriqueJeton= FonctionAllocation1D(NouveauN*NouveauM);//Ce tableau doit etre dynamique
 
        free(ListeCasesVides);//on libere ListeCasesVides
        ListeCasesVides=NULL;
        ListeCasesVides= FonctionAllocation1D(NouveauN*NouveauM);//Tableau qui contient les numeros de toutes les cases vides au debut puis -1 pour les cases occupées.
 
    }
    videJeu(plateau, NouveauN, NouveauM, ListeJoueurs, joueurEnCours, PartieFinie, NbCasesJouees, HistoriqueJeton, ListeCasesVides);//Vide le plateau de jeu APRES d'avoir modifier les dimensions, sinon, on ne vide pas tout le tableau
 
}


Je n’ai pas d’alerte au moment de la compilation.
Sauf que lorsque je redimensionne, j’ai parfois quelques jetons qui se placent sur le plateau et certaines cases ne sont pas accessibles.
Mais surtout, lorsque je redimensionne encore une fois, ou lorsque je vide le jeu suite à une nouvelle partie, le programme plante.
Il semblerait qu’il y ait des erreurs au niveau de free(HistoriqueJeton) et free(ListeCasesVides).
Je pencherai au niveau d'un problème de passage de paramètres/pointeurs à la fonction videJeu ou au moment de la création des tableaux avec les nouvelles dimensions.

Je vous remercie de l'aide que vous pourrez m'apporter.
Cordialement
Ludovic