//Créé une copie de la grille en paramètre public Grille(Grille g) { Init(); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { m_cases[i, j].Set(g.Get(i, j)); } } }
//Retourne la liste des solutions possibles public int NbSolve() { //On regarde pour quelle case on a le moins de possibilités //On en profite pour remplir toutes les cases avec une seule possibilites //Si on a rempli au moins une case, les possibilités sont diminuées donc on recommence int i, j; bool valeursSimples; Console.WriteLine("Nb possibles : " + m_cases[4, 4].NbDispo()); do { //On fait les vérifications à chaque itération qui a pu changer une valeur //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 if (!Possible()) { return(0); } //On regarde les possibilités i = 0; j = 0; //On réinitialise notre valeur pour ne pas avoir de boucle infinie valeursSimples = false; for (int x = 0; (x < 9); x++) { for (int y = 0; (y < 9); y++) { if (m_cases[x, y].NbDispo() == 0) { return(0); } if (m_cases[x, y].NbDispo() == 1) { bool[] temp = Possibilites(x, y); valeursSimples = true; for (int z = 0; z < 9; z++) { if (temp[z]) { Set(x, y, (z + 1)); } } } else if ((!valeursSimples) && (m_cases[x, y].NbDispo() < m_cases[i, j].NbDispo())) { i = x; j = y; } } } } while (valeursSimples); //On fait en fonction des possibilités disponnibles bool[] dispo = Possibilites(i, j); int res = 0; for (int k = 0; k < 9; k++) { Console.WriteLine((1 + k) + " " + (dispo[k] ? "dispo" : "pas dispo")); if (dispo[k]) { Console.WriteLine("Supposition : " + (k + 1)); Grille temp = new Grille(this); temp.Set(i, j, (k + 1)); res += temp.NbSolve(); } } return(res); }
//Retourne la liste des solutions possibles public Grille[] 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; Console.WriteLine("Nb possibles : " + m_cases[4, 4].NbDispo()); 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(new Grille[0]); } //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(new Grille[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_cases[x, y].NbDispo() == 0) { return(new Grille[0]); } if (m_cases[x, y].NbDispo() == 1) { //Si on trouve une case avec une seule valeur possible, on rentre cette valeur bool[] temp = Possibilites(x, y); //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_cases[x, y].NbDispo() < m_cases[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 = Possibilites(i, j); Grille[] res = new Grille[0]; for (int k = 0; k < 9; k++) { if (dispo[k]) { Grille temp = new Grille(this); temp.Set(i, j, (k + 1)); Grille[] rTemp = temp.Solve(); int taille = res.Length + rTemp.Length; Grille[] resTemp = new Grille[taille]; for (int a = 0; a < taille; a++) { resTemp[a] = (a < res.Length) ? res[a] : rTemp[a - res.Length]; } res = resTemp; } } return(res); }