Aller au menu - Aller au contenu

[Plan du site] Vous êtes ici --- > Le Site du Zéro > Les forums > Concours > Le Sudoku : des nombres en folie ! > Résolution de grille > Lecture du sujet

Résolution de grille

Problème avec mon algo

Vous devez être inscrit pour pouvoir poster des messages

Page : 1 
Auteur Message
1 visiteur sur ce sujet (1 anonyme)
Page : 1 
Hors ligne Hugo12 # Posté le 25/07/2008 à 13:33:10
Avatar
Groupe : Membres
Salut,

je suis occupé à créer la fonction de résolution de grille pour mon sudoku. Je commence par créer un code qui ne s'occupe que des lignes pour faciliter les tests. Lorsque je test, c'est avec une grille super simple à laquelle il ne manque qu'une case. Mais voilà, le programme ne parvient jamais à résoudre la grille. J'ai beau relire dix fois mon code, je ne parviens pas à trouver mon erreur.

Voici mon code :

Code : C++
  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
void Fenetre::resoudreGrille()
{
    int nombreValeur = 1;
    bool changement = false;//Tant qu'il n'y aura pas de changement, cette variable vaudra false
    int nombreCase = 0;
    bool erreur = false;

    while ( nombreValeur <=9 )
    {
        for ( y=0 ; y<9 ; y++ )         //exploration de toutes les lignes
        {
            for ( x=0 ; x<9 ; x++ ) //exploration de toutes les cases de la ligne
            {
                if ( nombrePossibilite(x, y) == nombreValeur )
                {
                    int x2 = 0;
                    for ( x2=0 ; x2<9 ; x2++)
                    {
                        if ( isIn( m_grille[x2][y], m_grille[x][y] )==true) //Si les valeurs possible pour cette case se retrouvent dans les valeurs de la case de départ
                        {
                            nombreCase++;
                        }
                    }
                    if (nombreCase > nombreValeur) //si il n'y a pas assez de valeur pour les cases, il y a un problème
                    {
                        erreur = true;
                        x=9;//              |
                        y=9;//              |  On force le programme à sortir des boucles
                        nombreValeur=10;//  |
                    }
                    else if (nombreCase == nombreValeur) //Si il y a juste assez de valeurs pour les cases, on retire ces valeurs à toutes les autres cases de la zone
                    {
                        for ( x2=0 ; x2<9 ; x2++)
                        {
                            if ( isIn( m_grille[x2][y], m_grille[x][y] )==false) //Si la case n'est pas une de celle sur laquelle on a travaillé, on supprime les valeurs possible retenue précédemment
                            {
                                supprimerValeur(m_grille[x][y], m_grille[x2][y]);
                                changement = true;
                            }
                        }
                    }
                    nombreCase = 0;//On réinitialise le nombre de case
                }
            }
        }



        if(changement==false)//Si il n'y a pas de changement, on augmente le nombre de valeur
        {
            nombreValeur++;
        }
        else //Sinon on recommence tout à 0 en conbsidérant les modifs
        {
            nombreValeur=1;
        }
    }
    /*Il ne reste plus qu'à mettre les solution dans les cases*/

    for (x=0 ; x<9 ; x++)
    {
        for (y=0 ; y<9 ; y++)
        {
            if(nombrePossibilite(x,y) == 1)
            {
                m_infos[x][y]= valeurPossible(m_grille[x][y]);
                m_label[x][y]->changerTexte(m_infos[x][y]);
            }
            else
            {
                erreur = true;
                x=9;
                y=9;
            }
        }
    }

    /*La résolution est terminée. On vérifie maintenant si il n'y a pas eu d'erreur */

    if (erreur==true)
    {
        QMessageBox::critical(this, "Erreur", "Cette grille est insoluble. Soit parce qu'elle comporte des erreurs, soit parce qu'elle possède un nombre de solution différent de 1.");
    }
}

int Fenetre::nombrePossibilite( int cx, int cy)
{
    int i=0;
    int nbr=0;
    for ( i=0 ; i<9 ; i++ )
    {
        if ( m_grille[cx][cy][i] == true )//si cette valeur est possible
        {
            nbr++;
        }
    }
    return nbr;
}

bool Fenetre::isIn( bool *tableau1, bool *tableau2 )//Cette fonction renvoie true si le tableau 1 est dans le tableau 2
{
    int i=0;

    for(i=0 ; i<9 ; i++)
    {
        if ( tableau1[i]==true && tableau2[i]==false)
        {
            return false;
        }
    }
    return true;
}

void Fenetre::supprimerValeur ( bool *tableau1, bool *tableau2 )//Cette fonction sert à supprimer les valeurs contenue dans tableau1 au tableau2
{
    int i=0;

    for  (i=0 ; i<9 ; i++)
    {
        if(tableau1[i]==true)
        {
            tableau2[i]=false;
        }
    }
}

int Fenetre::valeurPossible(bool *tableau)//Cette fonction renvoie la dernière valeur possible
{
    int i=0;
    int valeur=1;

    for(i=0 ; i<9 ; i++)
    {
        if (tableau[i]==true)
        {
            valeur= i+1;
        }
    }
    return valeur;
}


Ce qu'il faut savoir, c'est que m_grille[x][y] contient pour chaque case un tableau de 9 booléens. Le premier booléen vaut true si la valeur 1 est possible pour la case, le deuxième true si la valeur 2 est possible pour la case et ainsi de suite.

J'ai donc décidé de tester en changeant à chaque fois quelques lignes de codes pour voir d 'où venait mon erreur. Apparemment, c'est les tableau contenu dans m_grille[x][y] qui ne contiennet que des false.

Quelqu'un pourrait il m'aider parce que là je suis vraiment perdu.

Merci !

Citation : Inconnu
Vivez vos rêves, ne rêvez pas votre vie...
Connaisseur en Mindstorms NXT ? Envie d'en faire un tuto ? Contactez-moi !
 
Hors ligne Thibdumont # Posté le 25/07/2008 à 16:28:41
Groupe : Membres
Tu ne veux pas utiliser du backtracking comme la plupart des personnes ?
Si oui, fais une recherche pour connaitre le principe de l'algo.
Sinon, bonne chance pour résoudre ton problème car ça m'a l'air d'être un beau bordel. :o

Maps "rats" salon Image utilisateur et cuisine Image utilisateur
 
Hors ligne Hugo12 # Posté le 25/07/2008 à 17:26:44
Avatar
Groupe : Membres
Citation : Thibdumont
Tu ne veux pas utiliser du backtracking comme la plupart des personnes ?
Si oui, fais une recherche pour connaitre le principe de l'algo.
Sinon, bonne chance pour résoudre ton problème car ça m'a l'air d'être un beau bordel. :o


J'aimerais bien créer ma propre méthode pour le résoudre mais si je n'arrive pas à régler mon problème je me pencherai sur une autre méthode.

Citation : Inconnu
Vivez vos rêves, ne rêvez pas votre vie...
Connaisseur en Mindstorms NXT ? Envie d'en faire un tuto ? Contactez-moi !
 
Hors ligne Alanis # Posté le 25/07/2008 à 18:04:06
Groupe : Membres
Citation : Hugo12
Citation : Thibdumont
Tu ne veux pas utiliser du backtracking comme la plupart des personnes ?
Si oui, fais une recherche pour connaitre le principe de l'algo.
Sinon, bonne chance pour résoudre ton problème car ça m'a l'air d'être un beau bordel. :o


J'aimerais bien créer ma propre méthode pour le résoudre mais si je n'arrive pas à régler mon problème je me pencherai sur une autre méthode.


Tu sais , l'informatique c repompé le boulot des autres ;)
Hors ligne heero78 # Posté le 25/07/2008 à 18:06:04
Clique sur mon avatar. ;)
Avatar
Groupe : Membres
Moi je suis tout avec toi ^^ le backtracking est simple à mettre en œuvre mais niveau efficacité, bin y'a vraiment beaucoup mieux. :)

Ce que je te propose c'est que tu nous fournisse un code prêt pour les test, genre avec une initialisation de tes variables parce que la je ne sais pas trop à quoi elle ressembles (tu l'es utilise mais elle ne sont pas crée dans la partie du code que tu nous a fourni ^^')

m_grille[9][9][9] je suppose ? initialiser à true ? sauf pour les case déjà pleines ? bon bref ^^

Bonne chance
 
Hors ligne Hugo12 # Posté le 26/07/2008 à 11:36:59
Avatar
Groupe : Membres
Voila le code,

il suffit d'appeler la fonction resoudreGrille en lui fournissant un tableau de neuf case sur neuf de type : tableau [9][9]. Chaque case contenant soit 0 soit un chiffre de 1 à 9. La fonction modifie le tableau fourni.

Code : C++
  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
void resoudreGrille(int *grillePrincipale)
{
    int nombreValeur = 1;
    bool changement = false;//Tant qu'il n'y aura pas de changement, cette variable vaudra false
    int nombreCase = 0, x=0, y=0;
    bool erreur = false;
    
    /*Création des variables m_grille et m_infos*/
    
    bool *m_grille[9][9];
    int m_infos[9][9];
    
    for (x=0 ; x<9 ; x++)
    {
        for (y=0 ; y<9 ; y++)
        {
            if(grillePrincipale[x][y] == 0)
            {
                bool tableau[9]={true, true, true, true, true, true, true, true, true};
                m_grille[x][y]=tableau;
            }
            else
            {
                bool tableau[9]={false, false, false, false, false, false, false, false, false};
                tableau[grillePrincipale[x][y]-1] = true;
                m_grille[x][y]=tableau;
            }
        }
    }

    while ( nombreValeur <=9 )
    {
        for ( y=0 ; y<9 ; y++ )         //exploration de toutes les lignes
        {
            for ( x=0 ; x<9 ; x++ ) //exploration de toutes les cases de la ligne
            {
                if ( nombrePossibilite(m_grille[x][y]) == nombreValeur )
                {
                    int x2 = 0;
                    for ( x2=0 ; x2<9 ; x2++)
                    {
                        if ( isIn( m_grille[x2][y], m_grille[x][y] )==true) //Si les valeurs possible pour cette case se retrouvent dans les valeurs de la case de départ
                        {
                            nombreCase++;
                        }
                    }
                    if (nombreCase > nombreValeur) //si il n'y a pas assez de valeur pour les cases, il y a un problème
                    {
                        erreur = true;
                        x=9;//              |
                        y=9;//              |  On force le programme à sortir des boucles
                        nombreValeur=10;//  |
                    }
                    else if (nombreCase == nombreValeur) //Si il y a juste assez de valeurs pour les cases, on retire ces valeurs à toutes les autres cases de la zone
                    {
                        for ( x2=0 ; x2<9 ; x2++)
                        {
                            if ( isIn( m_grille[x2][y], m_grille[x][y] )==false) //Si la case n'est pas une de celle sur laquelle on a travaillé, on supprime les valeurs possible retenue précédemment
                            {
                                supprimerValeur(m_grille[x][y], m_grille[x2][y]);
                                changement = true;
                            }
                        }
                    }
                    nombreCase = 0;//On réinitialise le nombre de case
                }
            }
        }



        if(changement==false)//Si il n'y a pas de changement, on augmente le nombre de valeur
        {
            nombreValeur++;
        }
        else //Sinon on recommence tout à 0 en conbsidérant les modifs
        {
            nombreValeur=1;
        }
    }
    /*Il ne reste plus qu'à mettre les solution dans les cases*/

    for (x=0 ; x<9 ; x++)
    {
        for (y=0 ; y<9 ; y++)
        {
            if(nombrePossibilite(m_grille[x][y]) == 1)
            {
                grillePrincipale[x][y]= valeurPossible(m_grille[x][y]);
            }
            else
            {
                erreur = true;
                x=9;
                y=9;
            }
        }
    }

    /*La résolution est terminée. On vérifie maintenant si il n'y a pas eu d'erreur */

    if (erreur==true)
    {
        QMessageBox::critical(this, "Erreur", "Cette grille est insoluble. Soit parce qu'elle comporte des erreurs, soit parce qu'elle possède un nombre de solution différent de 1.");
    }
}

int nombrePossibilite( bool *tableau )
{
    int i=0;
    int nbr=0;
    for ( i=0 ; i<9 ; i++ )
    {
        if ( tableau[i] == true )//si cette valeur est possible
        {
            nbr++;
        }
    }
    return nbr;
}

bool isIn( bool *tableau1, bool *tableau2 )//Cette fonction renvoie true si le tableau 1 est dans le tableau 2
{
    int i=0;

    for(i=0 ; i<9 ; i++)
    {
        if ( tableau1[i]==true && tableau2[i]==false)
        {
            return false;
        }
    }
    return true;
}

void supprimerValeur ( bool *tableau1, bool *tableau2 )//Cette fonction sert à supprimer les valeurs contenue dans tableau1 au tableau2
{
    int i=0;

    for  (i=0 ; i<9 ; i++)
    {
        if(tableau1[i]==true)
        {
            tableau2[i]=false;
        }
    }
}

int valeurPossible(bool *tableau)//Cette fonction renvoie la dernière valeur possible
{
    int i=0;
    int valeur=1;

    for(i=0 ; i<9 ; i++)
    {
        if (tableau[i]==true)
        {
            valeur= i+1;
        }
    }
    return valeur;
}

Citation : Inconnu
Vivez vos rêves, ne rêvez pas votre vie...
Connaisseur en Mindstorms NXT ? Envie d'en faire un tuto ? Contactez-moi !
 
Hors ligne heero78 # Posté le 26/07/2008 à 16:41:35
Clique sur mon avatar. ;)
Avatar
Groupe : Membres
Lut bon j'ai fait quelque modifications, ton code réagi mieux (il n'y a pu d'erreur généré), mais il par en boucle infinie.
Donc a partir de la je pense que c'est a toi de trouver le problème ^^

main.cpp :Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <QtGui>
#include "Fenetre.h"

int main(int argc, char *argv[]){

    QApplication app(argc, argv);

    Fenetre *fenetre = new Fenetre();
    fenetre->show();

    return app.exec();
}


Fenetre.h :Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#ifndef FENETRE_H_INCLUDED
#define FENETRE_H_INCLUDED

#include <QtGui>

class Fenetre : public QWidget{
    public:
        Fenetre();
        void afficherGrille(int grille[][9]);
        void resoudreGrille(int grillePrincipale[][9]);
        int nombrePossibilite( bool tableau[][9][9], int x, int y);
        bool isIn(bool tableau[][9][9], int x1, int y1, int x2, int y2);
        void supprimerValeur (bool tableau[][9][9], int x1, int y1, int x2, int y2);
        int valeurPossible(bool tableau[][9][9], int x, int y);

    private:
        bool m_grille[9][9][9];
};

#endif // FENETRE_H_INCLUDED


Fenetre.cpp :Code : C++
  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
#include "Fenetre.h"

Fenetre::Fenetre(){
    QWidget(this);

    int grille[9][9];
    int tab[81] = {3,8,6,0,0,2,1,9,0,5,0,1,3,6,0,0,0,8,0,0,4,0,8,1,0,0,0,1,0,0,0,4,0,8,0,0,0,0,7,0,0,0,0,0,0,6,0,0,0,1,5,3,4,7,0,0,0,0,0,6,2,0,4,0,0,0,1,0,0,0,7,0,9,4,5,2,0,7,0,8,0};

    for(int i=0; i<9; i++){
        for(int j=0; j<9; j++){
            grille[i][j] = tab[i*9+j];
        }
    }

    resoudreGrille(grille);
    afficherGrille(grille);

    qApp->quit();
}
void Fenetre::afficherGrille(int grille[][9]){
    QString str(0);
    for(int i=0; i<9; i++){
        for(int j=0; j<9; j++){
            str += QString::number(grille[i][j])+"|";
        }
        str += "<br />";
    }
    QMessageBox::warning(this, "Grille", str);
}
void Fenetre::resoudreGrille(int grillePrincipale[][9]){
    int nombreValeur = 1;
    bool changement = false;//Tant qu'il n'y aura pas de changement, cette variable vaudra false
    int nombreCase = 0, x=0, y=0, z=0;
    bool erreur = false;

    /*Création des variables m_grille*/

    bool m_grille[9][9][9];

    for (x=0 ; x<9 ; x++){
        for (y=0 ; y<9 ; y++){
            if(grillePrincipale[x][y] == 0){
                for(z=0; z<9; z++){
                    m_grille[x][y][z] = true;
                }
            }else{
                for(z=0; z<9; z++){
                    m_grille[x][y][z] = false;
                }
                m_grille[x][y][grillePrincipale[x][y]-1] = true;
            }
        }
    }

    while ( nombreValeur <=9 ){
        changement = false; // Petit ajout utile si tu ne veux pas partir en boucle infinie ^^
        for ( y=0 ; y<9 ; y++ ){         //exploration de toutes les lignes
            for ( x=0 ; x<9 ; x++ ){ //exploration de toutes les cases de la ligne
                if ( nombrePossibilite(m_grille, x, y) == nombreValeur ){
                    int x2 = 0;
                    for ( x2=0 ; x2<9 ; x2++){
                        if ( isIn( m_grille, x2, y, x, y) ){ //Si les valeurs possible pour cette case se retrouvent dans les valeurs de la case de départ
                            nombreCase++;
                        }
                    }
                    if (nombreCase > nombreValeur){ //si il n'y a pas assez de valeur pour les cases, il y a un problème
                        erreur = true;
                        x=9;//              |
                        y=9;//              |  On force le programme à sortir des boucles
                        nombreValeur=10;//  |
                    }else if (nombreCase == nombreValeur){ //Si il y a juste assez de valeurs pour les cases, on retire ces valeurs à toutes les autres cases de la zone
                        for ( x2=0 ; x2<9 ; x2++){
                            if ( !isIn(m_grille, x2, y, x, y) ){ //Si la case n'est pas une de celle sur laquelle on a travaillé, on supprime les valeurs possible retenue précédemment
                                supprimerValeur(m_grille, x, y, x2, y);
                                changement = true;
                            }
                        }
                    }
                    nombreCase = 0;//On réinitialise le nombre de case
                }
            }
        }



        if(!changement){//Si il n'y a pas de changement, on augmente le nombre de valeur
            nombreValeur++;
        }else{ //Sinon on recommence tout à 0 en conbsidérant les modifs
            nombreValeur = 1;
        }
    }
    /*Il ne reste plus qu'à mettre les solution dans les cases*/

    for (x=0 ; x<9 ; x++){
        for (y=0 ; y<9 ; y++){
            if(nombrePossibilite(m_grille, x, y) == 1){
                grillePrincipale[x][y] = valeurPossible(m_grille, x, y);
            }else{
                erreur = true;
                x=9;
                y=9;
            }
        }
    }

    /*La résolution est terminée. On vérifie maintenant si il n'y a pas eu d'erreur */

    if (erreur){
        QMessageBox::critical(this, "Erreur", "Cette grille est insoluble. Soit parce qu'elle comporte des erreurs, soit parce qu'elle possède un nombre de solution différent de 1.");
    }
}

int Fenetre::nombrePossibilite( bool tableau[][9][9], int x, int y ){
    int nbr=0;
    for (int i=0 ; i<9 ; i++ ){
        if ( tableau[x][y][i] == true){//si cette valeur est possible
            nbr++;
        }
    }
    return nbr;
}

bool Fenetre::isIn(bool tableau[][9][9], int x1, int y1, int x2, int y2){//Cette fonction renvoie true si le tableau 1 est dans le tableau 2
    for(int i=0 ; i<9 ; i++){
        if ( tableau[x1][y1][i]==true && tableau[x2][y2][i]==false){
            return false;
        }
    }
    return true;
}

void Fenetre::supprimerValeur (bool tableau[][9][9], int x1, int y1, int x2, int y2){//Cette fonction sert à supprimer les valeurs contenue dans tableau1 au tableau2
    for  (int i=0 ; i<9 ; i++){
        if(tableau[x1][y1][i]){
            tableau[x2][y2][i] = false;
        }
    }
}

int Fenetre::valeurPossible(bool tableau[][9][9], int x, int y){//Cette fonction renvoie la dernière valeur possible
    int valeur=1;

    for(int i=0 ; i<9 ; i++){
        if (tableau[x][y][i]==true){
            valeur= i+1;
        }
    }
    return valeur;
}
 
Hors ligne Hugo12 # Posté le 30/07/2008 à 15:35:38
Avatar
Groupe : Membres
Merci de ton aide. Je vais essayer de terminer cette fonction à temps.

Citation : Inconnu
Vivez vos rêves, ne rêvez pas votre vie...
Connaisseur en Mindstorms NXT ? Envie d'en faire un tuto ? Contactez-moi !
 

Retour au forum "Le Sudoku : des nombres en folie !" ou à la liste des forums

Vous devez être inscrit pour pouvoir poster des messages

Changer de design | En savoir plus | Plan du site | Politique d'accessibilité | Règles | RSS tutoriels | RSS news
Édité par Simple IT SARL : Nous contacter | Notre blog | Revue de presse | Publicité

Y'a plus rien à lire, faut remonter maintenant !

Hébergement web - Correction de tutoriels - Créer un site
Vous souhaitez apparaître ici ? Contactez-nous.

Nombre de connectés 418 Zéros connectés | Requêtes SQL 5 requêtes | Temps de génération de la page : Total (SQL) 0.032s (0.0083s)