From f2f72589628f09dc0eb8f10a6738685cd2857711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20GUEZO?= Date: Sun, 9 Nov 2025 18:37:55 +0100 Subject: [PATCH] feat(Game.java): ajout commentaire et amelioration - enlever record (meilleur comprehension) - mis un static pour savoir si il y a un server d'affichage --- src/Game.java | 465 ++++++++++++++++++++++++++++---------------------- src/Main.java | 48 +++--- 2 files changed, 283 insertions(+), 230 deletions(-) diff --git a/src/Game.java b/src/Game.java index 46682b8..72ccae6 100644 --- a/src/Game.java +++ b/src/Game.java @@ -1,232 +1,289 @@ import java.awt.Color; +import java.awt.GraphicsEnvironment; import java.util.ArrayList; +/** + * La classe {@link Game} représente le moteur principal du jeu. + *

+ * Elle contient le modèle (les voitures, l'état du jeu, la carte), + * la vue (Track, Dashboard, Rankboard) et la logique de contrôle + * (pause, boucle de jeu, observateurs). + *

+ */ public class Game { - public static record CarInfo(String name, Color color) {} - - public static class Builder + /** + * {@link CarInfo} est une structure simple qui contient les informations + * nécessaires pour créer une voiture dans le jeu : son nom et sa couleur. + */ + public static class CarInfo { - /** - * Liste des voitures ajoutées au jeu. - * On utilise ArrayList pour pouvoir ajouter/supprimer des voitures dynamiquement. - */ - private ArrayList cars = new ArrayList<>(); - private State state = new State(); - private int time = 1000; + /** Nom de la voiture */ + public final String name; + /** Couleur de la voiture */ + public final Color color; - private Map map = null; - - public Builder addCar(CarInfo car) - { - cars.add(car); - return this; - } - - public Builder remCar(CarInfo car) - { - cars.remove(car); - return this; - } - - public Builder setMap(Map map) - { - this.map = map; - return this; - } - - public Builder setState(State s) - { - this.state = s; - return this; - } - - public Builder setTime(int time) - { - this.time = time; - return this; - } - - public Game build() - { - if (map == null) - { - System.err.println("Vous devez declarer la map avant de build!"); - System.exit(1); - } - return new Game(map, cars, state, time); - } + public CarInfo(String name, Color color) + { + this.name = name; + this.color = color; + } } - private final Map map; - private final State state; - private final int time; + /** + * Builder pour créer une instance de {@link Game} de façon fluide. + *

+ * Permet d'ajouter des voitures, de définir la carte, l'état initial et + * le temps entre les étapes du jeu avant de construire l'objet final. + *

+ */ + public static class Builder + { + /** Liste des voitures à créer pour le jeu */ + private ArrayList cars = new ArrayList<>(); + /** État initial du jeu */ + private State state = new State(); + /** Temps entre chaque "step" du jeu (en millisecondes) */ + private int time = 1000; + /** Carte sur laquelle se déroule le jeu */ + private Map map = null; - private final ArrayList cars = new ArrayList<>(); - private final ArrayList obs = new ArrayList<>(); + /** Ajoute une voiture à la liste */ + public Builder addCar(CarInfo car) + { + cars.add(car); + return this; + } - private boolean isPaused = false; + /** Supprime une voiture de la liste */ + public Builder remCar(CarInfo car) + { + cars.remove(car); + return this; + } - public Game(Map map, ArrayList cars, State state, int time) - { - this.map = map; - this.state = state; - this.time = time; + /** Définit la carte du jeu */ + public Builder setMap(Map map) + { + this.map = map; + return this; + } - init(cars); - } + /** Définit l'état initial du jeu */ + public Builder setState(State s) + { + this.state = s; + return this; + } - - private Game init(ArrayList carInfos) - { - new Track(map, cars, "Piste Formule 1", 1000, 500, 1, 1); - new Rankboard("Score", cars, 200, 200, 0, 510); - - final int loop = map.getPathSize(); - - int i = 0; - for (CarInfo ci : carInfos) - { - Car car = new Car(ci.name, ci.color, loop, state); - new Dashboard(car, car.toString(), this::togglePause, 300, 200, 1000, 200*i); - cars.add(car); - i++; - } + /** Définit le temps entre chaque étape du jeu */ + public Builder setTime(int time) + { + this.time = time; + return this; + } - GameView.update(); - return this; - } + /** + * Construit l'instance de {@link Game} avec les paramètres définis. + *

+ * Si la carte n'a pas été définie, le programme s'arrête. + *

+ */ + public Game build() + { + if (map == null) + { + System.err.println("Vous devez définir une carte avant de construire le jeu !"); + System.exit(1); + } + return new Game(map, cars, state, time); + } + } - private boolean isFinish() - { - for (Car car : cars) - { - if (car.getFuel() == 0) - return true; - } - return false; - } - - public Game addObserver(GObserver o) - { - obs.add(o); - return this; - } - - public Game remObserver(GObserver o) - { - obs.remove(o); - return this; - } - - public synchronized boolean togglePause() - { - if (isPaused) notifyAll(); - isPaused = !isPaused; - GameView.update(); - return isPaused; - } + /** Carte sur laquelle le jeu se déroule */ + private final Map map; + /** État du jeu (par exemple, positions, carburant) */ + private final State state; + /** Temps entre chaque étape du jeu en millisecondes */ + private final int time; - private synchronized void step() throws InterruptedException - { - for (int i = 0; i < cars.size(); i++) - { - // pause du jeu, while si on notifyall sans faire exprès un autre bout de code - while (isPaused) - wait(); - - cars.get(i).run(); + /** Liste des voitures du jeu */ + private final ArrayList cars = new ArrayList<>(); + /** Liste des observateurs pour la mise à jour des vues */ + private final ArrayList obs = new ArrayList<>(); - for (GObserver o : obs) - { - if (!o.apply()) - { - System.err.println("Une erreur s'est produite pendant le jeu."); - System.exit(1); - } - } - } - } + /** Indique si le jeu est en pause */ + private boolean isPaused = false; - public void run() - { - while (!isFinish()) - { - try - { - step(); - GameView.update(); - Thread.sleep(time); - } - catch (InterruptedException e) - { e.printStackTrace(); } - } - } -} + /** + * Bloc statique exécuté au chargement de la classe pour vérifier + * si le programme dispose d'un environnement graphique. + */ + static { + if (GraphicsEnvironment.isHeadless()) + { + System.err.println("Aucun serveur d'affichage trouvé"); + System.exit(1); + } + } + /** + * Constructeur principal. + * + * @param map carte du jeu + * @param carInfos liste des informations des voitures à créer + * @param state état initial du jeu + * @param time temps entre chaque étape du jeu + */ + public Game(Map map, ArrayList carInfos, State state, int time) + { + this.map = map; + this.state = state; + this.time = time; -// private Game init(int pnumber, State state) -// { -// // ajout de voiture -// int loop = map.getPathSize(); + init(carInfos); + } -// for (int i = 0; i < pnumber; i++) -// { -// cars[i] = new Car(loop, state); + /** + * Initialise le jeu en créant les vues et les objets {@link Car}. + *

+ * Chaque voiture obtient un Dashboard, la piste est affichée avec Track, + * et le Rankboard est créé pour afficher le classement. + *

+ * + * @param carInfos liste des informations des voitures + * @return l'instance de Game + */ + private Game init(ArrayList carInfos) + { + // Création des vues principales + new Track(map, cars, "Piste Formule 1", 1000, 500, 1, 1); + new Rankboard("Score", cars, 200, 200, 0, 510); -// Color color = (i < colors.size()) ? colors.get(i) : Color.BLUE; -// // new Dashboard(cars[i], "Voiture " + (i+1), this::togglePause, color, 300, 300, 300, 300*i); -// } - -// // new Track(); -// // new Rankboard(); -// return this; -// } + final int loop = map.getPathSize(); -// private boolean isFinish() -// { -// for (Car car : cars) -// { -// if (car.getFuel() == 0) -// return true; -// } -// return false; -// } + // Création de chaque voiture avec son Dashboard + int i = 0; + for (CarInfo ci : carInfos) + { + Car car = new Car(ci.name, ci.color, loop, state); + new Dashboard(car, car.toString(), this::togglePause, 300, 200, 1000, 200*i); + cars.add(car); + i++; + } + GameView.update(); + return this; + } -// private void step() throws InterruptedException -// { -// for (Car c : cars) -// { -// synchronized (this) -// { -// // pause du jeu, while si on notifyall sans faire exprès un autre bout de code -// while (paused) -// { -// wait(); -// } -// } -// c.run(); + /** + * Vérifie si le jeu est terminé. + *

+ * Le jeu est fini si au moins une voiture a épuisé son carburant. + *

+ * + * @return true si le jeu est terminé + */ + private boolean isFinish() + { + for (Car car : cars) + { + if (car.getFuel() == 0) + return true; + } + return false; + } -// if (!isSuccess) -// { -// System.err.println("Une erreur s'est produite pendant le jeu."); -// System.exit(1); -// } -// } -// } + /** + * Ajoute un observateur pour recevoir les mises à jour du jeu. + * + * @param o observateur + * @return instance de Game pour chaîner + */ + public Game addObserver(GObserver o) + { + obs.add(o); + return this; + } -// public void run() -// { -// while (!isFinish()) -// { -// try -// { -// step(); -// Thread.sleep(time); -// } -// catch (InterruptedException e) -// { e.printStackTrace(); } -// } -// } -// } + /** + * Supprime un observateur. + * + * @param o observateur + * @return instance de Game pour chaîner + */ + public Game remObserver(GObserver o) + { + obs.remove(o); + return this; + } + + /** + * Bascule l'état de pause du jeu. + *

+ * Si le jeu était en pause, il est relancé et les threads en attente sont notifiés. + *

+ * + * @return true si le jeu est maintenant en pause + */ + public synchronized boolean togglePause() + { + if (isPaused) notifyAll(); + isPaused = !isPaused; + GameView.update(); + return isPaused; + } + + /** + * Exécute un cycle du jeu + *

+ * Chaque voiture effectue son action, puis les observateurs sont notifiés. + * La boucle attend si le jeu est en pause. + *

+ * + * @throws InterruptedException si le thread est interrompu pendant wait() + */ + private synchronized void step() throws InterruptedException + { + for (int i = 0; i < cars.size(); i++) + { + while (isPaused) + wait(); + + cars.get(i).run(); + + for (GObserver o : obs) + { + if (!o.apply()) + { + System.err.println("Une erreur s'est produite pendant le jeu."); + System.exit(1); + } + } + } + } + + /** + * Boucle principale du jeu. + *

+ * Tant que le jeu n'est pas terminé, on exécute les étapes et on met à jour + * les vues toutes les 'time' millisecondes. + *

+ */ + public void run() + { + while (!isFinish()) + { + try + { + step(); + GameView.update(); + Thread.sleep(time); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + } +} \ No newline at end of file diff --git a/src/Main.java b/src/Main.java index 9a35226..b0985f5 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,34 +1,30 @@ import java.awt.Color; -import java.awt.GraphicsEnvironment; public class Main { public static void main(String[] args) throws InterruptedException { - if (!GraphicsEnvironment.isHeadless()) + Integer[][] map = new Integer[][] { - Integer[][] map = new Integer[][] - { - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -1, -1, 5, 0 }, - { 0, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 0, 0, -1, 0, 0, -1, 0 }, - { 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0 }, - { 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0 }, - { 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -1, -1, 2, 0, 0, -1, 0 }, - { 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0 }, - { 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0 }, - { 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -3, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - }; - - Map m = Map.fromInts(map); - - Game game = new Game.Builder() - .addCar(new Game.CarInfo("Voiture 1", Color.BLUE)) - .addCar(new Game.CarInfo("Voiture 2", Color.PINK)) - .addCar(new Game.CarInfo("Voiture 3", Color.RED)) - .setMap(m) - .build(); - game.run(); - } + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -1, -1, 5, 0 }, + { 0, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 0, 0, -1, 0, 0, -1, 0 }, + { 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0 }, + { 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0 }, + { 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -1, -1, 2, 0, 0, -1, 0 }, + { 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0 }, + { 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0 }, + { 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -3, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + }; + + Map m = Map.fromInts(map); + + Game game = new Game.Builder() + .addCar(new Game.CarInfo("Voiture 1", Color.BLUE)) + .addCar(new Game.CarInfo("Voiture 2", Color.PINK)) + .addCar(new Game.CarInfo("Voiture 3", Color.RED)) + .setMap(m) + .build(); + game.run(); } } \ No newline at end of file