Esempio n. 1
0
        //Remplie aléatoirement une grille
        protected Jeu[] RempAlea(Random rand)
        {
            //On charche pour quelle case on a le moins de possibilités
            //Pour optimiser l'algorithme on remplie toutes les cases avec une seule possibilité
            //Si on a rempli au moins une case, les possibilités sont diminuées donc on recommence la recherche
            //Enfin s'il n'y a plus que des cases avec plusieurs possibilités, on selectionne celle qui en a le moins
            //On créé une nouvelle grille pour chaque possibilité de la case choisie et on réappelle cette fonction pour essayer de resoudre la grille
            int  i, j;
            bool valeursSimples;

            do
            {
                //On fait les vérifications à chaque itération car une valeur a pu être entrée alors qu'elle est erronnée
                //Si la grille est pleine et sans incohérance, on retourne 1
                if (Possible() && Remplie())
                {
                    //Console.WriteLine("Fin normale");
                    return(new Jeu[] { this });
                }
                //Si elle n'est pas cohérente, on retourne 0
                //Une grille est incohérente si on a une case vide avec aucune possibilité ou plusieurs fois le même chiffre dans des carrés, colonnes ou lignes
                if (!Possible())
                {
                    //Console.WriteLine("Fin impossible");
                    return(new Jeu[0]);
                }
                //On regarde les possibilités
                i = 0;
                j = 0;
                //On réinitialise notre valeur de test de while() pour ne pas avoir de boucle infinie
                valeursSimples = false;
                for (int x = 0; (x < 9); x++)
                {
                    for (int y = 0; (y < 9); y++)
                    {
                        //Si on a une case vide sans valeurs possible la grille est incohérente
                        if (m_tab_jeu[x, y].NbDispo() == 0)
                        {
                            return(new Jeu[0]);
                        }
                        if (m_tab_jeu[x, y].NbDispo() == 1)
                        {
                            //Si on trouve une case avec une seule valeur possible, on rentre cette valeur
                            bool[] temp = m_tab_jeu[x, y].Dispo();
                            //L'ajout d'une valeur a modifié les possibilités des cases sur ses ligne, colonne et carré
                            //Il faut donc revérifier les cases au dessus de celle-ci, c'est pourquoi on recommence la boucle
                            valeursSimples = true;
                            for (int z = 0; z < 9; z++)
                            {
                                if (temp[z])
                                {
                                    Set(x, y, (z + 1));
                                }
                            }
                        }
                        else if ((!valeursSimples) && (m_tab_jeu[x, y].NbDispo() < m_tab_jeu[i, j].NbDispo()))
                        {
                            //On ne continue de chercher la case avec le moins de possibilité que si aucune case ayant une seule possibilité n'a été trouvée
                            //En effet, dans ce cas les probabilités ont changé donc la recherche est faussée pour cette boucle
                            i = x;
                            j = y;
                        }
                    }
                }
            } while (valeursSimples);
            //On fait en fonction des possibilités disponnibles
            bool[] dispo  = m_tab_jeu[i, j].Dispo();
            int    taille = m_tab_jeu[i, j].NbDispo();
            bool   continuer;

            Jeu[] res;
            do
            {
                //On choisie une valeur aléatoire parmi celles disponnibles
                continuer = false;
                int valRand = rand.Next(taille);
                int valeur  = 0;
                for (int k = 0; valeur == 0; k++)
                {
                    if (dispo[k])
                    {
                        if (valRand == 0)
                        {
                            valeur = k + 1;
                        }
                        else
                        {
                            valRand--;
                        }
                    }
                }
                //On regarde si on peut faire une grille avec cette valeur
                Jeu temp = new Jeu(this);
                temp.Set(i, j, valeur);
                res = temp.RempAlea(rand);
                if ((taille > 1) && (res.Length == 0))
                {
                    //Si aucune grille n'a pu être remplie avec cette valeur, on la supprime des possibilités et on recommence
                    taille--;
                    dispo[valeur - 1] = false;
                    continuer         = true;
                }
            } while (continuer);
            //Lorsqu'on arrive là, on a deux possibilités
            // > res est un tableau d'une case contenant la grille aléatoire terminée
            // > res est un tableau de 0 case et le problème sera traité par la fonction précédente dans la récursion
            return(res);
        }
Esempio n. 2
0
        //Masque les cases de la grille en fonction du niveau de difficulté
        protected void Masquer(int difficulte, Random rand)
        {
            bool[] tab = new bool[81];
            for (int i = 0; i < 81; i++)
            {
                tab[i] = true;
            }
            int pos = 81;

            while (pos > 0)
            {
                //On choisit une case au hasard
                int c = rand.Next(pos);
                int x = -1, y = 0;
                for (int n = 0; x == -1; n++)
                {
                    if (tab[n])
                    {
                        if (c == 0)
                        {
                            x = n / 9;
                            y = n % 9;
                        }
                        else
                        {
                            c--;
                        }
                    }
                }
                //On regarde si on peut retirer ce nombre
                bool[] dispo = new bool[9];
                for (int n = 0; n < 9; n++)
                {
                    dispo[n] = true;
                }
                //On regarde les valeurs sur la colonne ainsi que celles sur la ligne
                for (int n = 0; n < 9; n++)
                {
                    int v = ValeurVisible(x, n);
                    if ((v != 0) && (n != y))
                    {
                        dispo[v - 1] = false;
                    }
                    v = ValeurVisible(n, y);
                    if ((v != 0) && (n != x))
                    {
                        dispo[v - 1] = false;
                    }
                }
                //On regarde ensuite sur le carré
                int i = x / 3;
                int j = y / 3;
                for (int k = 0; (k < 3); k++)
                {
                    for (int l = 0; (l < 3); l++)
                    {
                        if (ValeurVisible((3 * i) + k, (3 * j) + l) != 0)
                        {
                            dispo[ValeurVisible((3 * i) + k, (3 * j) + l) - 1] = false;
                        }
                    }
                }
                //On compte le nombre de possibilités
                int res = 0;
                for (int n = 0; n < 9; n++)
                {
                    res += dispo[n] ? 1 : 0;
                }
                //Si on n'a pas plus de possibilités que le niveau de difficulté, on essaye d'enlever le chiffre
                if (res <= difficulte)
                {
                    //On créé une copie pour tester
                    Jeu temp = new Jeu(this);
                    //On enlève la valeur
                    temp.Set(x, y, 0);
                    temp.CalcDispo();
                    if (1 == temp.Solve())
                    {
                        //Si on a toujours une seule grille possible, on enlève la valeur
                        SetChiffreCache(x, y, Valeur(x, y));
                    }
                    else
                    {
                        //Sinon elle est necessaires : on la fixe
                        SetChiffreVisible(x, y, Valeur(x, y));
                    }
                }
                else
                {
                    //Sinon la valeur ne doit pas être modifiée : on la garde
                    SetChiffreVisible(x, y, Valeur(x, y));
                }
                tab[(9 * x) + y] = false;
                pos--;
            }
        }
Esempio n. 3
0
        //Retourne le nombre de grilles possibles avec les valeurs actuelles
        protected int Solve()
        {
            //On charche pour quelle case on a le moins de possibilités
            //Pour optimiser l'algorithme on remplie toutes les cases avec une seule possibilité
            //Si on a rempli au moins une case, les possibilités sont diminuées donc on recommence la recherche
            //Enfin s'il n'y a plus que des cases avec plusieurs possibilités, on selectionne celle qui en a le moins
            //On créé une nouvelle grille pour chaque possibilité de la case choisie et on réappelle cette fonction pour essayer de resoudre la grille
            int  i, j;
            bool valeursSimples;

            do
            {
                //On fait les vérifications à chaque itération car une valeur a pu être entrée alors qu'elle est erronnée
                //Si la grille est pleine et sans incohérance, on retourne 1
                if (Possible() && Remplie())
                {
                    return(1);
                }
                //Si elle n'est pas cohérente, on retourne 0
                //Une grille est incohérente si on a une case vide avec aucune possibilité ou plusieurs fois le même chiffre dans des carrés, colonnes ou lignes
                if (!Possible())
                {
                    return(0);
                }
                //On regarde les possibilités
                i = 0;
                j = 0;
                //On réinitialise notre valeur de test de while() pour ne pas avoir de boucle infinie
                valeursSimples = false;
                for (int x = 0; (x < 9); x++)
                {
                    for (int y = 0; (y < 9); y++)
                    {
                        //Si on a une case vide sans valeurs possible la grille est incohérente
                        if (m_tab_jeu[x, y].NbDispo() == 0)
                        {
                            return(0);
                        }
                        if (m_tab_jeu[x, y].NbDispo() == 1)
                        {
                            //Si on trouve une case avec une seule valeur possible, on rentre cette valeur
                            bool[] temp = m_tab_jeu[x, y].Dispo();
                            //L'ajout d'une valeur a modifié les possibilités des cases sur ses ligne, colonne et carré
                            //Il faut donc revérifier les cases au dessus de celle-ci, c'est pourquoi on recommence la boucle
                            valeursSimples = true;
                            for (int z = 0; z < 9; z++)
                            {
                                if (temp[z])
                                {
                                    //Set(x, y, (z + 1));
                                    SetChiffreVisible(x, y, (z + 1));
                                }
                            }
                        }
                        else if ((!valeursSimples) && (m_tab_jeu[x, y].NbDispo() < m_tab_jeu[i, j].NbDispo()))
                        {
                            //On ne continue de chercher la case avec le moins de possibilité que si aucune case ayant une seule possibilité n'a été trouvée
                            //En effet, dans ce cas les probabilités ont changé donc la recherche est faussée pour cette boucle
                            i = x;
                            j = y;
                        }
                    }
                }
            } while (valeursSimples);
            //On fait en fonction des possibilités disponnibles
            bool[] dispo  = m_tab_jeu[i, j].Dispo();
            int    taille = m_tab_jeu[i, j].NbDispo();
            int    res    = 0;

            //On teste toutes les valeurs
            for (int k = 0; (k < 9) && (res < 2); k++)
            {
                if (dispo[k])
                {
                    //On regarde combien de grilles sont possibles avec cette valeur
                    Jeu temp = new Jeu(this);
                    temp.SetChiffreVisible(i, j, k + 1);
                    res += temp.Solve();
                }
            }
            //res contient le nombre de grilles possibles avec les chiffres de départ (2 s'il y en a 2 ou plus)
            return(res);
        }