:: Enseignements :: ESIPE :: E3INFO :: 2016-2017 :: Algorithmique ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) | Minesweeper (récursivité) |
On poursuit l'écriture de fonctions récursives en implémentant une fonction
pour découvrir des cases dans un jeu de type Minesweeper (démineur).
On souhaite écrire une version du jeu Minesweeper (démineur).
On utilise la librairie MLV pour gérer le graphisme et les interactions avec l'utilisateur.
Normalement, la librairie est disponible sur vos comptes de l'université; si vous souhaitez
l'utiliser sur votre ordinateur personnel, vous pouvez vous référer à
cette page.
Commencer par récupérer l'archive
Sweeper.zip
et extraire les fichiers dans votre répertoire de travail.
$ make
gcc -c -o sweeper.o sweeper.c -Wall -ansi
gcc -c -o grid.o grid.c -Wall -ansi
gcc -c -o draw.o draw.c -Wall -ansi
gcc -o sweeper sweeper.o grid.o draw.o -lMLV -lm -lSDL
$ ./sweeper
Vous voyez qu'il y a déjà une partie du jeu en place mais que le jeu ne fonctionne pas.
Plus précisément, il manque une fonction qui place les mines sur la grille initiale
et une fonction qui découvre les cases dès que le joueur clique (gauche) sur une case.
Familiarisez-vous avec les structures
cell et
grid, les fonctions pour
dessiner la grille et la fonction principale du jeu.
Exercice 1 - Génération aléatoire des mines
Écrire la fonction
void add_mines(grid *g, int n) dans
grid.c.
La fonction prend (un pointeur vers) une grille,
g, et
un entier
n et elle doit ajouter exactement
n mines sur la grille
à des emplacements choisis de facon aléatoire.
De plus, cette fonction doit mettre à jour les champs
mine_count des cases
voisines des mines.
Voir la figure ci-dessous :
Pour vérifier votre fonction, vous pouvez ajouter dans votre
main un appel à
la fonction
set_all_visible(g). Cette fonction rend toutes les cases visibles.
N'oubliez pas d'enlever cet appel avant de commencer l'exercice suivant.
Exercice 2 - Découverte des mines
Écrire la fonction
int uncover(grid *g, cell *c) dans
grid.c.
La fonction prend (un pointeur vers) une grille,
g, et une case,
c.
Elle doit renvoyer le nombre de cases qui ont été découvertes.
Pour cela, elle doit découvrir récursivement les cases comme suit :
-
Si la case est déjà visible ou marquée (gris-sombre, par un clic droit),
alors la fonction ne découvre pas la case courante, ni les cases voisines.
Elle renvoie 0 pour indiquer qu'aucune case n'a été découverte.
-
Sinon, on commence par découvrir la case c
et on utilise la fonction
draw_cell_actualise_window(c) pour visualiser ce changement.
-
Si la case c contient une mine ou si son compteur de mines voisines
ne vaut pas 0, alors on renvoie 1 pour indiquer qu'une seule case a été découverte.
-
Sinon, on lance, pour chaque voisin v tel que
v n'est pas découvert, un appel récursif à uncover sur v.
On récupère les résultats (nombre de cases découvertes) de tous les appels et
on renvoie leur somme (+ 1 pour la découverte de la case c).
Pour mieux voir l'ordre dans lequel les cases sont découvertes, vous pouvez utilisez
la fonction
void MLV_wait_milliseconds(int milliseconds) de la librairie MLV.
Exercice 3 - N reines
Implanter la fonction récursive pour la résolution du puzzle
N reines
vue au cours.
Comparer le nombre de solutions obtenu avec les valeurs tabulées sur le lien
suivant :
The On-Line Encyclopedia of Integer Sequences.
-
Pour quelles valeurs de N pouvez-vous obtenir le nombre de solutions dans
un temps raisonnable ?
-
Implanter au moins une des améliorations suivantes :
-
Ajouter une visualisation des solutions du puzzle en utilisant la
librairie MLV.
-
Ajouter une visualisation de la recherche en utilisant la libraire MLV.
C'est-à-dire, dans chaque appel de la fonction récursive, vous
dessinez
l'échiquier avec les reines qui sont déjà placées et les cases potentielles
pour le placement de la prochaine reine.
-
Trouver des optimisations de votre fonction afin d'obtenir le nombre de
solutions pour une plus grande valeur de N.
© Université de Marne-la-Vallée