Sudoku 1 Primitives

Transcription

Sudoku 1 Primitives
IFIPS-S5
Projet C
Année 2009-2010
Sudoku
Le sudoku se joue à un seul joueur. Le but est de remplir une grille 9 × 9 avec des chiffres
compris entre 1 et 9 en respectant les 3 règles suivantes :
– Tous les chiffres doivent être présents une seule fois sur chaque ligne.
– Tous les chiffres doivent être présents une seule fois sur chaque colonne.
– Tous les chiffres doivent être présents une seule fois sur chaque sous carré.
Le carré 9 × 9 est constitué de 9 sous carrés 3× 3. Les fonctions suivantes permettrons à
concevoir un programme structuré.
1
Primitives
1. Ecrire la procédure
void charger_grille (int grille[9][9]) permettant à l’utilisateur d’initialiser la
grille.
2. Ecrire la fonction
void affiche(int grille[9][9]) qui affiche la grille Sudoku à l’écran.
3. Ecrire la fonction
int dans_ligne(int grille[9][9], int i, int n) qui prendra la valeur vrai (1) si
le chiffre n est déjà présent dans la i ème ligne de la grille.
4. Ecrire la fonction
int dans_colonne(int grille[9][9], int j, int n) qui prendra la valeur vrai (1)
si le chiffre n est déjà présent dans la jème colonne de la grille.
5. Ecrire la fonction
int dans_sous_carre(int grille[9][9], int i, int j, int n) qui prendra la valeur vrai (1) si le chiffre n est déjà présent dans le sous carré contenant la case [i][j].
6. Ecrire la fonction
void jouer(int grille[9][9], int i, int j,int n) qui remplacera le chiffre n dans
la case [i][j] à condition que le nouveau chiffre respecte les trois règles mentionnées audessus.
7. Ecrire la fonction
int* chiffres_possibles(int grille[9][9], int i, int j) qui donnera la liste de
tous les chiffres permis (ceux qui respectent les 3 règles) pour la case [i][j] .
8. Ecrire la fonction
void seul_chiffre(int grille[9][9]) qui cherchera toutes les cases pour lesquelles
il n’y a qu’un seul chiffre permis, ensuite elle affectera la valeur du chiffre dans la case
correspondante.
9. Ecrire la fonction int c_est_fini(int grille[3][3]) qui prendra la valeur 1 s’il ne
reste plus de case libre dans la grille et 0 dans le cas contraire.
1
2
Méthode avancée
Cette partie consiste dans un premier temps à écrire un code permettant de résoudre tous les
sudoku quelque soit leur niveau et de donner toutes les solutions possibles. Puis, de générer des
grilles de sudoku en utilisant le code précédent.
2.1
Principe
Le principe de cette méthode est de remplir progressivement les cases vides en respectant
toujours les règles du sudoku.
Tout d’abord, on définit un parcours des N cases vides afin de remplir les cases dans un certain
ordre. On peut construire formellement un arbre (voir figure 1) comportant autant de niveaux
que de cases vides qui contient toutes les valeurs de la case vide n vérifiants les règles du sudoku
connassant la valeur des cases 1, . . . , n − 1. Pour trouver la solution du sudoku, il faut trouver
la branche qui descend jusqu’à la dernière case (représenté en gras sur la figure 1).
Fig. 1 – Arbre des configurations respectant les règles du sudoku
Il n’est pas nécessaire de contruire l’arbre puis de le parcourir, les deux peuvent se faire simultanément. Ce qui implique que l’on peut construire les sous-arbres uniquement lorsqu’on
les explorent et on peut éliminer de la mémoire de l’ordinateur les sous-arbres qui ont déjà
été parcourus. La mémorisation des portions de l’arbres qui nous intéresse se fera à l’aide de
fonction récursive.
2.2
Méthode récursive :
Cette méthode permet de se déplacer dans l’arbre de la figure 1. L’idée est de remplir les cases
vides par des chiffres respectant les règles du sudoku (on monte vers les feuilles), lorsqu’on ne
peut plus remplir les cases vides (On arrive à une feuille de l’arbre), on remet en cause les
chiffres des case précédente (on descend vers la racine de l’arbre). Ces étapes de remplissages et
2
de remise en cause permettent de parcourir l’arbre. Afin de remettre en cause les cases remplies
précédemment, il faut les mémoriser ainsi que les chiffres de recpectant les règles déjà parcourru.
L’appel recursif des fonction permet naturellement de stocker ces étapes intermédiares dans la
pile sans que le programmeur sans préoccupe particulièrement.
En résumé, une fonction récursive va permettre d’explorer de manière exhaustive l’arbre de la
figure 1. Il est donc nécessaire de tester si position courrante dans l’arbre correspond à la grille
de sudoku résolue.
2.3
Algorithme :
Cet algorithme peut être codé grâce à un fonction récursive
void sudoku(int grille[9][9], int i, int j). Voici les instructions que doit contenir
cette fonction :
debut de la fonction récursive sudoku :
1. trouver la première case vide [i][j]
2. boucle n de 1 à 9
debut de la boucle sur n :
(a) si ce chiffre est compatible avec le reste de la grille :
i. le mettre dans la case [i][j]
ii. si la grille est complétée
A. afficher la solution. (Ceci est la condition d’arrêt pour la procédure récursive !
).
B. sinon, appeler la fonction récursive pour cette nouvelle grille : sudoku(grille,i,j)
(b) sinon, remettre cette case à 0
fin de la boucle sur n
fin de la fonction récursive sudoku
Dans le programme principal, on appelle la fonction récursive avec pour paramètres la grille
initiale et la première case [0][0] : (sudoku(grille,0,0))
3