using System; using System.Collections.Generic; using System.Text; namespace SudokuProc { class Program { private static Random randomG = new Random(); static int[,] Grille = new int[9, 9]; static bool[,] Verrou = new bool[9, 9]; static bool[,] verrouUtilisateur = new bool[9, 9]; static bool GameStarted = false; static bool modeFacile; static bool[,] Suggested = new bool[9,9]; static int[,] Suggestion = new int[9,9]; static int[,] Historique = new int[500,3]; //Historique de toutes les actions durant la partie //[x,0]=ligne [x,1]=colonne [x,2]=chiffre static int nbActions; //nombre d'actions totales de l'utilisateur durant la partie static bool[,] Change = new bool[9, 9]; //Cases qui ont changé après résolution de l'impasse static void Main(string[] args) { //Initialisation de la fenêtre Console.Clear(); Console.Title = "TP1 - Sudoku!"; Console.SetWindowSize(120, 50); //intro Console.WriteLine("*********************TP1 - Sudoku!*********************\n"); while (true) { AfficherMenu(); if (GameStarted) { switch (EntreeChoix(1, 7)) { case 1: //Continuer la partie Jouer(); break; case 2: //Ecrire une solution GenererGrille(0, verrouUtilisateur); AfficherGrille(); NettoyerGrille(verrouUtilisateur); Console.WriteLine("Appuyez sur une touche pour continuer..."); Console.ReadLine(); Jouer(); break; case 3: //reset la grille ResetGrille(); Jouer(); break; case 4: //Voir l'historique des coups joués VoirHistorique(); Jouer(); break; case 5: //Nouvelle partie, Jeu normal InitialiserGrille(); modeFacile = false; Jouer(); break; case 6: //Nouvelle partie, Jeu facile InitialiserGrille(); modeFacile = true; Jouer(); break; case 7: //Quitter Console.WriteLine("Merci d'avoir jouer à TP1 - Sudoku!"); return; } } else { switch (EntreeChoix(1, 3)) { case 1: //Jeu normal InitialiserGrille(); modeFacile = false; Jouer(); break; case 2: //Jeu facile InitialiserGrille(); modeFacile = true; Jouer(); break; case 3: //Quitter Console.WriteLine("Merci d'avoir jouer à TP1 - Sudoku!"); return; } } //### Ajouter une exception ici } } /// /// Affiche un menu /// static void AfficherMenu() { if (GameStarted) { Console.WriteLine("1) Continuer la partie"); Console.WriteLine("2) Écrire une solution à la partie en cours"); Console.WriteLine("3) Reset la grille"); Console.WriteLine("4) Voir l'historique des coups joués"); Console.WriteLine("5) Démarrer une nouvelle partie"); Console.WriteLine("6) Démarrer une nouvelle partie en mode facile"); Console.WriteLine("7) Quitter"); } else { Console.WriteLine("1) Démarrer une nouvelle partie"); Console.WriteLine("2) Démarrer une nouvelle partie en mode facile"); Console.WriteLine("3) Quitter"); } Console.Write("Votre choix : "); } /// /// Lis un chiffre entré par l'utilisateur /// /// Borne inférieur, inclusive, 1+ /// Borne supérieure, inclusive /// La valeur entrée static int EntreeChoix(int p_Min, int p_Max) { int chiffre; while (true) { chiffre = Convert.ToInt32(Console.ReadLine(),10); if (chiffre == 0) { //Entrée invalide Console.WriteLine("Vous devez entrer un chiffre entre {0} et {1}.", p_Min, p_Max); } else { if ((chiffre >= p_Min) && (chiffre <= p_Max)) { return chiffre; } else { //Chiffre hors limites Console.WriteLine("La valeur entrée doit être entre {0} et {1}.", p_Min, p_Max); } } } } /// /// Génère un grille de départ puis cacher des cases. /// static void InitialiserGrille() { //Initialisation des tables for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { Grille[i, j] = 0; Verrou[i, j] = false; //Dévérouiller toutes les cases. Nécessaire pour la génération de grille. verrouUtilisateur[i, j] = false; } } GenererGrille(0,Verrou); CacherCases(); //verrouUtilisateur doit correspondre au Verrou en debut de partie for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { verrouUtilisateur[i, j] = Verrou[i, j]; } } //Remettre l'historique a 0 for (int i = 0; i < 500; i++) { Historique[i, 0] = 0; Historique[i, 1] = 0; Historique[i, 2] = 0; } nbActions = 0; } /// /// Fonction récursive. Place des numeros dans la grille /// pour obtenir une grille de sudoku valide. /// /// Itérateur pour indiquer la case où l'on est rendu. Mettre /// a 0 pour commencer du début. /// Tableau indiquant les cases à ne pas modifier /// TRUE une valeur à été placée avec succès. FALSE si les posibilités sont épuisées sans succès. static bool GenererGrille(int p_compteur, bool[,] p_verrou) { //Condition de sortie if (p_compteur == 81) { return true; } int rangee = p_compteur / 9; int col = p_compteur % 9; int numChoisi; bool[] utilise = new bool[9]; int essais = 0; do { while (true) { if (essais == 9) //Tout les nombre ont été essayé { if (!p_verrou[rangee, col]) { Grille[rangee, col] = 0; } return false; } if (p_verrou[rangee, col]) { //Si la case est vérouillée, on enregistre le nombre d'essai à 9. //Tout les nombres ont été essayé. Le programme considère alors //qu'il n'y a pas de modification possible. essais = 9; break; } else { do { numChoisi = randomG.Next(1, 10); } while (utilise[numChoisi - 1]); utilise[numChoisi - 1] = true; //vérouille le nombre selectionner pour qu'il ne soit pas réutilisé. essais++; if (Check(rangee, col, numChoisi) == 0) { Grille[rangee, col] = numChoisi; break; } } } } while (!GenererGrille(p_compteur + 1, p_verrou)); return true; } /// /// /// /// /// static bool GenGrid(int position) { Random NumRand = new Random(); int num; int line = position / 9; int col = position % 9; num = NumRand.Next(1, 10); for (int i = 0; i < 9; ++i) { /* Si le nombre est valide pour la grille, l'inscrire dans la * grille et appeler GenGrille de nouveau en incrementant la * position. Sinon, essayer un autre chiffre. */ if (Check(line, col, num) == 0) { if (position == 80) { Grille[line, col] = num; return true; } else { Grille[line, col] = num; if (GenGrid(position + 1) == true) { return true; } else { Grille[line, col] = 0; } } } /* Si le numero est 9, le mettre a 1, sinon l'incrementer pour le prochain essai */ if (num == 9) { num = 1; } else { ++num; } } return false; //Tous les chiffres de 1 a 9 ont ete essayes sans succes. } /// /// Cache des cases au hasard dans la grille et vérouille le reste. /// static void CacherCases() { int casesCache = 0; int casesACacher; int line; int col; //On vérouille toutes les case, on va ensuite dévérouiller les cases où on cache des chiffres. for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { Verrou[i, j] = true; } } for (int regionH = 0; regionH < 9; regionH = regionH + 3) //Bloc de 3 ligne { for (int regionV = 0; regionV < 9; regionV = regionV + 3) //Bloc de 3 colonnes { casesCache = 0; casesACacher = randomG.Next(4, 8); while (casesCache != casesACacher) { line = randomG.Next(0, 3) + regionH; col = randomG.Next(0, 3) + regionV; if (Verrou[line, col]) //Ignorer si la case est dévérouillée, donc déja cachée { Grille[line, col] = 0; casesCache++; Verrou[line, col] = false; } } } } } /// /// Vérifie si un chiffre peut être placer dans une certaine case selon les règles du Sudoku /// /// Ligne de la case /// Colonne de la case /// Valeur à vérifier /// 0 si possible, 1 si erreur dans la région, 2 si erreur dans la ligne, 3 si erreur dans la colonne static int Check(int p_Ligne, int p_Col, int p_Nombre) { //check la region 3x3 int regionV = (p_Ligne - (p_Ligne % 3)); int regionH = (p_Col - (p_Col % 3)); for (int i = regionV; i < regionV + 3; i++) { for (int j = regionH; j < regionH + 3; j++) { if (Grille[i, j] == p_Nombre) return 1; } } //check ligne for (int i = 0; i < 9; i++) { if (Grille[p_Ligne, i] == p_Nombre) return 2; } //check colonne for (int i = 0; i < 9; i++) { if (Grille[i, p_Col] == p_Nombre) return 3; } //Réussi return 0; } /// /// Lit et enregistre les modification à la grille de jeu. /// /// TRUE pour le mode facile static void Jouer() { int line; int col; int valeurEntre; char[] delimiterChars = { ' ', ',', '.', ':', '\t', ';' }; string[] Valeurs; bool gridFull = false; //flag qui indique que toutes les cases sont occupees, partie terminee GameStarted = true; //partie en cours Console.WriteLine("\nVoici votre grille : \n"); //Boucler jusqu'a ce que toutes les cases soient occupees while (!gridFull) { AfficherGrille(); Console.WriteLine("Que voulez-vous modifier? (ligne, colonne, valeur) \"Enter\" pour retourner au menu, \"s\" pour suggerer une action, \"d\" pour défaire la dernière action"); Valeurs = Console.ReadLine().Split(delimiterChars); //L'utilisateur a appuye sur "Enter", retourner au menu if (Valeurs[0] == "") { return; } ////L'utilisateur desire retourner au menu //if((Valeurs[0] == "m")||(Valeurs[0] == "M")) //{ // return; //} //L'utilisateur veut defaire la derniere action else if((Valeurs[0] == "d") || (Valeurs[0] == "D")) { undo(); continue; } //L'utilisateur desire une suggestion pour sa prochaine action else if ((Valeurs[0] == "s") || (Valeurs[0] == "S")) { SuggestMove(); continue; } line = Convert.ToInt32(Valeurs[0])-1; col = Convert.ToInt32(Valeurs[1])-1; valeurEntre = Convert.ToInt32(Valeurs[2]); //verifier si les chiffres entres sont corrects if ((line < 0) || (line > 8) || (col < 0) || (col > 8) || (valeurEntre < 0) || (valeurEntre > 9)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("\n-- Une des valeurs entrees est incorrecte\n"); Console.ResetColor(); continue; } EnregistrerNombre(line, col, valeurEntre); //Verifier si toutes les cases sont remplies gridFull = true; for (int i = 0; i < 9; ++i) { for (int j = 0; j < 9; ++j) { if (Grille[i, j] == 0) { gridFull = false; } } } } //Cases toutes occupees, fin de la partie AfficherGrille(); Console.WriteLine("Bravo! Vous avez completé la grille!"); } /// /// Vérifie si une case est disponible et y enregistre la valeur spécifiée. /// /// Ligne de la case /// Colonne de la case /// Valeur à entrer static void EnregistrerNombre(int line, int col, int valeurEntre) { int resultatCheck; int temp; //Si la case ne contient pas une variable de départ (verrouillée) if (!Verrou[line, col]) { resultatCheck = Check(line, col, valeurEntre); //Verifier si la valeur est valide pour cette case //Retirer la valeur dans la case si l'utilisateur a entré comme valeur '0' if (valeurEntre == 0) { //enregistrer l'etat de la case dans l'historique avant de la modifier Historique[nbActions, 0] = line; Historique[nbActions, 1] = col; Historique[nbActions, 2] = Grille[line, col]; ++nbActions; Grille[line, col] = valeurEntre; verrouUtilisateur[line, col] = false; } //Si la valeur est valide pour cette case else if (resultatCheck == 0) { temp = Grille[line, col]; //enregistrer l'etat de la case dans l'historique avant de la modifier Historique[nbActions, 0] = line; Historique[nbActions, 1] = col; Historique[nbActions, 2] = Grille[line, col]; ++nbActions; Grille[line, col] = valeurEntre; verrouUtilisateur[line, col] = true; if (modeFacile) { //Verifier s'il est possible de completer la grille avec la valeur entree //Si non, remettre l'ancienne valeur (temp), deverouiller la case, decrementer // le nombre de cases occupees et afficher une erreur if (!GenererGrille(0, verrouUtilisateur)) { Grille[line, col] = temp; verrouUtilisateur[line, col] = false; AfficherErreur(5); //decrementer le nombre d'actions --nbActions; } //Enlever les valeurs ajoutees a Grille[,] par la fonction GenererGrille() //Toutes les cases non verrouillees sont remises a 0 NettoyerGrille(verrouUtilisateur); } } //Valeur invalide pour la case (meme valeur sur la ligne, colonne ou region else { AfficherErreur(resultatCheck); } } else { AfficherErreur(4); //Erreur, case verrouillée (case de départ) } } /// /// Affiche la grille de jeu /// static void AfficherGrille() { //En-tête Console.WriteLine(" 1 2 3 4 5 6 7 8 9 "); Console.WriteLine(" -------------------------------------------------------"); //Lignes for (int i = 0; i < 9; i++) { Console.Write(" |"); for (int j = 0; j < 9; j++) { EcrireCaseLigneVide(i,j); } Console.WriteLine(); Console.Write(" {0} |", i + 1); for (int j = 0; j < 9; j++) { if ((j == 2) || (j == 5)) //Case adjacente à un séparateur vertical { EcrireCaseAdj(i, j); } else //Autre case { EcrireCaseAutre(i, j); } } Console.WriteLine(); Console.Write(" |"); for (int j = 0; j < 9; j++) { EcrireCaseLigneVide(i, j); } Console.WriteLine(); //Séparateur de bloc horizontal if ((i == 2) || (i == 5)) { Console.WriteLine(" *******************************************************"); } else { if (i == 8) //Dernière ligne { Console.WriteLine(" -------------------------------------------------------"); } else { Console.WriteLine(" ------------------#-----------------#------------------"); } } } } /// /// Afficher une partie de case sur une ligne sans chiffres /// /// le numéro de la ligne /// le numéro de la colonne private static void EcrireCaseLigneVide(int i, int j) { if (Change[i, j]) { Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("-----"); Console.ResetColor(); if ((j == 2) || (j == 5)) { Console.Write("#"); } else { Console.Write("|"); } } else { if ((j == 2) || (j == 5)) { Console.Write(" #"); } else { Console.Write(" |"); } } } /// /// Écrit une case adjacente à un séparateur vertical /// /// le numéro de la ligne /// le numéro de la colonne static void EcrireCaseAdj(int i, int j) { if (Grille[i, j] == 0) //Case non modifiée { if (Change[i, j]) //Case a changer pour resoudre une impasse { Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("| |"); Console.ResetColor(); Console.Write("#"); } else //Laisser la case blanche { Console.Write(" #", Grille[i, j]); } } else //Une valeur y est entrée { if (Verrou[i, j]) //Valeur de départ vérouillée { Console.ForegroundColor = ConsoleColor.Green; Console.Write(" [{0}] ", Grille[i, j]); Console.ResetColor(); Console.Write("#"); } else if (Suggested[i, j]) //Valeur suggérée (Rouge) { Console.ForegroundColor = ConsoleColor.Red; Console.Write(" ({0}) ", Suggestion[i, j]); //Console.Write(" ({0}) ", Grille[i, j]); Console.ResetColor(); Console.Write("#"); } else if (Change[i, j]) { Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("| {0} |", Grille[i, j]); Console.ResetColor(); Console.Write("#"); } else //Valeur entrée par l'utilisateur { Console.ForegroundColor = ConsoleColor.Cyan; Console.Write(" {0} ", Grille[i, j]); Console.ResetColor(); Console.Write("#"); } } } /// /// Écrit une case qui n'est pas adjacente à un séparateur /// /// le numéro de la ligne /// le numéro de la colonne static void EcrireCaseAutre(int i, int j) { if (Grille[i, j] == 0) //Case non modifiée { if (Change[i, j]) //Case a changer pour resoudre une impasse { Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("| |"); Console.ResetColor(); Console.Write("|"); } else //Laisser la case blanche { Console.Write(" |", Grille[i, j]); } } else //Une valeur y est entrée { if (Verrou[i, j]) //Valeur de départ vérouillée { Console.ForegroundColor = ConsoleColor.Green; Console.Write(" [{0}] ", Grille[i, j]); Console.ResetColor(); Console.Write("|"); } else if (Suggested[i, j]) //Valeur suggérée (Rouge) { Console.ForegroundColor = ConsoleColor.Red; Console.Write(" ({0}) ", Suggestion[i, j]); //Console.Write(" ({0}) ", Grille[i, j]); Console.ResetColor(); Console.Write("|"); } else if (Change[i, j]) //Case a changer pour resoudre une impasse { Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("| {0} |", Grille[i, j]); Console.ResetColor(); Console.Write("|"); } else //Valeur entrée par l'utilisateur { Console.ForegroundColor = ConsoleColor.Cyan; Console.Write(" {0} ", Grille[i, j]); Console.ResetColor(); Console.Write("|"); } } } /// /// Affiche des message d'erreurs au hasard /// /// Type d'erreur: 1. Région 2.Ligne 3.Colonne 4.Case vérouill 5.Impossible de completer static void AfficherErreur(int type) { //Message en rouge Console.ForegroundColor = ConsoleColor.Red; if (type == 1) //Valeur déja dans la région { switch (randomG.Next(1, 5)) { case 1: Console.WriteLine("\n-- Cette valeur est déja dans la région!\n"); break; case 2: Console.WriteLine("\n-- Attention! Vous ne pouvez pas placer cette valeur ici! Vérifiez la région.\n"); break; case 3: Console.WriteLine("\n-- Ce chiffre ne peut pas être placé ici! Il est déja dans la région.\n"); break; case 4: Console.WriteLine("\n-- Ce chiffre est déja placé dans la région.\n"); break; } } if (type == 2) //Valeur déja dans la ligne { switch (randomG.Next(1, 5)) { case 1: Console.WriteLine("\n-- Vérifier la ligne, cette valeur y est déja.\n"); break; case 2: Console.WriteLine("\n-- Ce chiffre est déja sur cette ligne.\n"); break; case 3: Console.WriteLine("\n-- Attention, vous ne pouvez pas placer deux fois le même chiffre sur la même ligne.\n"); break; case 4: Console.WriteLine("\n-- Vous ne pouvez pas écrire ce chiffre ici, il est déja dans la ligne.\n"); break; } } if (type == 3) //Valeur déja dans la colonne { switch (randomG.Next(1, 5)) { case 1: Console.WriteLine("\n-- Cette valeur est déja dans la colonne.\n"); break; case 2: Console.WriteLine("\n-- Vous ne pouvez pas placer deux fois le même chiffre dans la même colonne.\n"); break; case 3: Console.WriteLine("\n-- Ce chiffre ne peut pas être écrit ici, il est déja dans la colonne.\n"); break; case 4: Console.WriteLine("\n-- Ce chiffre est déja placé dans la colonne.\n"); break; } } if (type == 4) //Case vérouillée { switch (randomG.Next(1, 6)) { case 1: Console.WriteLine("\n-- Vous ne pouvez pas modifier cette case!\n"); break; case 2: Console.Write("\n-- Vous ne pouvez pas modifier les cases avec des "); Console.ForegroundColor = ConsoleColor.Green; Console.Write("[ ]"); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(".\n"); break; case 3: Console.WriteLine("\n-- Cette case à été verouillée pour votre sécurité.\n"); break; case 4: Console.WriteLine("\n-- Cette case est vérouillée!\n"); break; case 5: Console.WriteLine("\n-- Vous ne pouvez pas modifier les cases de départ.\n"); break; default: break; } } if (type == 5) //Pas de solution possible (Mode facile) { switch (randomG.Next(1, 4)) { case 1: Console.WriteLine("\n-- Aucune solution possible avec cette valeur!\n"); break; case 2: Console.WriteLine("\n-- Cette valeur vous empecherais de completer la grille.\n"); break; case 3: Console.WriteLine("\n-- Vous ne pouvez pas placer ce chiffre ici, il n'y a aucune solution possible.\n"); break; } } Console.ResetColor(); } static void undo() { if (nbActions == 0) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("\n-- Aucune action n'as encore été prise !\n"); Console.ResetColor(); return; } --nbActions; int line = Historique[nbActions,0]; int col = Historique[nbActions,1]; Grille[line, col] = Historique[nbActions, 2]; if (Grille[line, col] == 0) { verrouUtilisateur[line, col] = false; } else { verrouUtilisateur[line, col] = true; } } /// /// Suggere une action a l'utilisateur /// static void SuggestMove() { int[] positions= new int[81]; //Positions dans la Grille qui sont vides int count=0; //nombre de positions trouvees int randPosition; //Position au hasard dans une des positions vides trouvees int caseVideChoisie; bool[,] verrouSugg = new bool[9, 9]; //Obtenir les positions for (int i = 0; i < 9; ++i) { for (int j = 0; j < 9; ++j) { if (Grille[i, j] == 0) { positions[count] = i * 9 + j; ++count; } //initialiser le verrou de suggestions verrouSugg[i, j] = verrouUtilisateur[i, j]; } } while (true) { if(!GenererGrille(0, verrouSugg)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("\n-- Il est impossible de completer la grille avec les valeurs entrees presentement\n"); Console.ResetColor(); NettoyerGrille(verrouUtilisateur); ResoudreImpasse(); return; } else { //AfficherGrille(); //GenererGrille(0, verrouUtilisateur); randPosition = randomG.Next(0, count); //position random dans positions[] caseVideChoisie = positions[randPosition]; //Case vide choisie Suggestion[caseVideChoisie / 9, caseVideChoisie % 9] = Grille[caseVideChoisie / 9, caseVideChoisie % 9]; Suggested[caseVideChoisie / 9, caseVideChoisie % 9] = true; verrouSugg[caseVideChoisie / 9, caseVideChoisie % 9] = true; //On retire la valeur utilisée positions[randPosition] = positions[count-1]; --count; NettoyerGrille(verrouSugg); AfficherGrille(); if (count == 0) //Toute la grille est suggérée { Console.WriteLine("La grille est pleine!"); Console.WriteLine("Appuyer sur une touche pour continuer..."); Console.ReadLine(); EnregistrerSug(); return; } while (true) { Console.WriteLine("Suggerer une autre action ? (y/n)"); string reponse = Console.ReadLine(); if (reponse == "y") { break; } else if (reponse == "n") { EnregistrerSug(); return; } else { Console.WriteLine("Reponse incorrecte"); } } } } } /// /// Enregistre les suggestion et initialise le tableau de suggestion /// static void EnregistrerSug() { while (true) { Console.WriteLine("Voulez-vous conserver les suggestions? (y/n)"); string reponse = Console.ReadLine(); if (reponse == "y") { for (int i = 0; i < 9; ++i) { for (int j = 0; j < 9; ++j) { if (Suggested[i, j]) { //enregistrer l'etat de la case dans l'historique avant de la modifier Historique[nbActions, 0] = i; Historique[nbActions, 1] = j; Historique[nbActions, 2] = 0; ++nbActions; verrouUtilisateur[i, j] = true; Grille[i, j] = Suggestion[i, j]; } } } break; } else if (reponse == "n") { break; } else { Console.WriteLine("Reponse incorrecte"); } } //Remettre toutes les cases de Suggested[] a false for (int i = 0; i < 9; ++i) { for (int j = 0; j < 9; ++j) { Suggested[i, j] = false; } } } static void ResoudreImpasse() { int[,] backupGrille = new int[9, 9]; //Backup de la grille bool[,] backupVerrou = new bool[9, 9]; //Backup de verrouUtilisateur //int[,] bufferResolution = new int[9, 9]; //Grille resolue string reponse; //reponse aux questions int nbActionsDefaites = 0; //Nombre de fois qu'on retourne en arriere //pour corriger l'impasse while (true) { Console.WriteLine("Voulez-vous retourner en arrière pour voir ce qui a causé l'impasse? (y/n)"); reponse = Console.ReadLine(); if (reponse == "n") { return; } else if(reponse == "y") { /* Faire un backup de la grille et du verrou utilisateur */ for (int i = 0; i < 9; ++i) { for (int j = 0; j < 9; ++j) { backupGrille[i, j] = Grille[i, j]; backupVerrou[i, j] = verrouUtilisateur[i, j]; } } /* Aussi longtemps que la grille ne peut etre resolue avec les valeurs * entrees, retourner une action en arriere et essayer encore */ for (int i = 0; !GenererGrille(0, verrouUtilisateur); ++i) { int line = Historique[(nbActions-1) - i, 0]; int col = Historique[(nbActions-1) - i, 1]; if (Historique[(nbActions-1) - i, 2] == 0) { Grille[line, col] = Historique[(nbActions-1) - i, 2]; verrouUtilisateur[line, col] = false; } else { Grille[line, col] = Historique[(nbActions-1) - i, 2]; verrouUtilisateur[line, col] = true; } ++nbActionsDefaites; } NettoyerGrille(verrouUtilisateur); //la Grille[,] peut etre resolue a partir d'ici //Determiner quelles cases doivent etre modifiees for (int i = 0; i < 9; ++i) { for (int j = 0; j < 9; ++j) { if (Grille[i, j] != backupGrille[i, j]) { Change[i, j] = true; } } } //Afficher la grille avec les cases qui doivent etre modifiees AfficherGrille(); while (true) { Console.WriteLine("Voici l'etat du tableau tel qu'il etait la derniere fois qu'il etait resolvable"); Console.WriteLine("Voulez-vous revenir en appliquant ces modifications? (y/n)"); Console.WriteLine("Les cases qui seront modifiées apparaissent en jaune"); reponse = Console.ReadLine(); if (reponse == "y") { //Decrementer le nombre d'actions du nombre de fois qu'on retourne en arriere nbActions -= nbActionsDefaites; for (int i = 0; i < 9; ++i) { for (int j = 0; j < 9; ++j) { Change[i, j] = false; } } return; } else if (reponse == "n") { for (int i = 0; i < 9; ++i) { for (int j = 0; j < 9; ++j) { Grille[i, j] = backupGrille[i, j]; verrouUtilisateur[i, j] = backupVerrou[i, j]; Change[i, j] = false; } } return; } else { Console.WriteLine("Reponse incorrecte"); } } } else { Console.WriteLine("Reponse incorrecte"); } } } /// /// Remet la grille telle qu'elle etait au debut de la partie /// static void ResetGrille() { nbActions = 0; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (!Verrou[i, j]) { Grille[i, j] = 0; verrouUtilisateur[i, j] = false; } } } } /// /// Cache les case qui ne sont pas vérouillées. /// (Nettoyage après avoir vérifier une solution possible) /// /// Tableau de verrouillage à utiliser static void NettoyerGrille(bool[,] Verrou) { for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (!(Verrou[i,j])) { //Si la case n'est pas vérouillée, effacer la case. Grille[i,j] = 0; } } } } static void VoirHistorique() { int[,] copyGrille = new int[9, 9]; int ligneCase; // ligne de la case apres modification int colonneCase; // colonne de la case apres modification /* Faire une copie de la grille */ for (int i = 0; i < 9; ++i) { for (int j = 0; j < 9; ++j) { copyGrille[i, j] = Grille[i, j]; } } for (int i = 0; i < nbActions; ++i) { ligneCase = Historique[(nbActions-1)-i,0]; colonneCase = Historique[(nbActions-1)-i,1]; Console.WriteLine("{0}) Ligne: {1} Colonne: {2} Valeur: {3}", i+1, Historique[(nbActions-1)-i,0]+1, Historique[(nbActions-1)-i,1]+1, copyGrille[ligneCase,colonneCase]); copyGrille[ligneCase, colonneCase] = Historique[(nbActions - 1) - i, 2]; } Console.WriteLine("Appuyez sur une touche pour continuer"); Console.ReadLine(); } } }