Date de première publication : 2016/09/20
Coder le jeu "FloodIt" soit en JavaFX, soit en Swing !
Principe du jeu
Nous vous proposons de le jeu qui s’intitule Flood It (de LabPixies disponible sur iPhone et Android). Le principe est très simple : Vous disposez d’une zone de jeu carrée de 12 cases par 12 cases. Chacune des cases est remplie d’une couleur sur 6 possibles. Vous devez vous arranger pour que toutes les cases soient de la même couleur en 22 coups maximum. Pour cela, vous choisissez une couleur pour la case en haut à gauche et cela peint toutes les cases adjacentes de cette couleur : le raz de marée. On dira qu’une case est adjacente si elle est de la couleur de la première case avant le changement et si elle touche une case de cette couleur soit par le haut/bas, soit par la gauche ou la droite (on ne considère pas les cases en diagonales).
Si vous voulez tester le jeu, il est jouable ici.
On remplace les couleurs par un chiffre entre 0 et 5. Voici un petit exemple :
Situation initiale :
0 | 1 | 3 | 1 |
2 | 1 | 2 | 2 |
3 | 1 | 1 | 3 |
0 | 0 | 4 | 4 |
Premier coup :
1 | 1 | 3 | 1 |
2 | 1 | 2 | 2 |
3 | 1 | 1 | 3 |
0 | 0 | 4 | 4 |
Deuxième coup :
3 | 3 | 3 | 1 |
2 | 3 | 2 | 2 |
3 | 3 | 3 | 3 |
0 | 0 | 4 | 4 |
La partie se termine alors en 6 coups (choisir dans n'importe quel ordre les couleurs 2, 1, 0 et 4). Vous avez compris ?
Deuxième coup :
1 | 2 | 3 | 0 |
0 | 2 | 2 | 0 |
3 | 2 | 2 | 3 |
0 | 0 | 0 | 0 |
Modèle MVC
Si l'on veut appliquer le modèle MVC à ce jeu, il faut tout d'abord coder le modèle : une classe Zone
qui permet de gérer cette fameuse grille de couleurs. Cette classe doit :
- connaître les éléments de couleurs, par exemple un
int [][]
, - permettre une initialisation (éventuellement à un germe donné). Le nombre de couleurs du jeu original est de 6. La dimension de la grille originale est de 12 par 12.
- propager une couleur (la méthode
remplir()
), - maintenir le nombre d'itérations
- et enfin renvoyer si la grille est uniforme ou non !
Voici le code de la fonction remplir()
:
static boolean remplir(int[][] grille, int i, int j,
int ancien, int nouv) {
if ((i>=TAILLE) || (j>=TAILLE) || (i<0) || (j<0))
return false;
if ((i==0) && (j==0) && nouv == ancien)
return false;
if (grille[i][j] == ancien) {
grille[i][j] = nouv;
remplir(grille, i , j+1, ancien, nouv);
remplir(grille, i+1, j, ancien, nouv);
remplir(grille, i-1, j, ancien, nouv);
remplir(grille, i, j-1, ancien, nouv);
}
return true;
}
Le modèle est indépendant de la mise en œuvre graphique.
Ce qu'il faut faire en JavaFX...
On peut coder l'application avec un tableau de Button
mais je n'aime pas le rendu. Je préfère utiliser un Canvas
redimensionnable qui dessine toute la grille et sur laquelle on va réagir aux événements de type clic
- Déclarer une classe
FXloodIt
qui dérive deApplication
. - Déclarer un attribut
zone
de typeZone
codé dans la section précédente. - Déclarer une classe
ZoneGraphique
qui étendCanvas
. Cette classe sera la représentation graphique la zone précédente. Elle encapsule un attributzone
. Le lien sera fait, soit par un setter, soit à la construction, voire on pourrait mettre en place le mécanimse de propriété :-) - Pour l'interaction avec l'utilisateur, il suffit d'ajouter un
EventHandler
concernant un clic souris. - Le nombre de coups joués peut être placé dans un
Label
en bas de la fenêtre.
Pour l'affichage du canvas, il faut ajouter une méthode type paint()
Ce qu'il faut faire en Swing...
- Déclarer une classe
JFloodIt
qui dérive ou encapsule une instance deJFrame
. - Déclarer un attribut
zone
de typeZone
dans la classeJFloodIt
- Déclarer une classe
JZone
qui étendJPanel
. Cette classe sera la représentation graphique la zone précédente. Elle encapsule un attributzone
, de même type que celui déclaré précédemment. Le lien sera fait, soit par un setter, soit à la construction. - Redéfinir la méthode
paintComponent()
de Zone pour afficher un petit rectangle - Créer une méthode
creerGUI()
dans la classe JFloodIt. Cette méthode ajoute une instance deJZone
augetContentPane()
. - Pour des questions de timing (et de confinement), l’appel à
creerGUI()
doit être "protégé". Vous vous souvenez comment on a créé l’interface graphique dans le tutoriel Swing ? Il faut faire la même chose en utilisant la méthodeSwingUtilities.invokeAndWait()
. Cela permet de s’assurer que l’interface graphique est bien créée dans le thread des événements de Swing et que l’interface est opérationnelle. - Créer un tableau de
Color
statique dans la classeZone
avec six couleurs de votre choix. - Modifier
Zone.paintComponent()
pour que la zone de jeu soit correctement affichée. - On y presque ! On doit maintenant interagir avec l’utilisateur. Je vous propose d’implémenter un
MouseListener
au niveau deJFloodIt
. - Redéfinir la méthode concernant le clic. Il faut calculer les coordonnées (i,j) de la grille en fonction des coordonnées souris (
getX()
,getY()
). Il faut ensuite appeler la méthoderemplir (zone, 0, 0, zone[0][0], zone[i][j])
et lancer unrepaint()
. C’est déjà pas mal, non ? - Ajouter une barre des tâches ,un composant
JLabel
attribut deJFloodApp
. Le composant affiche une petite aide au départ, le nom de coups en cours de route. Un composant de typeJLabel
n’est pas opaque par défaut, alors cela peut être une bonne idée qu’il le soit.
Compléments
Il faudrait aussi gérer les choses suivantes :
- Le nombre maximal de coups à jouer avec un système d'affichage comme pour le démineur par exemple
- Un bouton ou un menu pour recommencer le jeu
- On pourrait même imaginer une gestion des scores (nom et meilleur nombre de coups)