Java Avancé : Jeu de la vie
par
popularité : 13%
Jeu de la Vie
Dans le Jeu de la Vie (proposé par Conway 1970), dans une matrice se trouvent des cellules, actives ou inactives.
Le Jeu de la vie consiste à faire évoluer sur un grille un ensemble cellules
selon les règles suivantes :
- Si une cellule active est entourée de moins de 2 cellules :
elle manque de contact et se désactive. - Si une cellule active est entourée de plus de 3 cellules : elle est en milieu surpeuplé et se désactive.
- Si une cellule inactive est entourée de 3 cellules, alors elle s’active.
- Dans les autres cas, la cellule garde son état.
Voici le lien pour la page wikipedia en français.
Ici http://golly.sourceforge.net/ se trouve le logiciel golly, spécialement dédié aux automates cellulaires.
Possibilité d’utiliser un monde très très étendu...
Enoncé
Créer le programme permettant le déroulement d’un jeu de la Vie.
1. Créer les classes Cellule et Matrice :
Les classes suivantes sont à définir :
- Cellule, avec les variables
- vivante : booléen
- etatPrecedent : booléen qui indique si un l’état précédent de la cellule
- Cellule[][] grille : un lien vers la matrice de cellules
- Circle cercle : un lien vers sa représentation graphique
- x, y les coordonnées
- le constructeur : public Cellule(Cellule [][]grille, int x, int y, boolean vivante)
- evoluer() qui change la valeur de la cellule par rapport à son voisinage
On prendra un monde sphérique. ’taille’ étant la dimension de la grille carrée, la case en haut à gauche de la case (0,0) est la case (taille-1, taille-1).
- Matrice, avec les variables
- Cellule[][] grille, la grille au temps actuel
- Cellule[][] grilleAncienne, la grille au temps précédent
- double densité : pourcentage initiale de cellules actives
- int taille : la taille de la matrice (carrée)
- le constructeur public Matrice(int taille, double densite)
- la fonction void init() qui cree des cellules inactives dans la grille et les recopie dans la grilleAncinne
- la fonction initHasard() qui active densité% de cellule dans la grille et dans la grilleAncienne
- copieGrille(), recopie grille dans ancienne grille
- animGrille(), demande à chaque cellule d’évoluer
2. Interactivité
Ajouter des interactions :
- l’appui sur ’p’ met en pause la simulation
- l’appui sur ’d’ démarre la simulation
- l’appui sur ’e’ efface tout
- ’l’appui sur ’h’ active des cellules aléatoirement
- un clic souris sur la zone de simulation active.desactive des cellules
3. Ralentissez la croissance :
ajouter des étapes afin de voir l’évolution des cellules au ralenti :
- les cellules actives sont en vert clair
- les cellules qui se désactivent et seraient désactivés au top suivant sont en vert
- les cellules qui se réactivent et seraient actives au top suivant sont en vert sombre
- les cellules inactives sont en vert noir.
4. Animation :
Quand une cellule change d’état, sa couleur s’estompe graduellement.
Remarque : Ceci ralenti la simulation..
Fenêtre JFX pour tester le code
On utilisera une fenêtre de type JavaFX.
En JavaFX, une application graphique se déroule sur une scène (scene) de théâtre (stage).
Sur cette scène se trouve des acteurs, les éléments graphiques.
N.B. Pour lancer cette application, il est nécessaire d’ajouter dans les options de la JVM le chemin d’accès au répertoire où vous avez installer JavaFX. Exemple :
— module-path /MONREPERTOIRE/LeRepDeJAVAFX/lib —add-modules=javafx.controls,javafx.fxml
Voici un exemple de code pour l’Application :
- import javafx.animation.KeyFrame;
- import javafx.animation.Timeline;
- import javafx.application.Application;
- import javafx.scene.Group;
- import javafx.scene.Scene;
- import javafx.scene.paint.Color;
- import javafx.scene.shape.Circle;
- import javafx.stage.Stage;
- import javafx.util.Duration;
- public class JfxAnimVie extends Application {
- /**matrice liee a cet objet graphique*/
- Matrice matrice;
- /**elements graphiques représentant les cellules*/
- public static Circle[][] circles;
- /**taille d'une cellule en pixel*/
- int espace = 10;
- /**taille de la matrice*/
- private int taille;
- /**nombre de celluls initialement actives*/
- private double densite;
- /**délai en ms entre chaque évolution*/
- private int tempo;
- @Override
- public void start(Stage primaryStage) {
- taille = 200;
- densite = 0.2;
- tempo = 100;
- construireScenePourJeuDeLaVie( primaryStage);
- }
- void construireScenePourJeuDeLaVie(Stage primaryStage) {
- int largeur = 800;
- int hauteur = 900;
- espace = 4;
- //definir la scene principale
- primaryStage.setTitle("Life...");
- primaryStage.setScene(scene);
- //definir les acteurs
- matrice = new Matrice(taille, densite);
- matrice.init();
- matrice.initHasard();
- //definir les costumes
- JfxAnimVie.circles = new Circle[taille][taille];
- //habiller les acteurs
- dessinMatrice( root);
- //afficher le theatre
- primaryStage.show();
- //-----lancer le timer pour faire vivre la matrice
- Timeline littleCycle = new Timeline(new KeyFrame(Duration.millis(tempo), event-> { matrice.copieGrille(); matrice.animGrille(); }
- ));
- littleCycle.setCycleCount(Timeline.INDEFINITE);
- littleCycle.play();
- }
- /** creation des cellules et de leurs habits */
- Cellule[][] grille = matrice.getGrille();
- int rayon = espace/2;
- for(int i=0; i<taille; i++)
- for(int j=0; j<taille; j++) {
- Cellule cell = grille[i][j];
- circles[i][j] = new Circle(i*espace+rayon, j*espace+rayon, rayon);
- cell.setCercle(circles[i][j]);
- root.getChildren().add(circles[i][j]);
- }
- }
- }
Version courte mais complète
Vous trouvez ci-dessous un petit code complet permettant l’exécution du jeu de la Vie en Java FX, en 1 seule classe.
- import javafx.animation.KeyFrame;
- import javafx.animation.Timeline;
- import javafx.application.Application;
- import javafx.scene.Group;
- import javafx.scene.Scene;
- import javafx.scene.paint.Color;
- import javafx.scene.shape.Circle;
- import javafx.stage.Stage;
- import javafx.util.Duration;
- public class QuickLife extends Application {
- /**
- * matrice representant l'ETAT des cellules
- */
- byte[][] matrice;
- /**
- * copie de la matrice representant l'ETAT des cellules
- */
- byte[][] matriceCopie;
- /**
- * objets graphiques représentant les cellules
- */
- public Circle[][] circles;
- /**
- * taille d'une cellule en pixel
- */
- int espace = 7;
- /**
- * longueur de la matrice (en nombre de cellules sur une rangée)
- */
- private int taille;
- /**
- * densite de cellules actives au départ
- */
- double densite;
- /**
- * délai en ms entre chaque évolution
- */
- private int tempo;
- /**
- * lancement de l'application
- */
- public void start(Stage primaryStage) {
- taille = 60;
- tempo = 10;
- espace = 10;
- densite = 0.4;
- construireScenePourJeuDeLaVie(primaryStage);
- }
- void construireScenePourJeuDeLaVie(Stage primaryStage) {
- int largeur = (taille + 1) * (espace + 1);
- int hauteur = (taille + 1) * (espace + 1);
- //definir la troupe
- //definir la scene principale
- primaryStage.setTitle("Life...");
- primaryStage.setScene(scene);
- //creation et initialisation des cellules
- matrice = new byte[taille][taille];
- matriceCopie = new byte[taille][taille];
- initMatrice(densite);
- copie(matrice, matriceCopie);
- //definir les acteurs (representation des cellules
- circles = new Circle[taille][taille];
- creationTroupe(root);
- //afficher le theatre
- primaryStage.show();
- //-----lancer le timer pour faire vivre la matrice
- Timeline littleCycle = new Timeline(new KeyFrame(Duration.millis(tempo),
- event -> {
- //à chaque top, lancer une evolution
- evoluerMatrice();
- //puis effectuer une copie de la matrice
- copie(matrice, matriceCopie);
- }));
- //animation en boucle
- littleCycle.setCycleCount(Timeline.INDEFINITE);
- littleCycle.play();
- }
- /**
- * copie le contenu de matrice dans matriceCopie
- *
- * @param matrice matrice d'origine
- * @param matriceCopie matrice de destination
- */
- void copie(byte[][] matrice, byte[][] matriceCopie) {
- for (int i = 0; i < taille; i++)
- }
- /**
- * initialise les cellules à active (1) ou non (0)
- * en fonction de la densite d'activation (entre 0 et 1)
- *
- * @param densite densite de cellule à activer, entre entre 0(aucune cellule active) et 1(toutes cellules actives)
- */
- void initMatrice(double densite) {
- for (int i = 0; i < taille; i++)
- for (int j = 0; j < taille; j++)
- matrice[i][j] = 1;
- }
- /**
- * creation des cercles et de leurs couleurs en fonction de l'etat de leur cellule (cellule située aux même coordonnées (i,j))
- *
- * @param root ensemble des acteurs de la scène dans lequel les cercles seront ajoutés
- */
- int rayon = espace / 2;
- for (int i = 0; i < taille; i++)
- for (int j = 0; j < taille; j++) {
- circles[i][j] = new Circle((i + .5) * espace, (j + .5) * espace, rayon);
- root.getChildren().add(circles[i][j]);
- }
- }
- /**
- * evolution d'une cellule par rapport aux voisines/
- * Met à jour les valeurs dans matrice à partir des valeurs dans matriceCopie.
- *
- * @param x no de colonne de la cellule qui doit evoluer
- * @param y no de ligne de la cellule qui doit evoluer
- */
- void evoluer(int x, int y) {
- int nbVoisinesActives = 0;
- for (int i = -1; i <= 1; i++)
- for (int j = -1; j <= 1; j++) {
- if (i == 0 && j == 0) continue;
- int xx = ((x + j) + taille) % taille;
- int yy = ((y + i) + taille) % taille;
- nbVoisinesActives = nbVoisinesActives + matriceCopie[yy][xx];
- }
- if (matriceCopie[y][x] == 1) {
- if (nbVoisinesActives > 3 || nbVoisinesActives < 2) {
- matrice[y][x] = 0;
- }
- } else {
- if (nbVoisinesActives == 3) {
- matrice[y][x] = 1;
- }
- }
- }
- /**
- * evolution de l'ensemble de la matrice
- */
- void evoluerMatrice() {
- for (int x = 0; x < taille; x++)
- for (int y = 0; y < taille; y++)
- evoluer(x, y);
- }
- /**
- * lancement du prog
- */
- launch(args);
- }
- }
cf. le code complet sur https://github.com/EmmanuelADAM/Jeu...