From 86383155cdf7bb792d29101e4d37167e0a4069eb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lo=C3=AFc=20GUEZO?=
Date: Fri, 19 Dec 2025 18:46:27 +0100
Subject: [PATCH] feat(Game): ajout commentaire et ajout fonction setup
---
src/model/Game.java | 245 ++++++++++++++++++++++++++++----
src/model/car/BasicCar.java | 124 ++++++++--------
src/model/car/CarDecorator.java | 9 +-
src/visual/GameView.java | 7 +-
src/visual/RankboardView.java | 7 +-
5 files changed, 303 insertions(+), 89 deletions(-)
diff --git a/src/model/Game.java b/src/model/Game.java
index c37c2bd..22c916c 100644
--- a/src/model/Game.java
+++ b/src/model/Game.java
@@ -2,75 +2,188 @@ package model;
import java.util.ArrayList;
import java.util.List;
-import java.util.function.Consumer;
import model.car.Car;
import model.map.Map;
import visual.*;
+/**
+ * {@code Game} représente le cœur du moteur de jeu.
+ */
public class Game {
- public static interface Observer extends Consumer {
+ /**
+ * {@code Observer} représente une entité réagissant au déroulement
+ * du jeu : voiture, vue graphique, tableau de scores, etc.
+ *
+ *
+ * Les fonctions disponible dans l'interface sont les suivantes:
+ *
+ * - {@link #setup(Game)} : appelée lors de l'initialisation
+ * - {@link #apply()} : appelée à chaque tick du jeu
+ * - {@link #end()} : appelée lorsque le jeu se termine
+ *
+ *
+ */
+ public static interface Observer {
/**
+ * Méthode appelée à chaque tick du jeu.
*
- * @return si False le programme s'arrete, sinon il continue
+ * @return {@code true} si le jeu doit continuer,
+ * {@code false} si le jeu doit s'arrêter
*/
public boolean apply();
+
+ /**
+ * Méthode appelée lors de la création du jeu. Très
+ * utile si on veut récupérer des informations pas
+ * encore initialisée.
+ *
+ * @param game l'instance du jeu associée à cet observer
+ */
+ public void setup(Game game);
+
+ /**
+ * Méthode appelée lorsque le jeu se termine. Utile
+ * comme Destructor de classe ou pour information de
+ * fin.
+ */
+ public void end();
}
+ /**
+ * {@code Builder} est responsable de la construction contrôlée
+ * d'une instance de {@link Game}.
+ *
+ * Il permet de configurer l'ensemble des éléments du jeu avant son lancement :
+ *
+ * - les voitures ({@link Car})
+ * - les vues graphiques ({@link GameView})
+ * - la carte ({@link Map})
+ * - le temps entre chaque tick
+ *
+ *
+ */
public static class Builder {
+ /**
+ * {@code DashboardConfig} encapsule les paramètres communs
+ * nécessaires à la création automatique de plusieurs dashboards.
+ *
+ */
private static record DashboardConfig(int width, int height, int x, int y) {
+ /**
+ * Initialise un dashboard pour une voiture donnée.
+ *
+ * @param builder le builder utilisé pour ajouter la vue
+ * @param car la voiture associée au dashboard
+ * @param index l'indice de la voiture (utilisé pour le décalage vertical)
+ */
public void initDashboard(Builder builder, Car car, int index) {
- builder.dashboard(car, car.getName(), width, height, x, y + (height * index));
+ builder.dashboard(
+ car,
+ car.getName(),
+ width, height,
+ x, y + (height * index));
}
}
+ /** Liste des voitures participant à la partie */
private final List cars = new ArrayList<>();
+
+ /** Liste des vues graphiques observant le jeu */
private final List views = new ArrayList<>();
+ /** Configuration globale des dashboards automatiques */
private DashboardConfig dashboardConfig = null;
+
+ /** Temps (en millisecondes) entre deux ticks du jeu */
private int time = 500;
+
+ /** La classe Map */
private Map map = null;
+ /**
+ * Ajoute une voiture au jeu.
+ *
+ * @param car la voiture à ajouter
+ * @return le builder courant (chaînage fluide)
+ */
public Builder car(Car car) {
cars.add(car);
return this;
}
+ /**
+ * Définit la carte du jeu.
+ *
+ * @param map la carte du circuit
+ * @return le builder courant
+ */
public Builder map(Map map) {
this.map = map;
return this;
}
+ /**
+ * Définit le temps entre chaque tick.
+ *
+ * @param time durée en millisecondes
+ * @return le builder courant
+ */
public Builder time(int time) {
this.time = time;
return this;
}
+ /**
+ * Ajoute une vue de classement.
+ */
public Builder rankboard(String title, int width, int height, int x, int y) {
views.add(new RankboardView(null, title, width, height, x, y));
return this;
}
+ /**
+ * Ajoute la vue principale du circuit.
+ */
public Builder track(String title, int width, int height, int x, int y) {
views.add(new TrackView(null, title, width, height, x, y));
return this;
}
+ /**
+ * Ajoute un dashboard lié à une voiture.
+ */
public Builder dashboard(Car car, String title, int width, int height, int x, int y) {
views.add(new DashboardView(null, car, title, width, height, x, y));
return this;
}
+ /**
+ * Configure la création automatique d'un dashboard par voiture.
+ */
public Builder dashboards(int width, int height, int x, int y) {
dashboardConfig = new DashboardConfig(width, height, x, y);
return this;
}
+ /**
+ * Construit et initialise le jeu.
+ *
+ * Cette méthode :
+ *
+ * - crée automatiquement les dashboards si configurés
+ * - regroupe toutes les voitures et vues comme observateurs
+ * - instancie le {@link Game}
+ * - appelle {@link Game.Observer#setup(Game)} sur chaque observateur
+ *
+ *
+ *
+ * @return une instance de {@link Game} prête à être lancée
+ */
public Game build() {
if (dashboardConfig != null) {
- int index = 0;
- for (Car car : new ArrayList<>(cars)) {
- dashboardConfig.initDashboard(this, car, index++);
+ for (int i = 0; i < cars.size(); i++) {
+ dashboardConfig.initDashboard(this, cars.get(i), i);
}
}
@@ -81,78 +194,143 @@ public class Game {
Game game = new Game(map, time, observers);
for (Game.Observer obs : new ArrayList<>(observers)) {
- obs.accept(game);
+ obs.setup(game);
}
return game;
}
}
+ /** Carte du jeu (circuit, environnement, etc.) */
private Map map;
+
+ /** Temps (en millisecondes) entre deux ticks du moteur */
private int time;
+
+ /** Liste des observateurs du jeu (voitures, vues, tableaux, etc.) */
private List observers;
+ /** Indique si le jeu est actuellement en pause */
private boolean isPaused;
- private Game() {
- }
-
+ /**
+ * Constructeur principal du moteur de jeu.
+ *
+ * @param map la carte du jeu
+ * @param time le temps entre chaque tick
+ * @param observer la liste des observateurs initialisés
+ */
private Game(Map map, int time, List observer) {
this.map = map;
this.time = time;
this.observers = observer;
}
+ /**
+ * Ajoute dynamiquement un observateur au jeu.
+ *
+ * @param o l'observateur à ajouter
+ * @return l'instance courante du jeu
+ */
public Game addObserver(Observer o) {
observers.add(o);
return this;
}
+ /**
+ * Supprime un observateur du jeu.
+ *
+ * @param o l'observateur à retirer
+ * @return l'instance courante du jeu
+ */
public Game removeObserver(Observer o) {
observers.remove(o);
return this;
}
- private boolean isFinish() {
+ /**
+ * Détermine si la partie est terminée.
+ *
+ * La partie est considérée comme finie lorsque
+ * toutes les voitures n'ont plus de carburant.
+ *
+ * @return {@code true} si la partie est terminée
+ */
+ private boolean hasEnoughFuel() {
for (Game.Observer observer : observers) {
- switch (observer) {
- case Car car -> {
- if (car.getFuel() > 0)
- return false;
- }
- default -> {
- }
+ if (observer instanceof Car car && car.getFuel() > 0) {
+ return true;
}
}
+ return false;
+ }
+ /**
+ * Notifie tous les observers pour un tick.
+ *
+ * @return {@code true} si le jeu peut continuer
+ */
+ public boolean notifyObservers() {
+ for (Observer o : observers) {
+ if (!o.apply()) {
+ return false;
+ }
+ }
return true;
}
- public void notifyObservers() {
- for (Observer o : observers) {
- if (!o.apply()) {
- System.exit(0);
- }
- }
+ /**
+ * Indique si la partie est terminée.
+ *
+ * @return {@code true} si le jeu est terminé
+ */
+ // DOIT ETRE MODIFIÉE SI AJOUT CONDITION DE FIN
+ private boolean isGameOver() {
+ return !(hasEnoughFuel());
}
+ /**
+ * Notifie tous les observers pour la fin de partie.
+ */
+ public void notifyEnd() {
+ for (Observer o : observers) {
+ o.end();
+ }
+ System.exit(0);
+ }
+
+ /**
+ * Lance la boucle principale du moteur de jeu.
+ *
+ * La boucle s'exécute tant que :
+ *
+ * - la partie n'est pas terminée
+ * - aucun observateur ne demande l'arrêt
+ *
+ *
+ * La boucle respecte également l'état de pause.
+ */
public void run() {
try {
- while (!isFinish()) {
+ while (isGameOver() && notifyObservers()) {
synchronized (this) {
while (isPaused)
wait();
}
- notifyObservers();
Thread.sleep(time);
}
} catch (InterruptedException e) {
e.printStackTrace();
System.exit(1);
}
-
+ notifyEnd();
}
+ /**
+ * Active ou désactive la pause du jeu.
+ *
+ * @return l'état de pause après modification
+ */
public synchronized boolean togglePause() {
if (isPaused)
notifyAll();
@@ -160,6 +338,11 @@ public class Game {
return isPaused;
}
+ /**
+ * Retourne la liste des voitures participant au jeu.
+ *
+ * @return une liste de {@link Car}
+ */
public List getCars() {
return observers.stream()
.filter(o -> o instanceof Car)
@@ -167,10 +350,16 @@ public class Game {
.toList();
}
+ /**
+ * Retourne la carte du jeu.
+ */
public Map getMap() {
return map;
}
+ /**
+ * Indique si le jeu est actuellement en pause.
+ */
public boolean getPause() {
return isPaused;
}
diff --git a/src/model/car/BasicCar.java b/src/model/car/BasicCar.java
index 6cada1f..b88f407 100644
--- a/src/model/car/BasicCar.java
+++ b/src/model/car/BasicCar.java
@@ -123,7 +123,7 @@ public class BasicCar implements Car {
state = next;
return "";
}
-
+
/**
* Fait avancer la voiture d'un certain nombre de positions.
*
@@ -131,78 +131,78 @@ public class BasicCar implements Car {
* incrémenté et
* la position revient à zéro.
*
- *
- * @param move nombre de positions à avancer
- * @return cette même instance (pour chaînage fluide)
- */
- private void move() {
- int jump = RANDOM.nextInt(state.MIN, state.MAX);
-
- for (int i = 0; i < jump; i++) {
- pos = state.move(pos, movement);
-
- Point point = map.getPath(pos);
- Circuit element = map.getElement(point.x, point.y);
-
- if (hasAccident(element, jump)) {
- setDamage();
- return;
+ *
+ * @param move nombre de positions à avancer
+ * @return cette même instance (pour chaînage fluide)
+ */
+ private void move() {
+ int jump = RANDOM.nextInt(state.MIN, state.MAX);
+
+ for (int i = 0; i < jump; i++) {
+ pos = state.move(pos, movement);
+
+ Point point = map.getPath(pos);
+ Circuit element = map.getElement(point.x, point.y);
+
+ if (hasAccident(element, jump)) {
+ setDamage();
+ return;
}
round = pos / map.getPathSize();
}
}
-
+
private boolean hasAccident(Circuit element, int jump) {
return element.isYRoad() && element.getValue() <= jump;
}
-
+
/**
* Consomme du carburant en fonction de l'état du jeu.
- *
- * @return cette même instance pour chaînage
- */
- public void consumeFuel() {
- fuel = state.fuelConsumption(fuel);
- if (fuel < 0)
- fuel = 0; // sécurité
-}
-
-public boolean hasFinished() {
- return 3 < round;
-}
-
-/**
- * Exécute une "étape" de la voiture : avance d'une position aléatoire et
- * consomme du carburant.
- *
- * La progression est déterminée par un intervalle aléatoire fourni par l'état
- * du jeu.
- *
-*/
-@Override
-public boolean apply() {
- if (state.isDamaged()) {
- decreaseDamage();
- } else if (fuel > 0) {
- move();
- if (isConsuming)
- consumeFuel();
+ *
+ * @return cette même instance pour chaînage
+ */
+ public void consumeFuel() {
+ fuel = state.fuelConsumption(fuel);
+ if (fuel < 0)
+ fuel = 0; // sécurité
}
- return !hasFinished();
-}
-@Override
-public void consumption(boolean active) {
- isConsuming = active;
-}
+ public boolean finished() {
+ return 3 < round;
+ }
+
+ /**
+ * Exécute une "étape" de la voiture : avance d'une position aléatoire et
+ * consomme du carburant.
+ *
+ * La progression est déterminée par un intervalle aléatoire fourni par l'état
+ * du jeu.
+ *
+ */
+ @Override
+ public boolean apply() {
+ if (state.isDamaged()) {
+ decreaseDamage();
+ } else if (fuel > 0) {
+ move();
+ if (isConsuming)
+ consumeFuel();
+ }
+ return !finished();
+ }
+
+ @Override
+ public void consumption(boolean active) {
+ isConsuming = active;
+ }
@Override
public Car remove() {
return this;
}
-@Override
-public void reverse(boolean active) {
+ @Override
+ public void reverse(boolean active) {
movement = (active) ? -1 : 1;
}
@@ -255,7 +255,17 @@ public void reverse(boolean active) {
}
@Override
- public void accept(Game game) {
+ public void setup(Game game) {
this.map = game.getMap();
}
+
+ @Override
+ public String toString() {
+ return "nom: " + NAME + " score: " + getScore();
+ }
+
+ @Override
+ public void end() {
+ System.out.println(this);
+ }
}
diff --git a/src/model/car/CarDecorator.java b/src/model/car/CarDecorator.java
index ea985a5..f72cd26 100644
--- a/src/model/car/CarDecorator.java
+++ b/src/model/car/CarDecorator.java
@@ -77,7 +77,12 @@ public abstract class CarDecorator implements Car {
}
@Override
- public void accept(Game game) {
- car.accept(game);
+ public void setup(Game game) {
+ car.setup(game);
+ }
+
+ @Override
+ public void end() {
+ car.end();
}
}
\ No newline at end of file
diff --git a/src/visual/GameView.java b/src/visual/GameView.java
index 3156c51..edada9f 100644
--- a/src/visual/GameView.java
+++ b/src/visual/GameView.java
@@ -32,7 +32,7 @@ public abstract class GameView extends JComponent implements Game.Observer {
}
}
- public void accept(Game game) {
+ public void setup(Game game) {
this.game = game;
init(game);
}
@@ -85,4 +85,9 @@ public abstract class GameView extends JComponent implements Game.Observer {
public boolean apply() {
return (game != null);
}
+
+ @Override
+ public void end() {
+ frame.dispose();
+ }
}
\ No newline at end of file
diff --git a/src/visual/RankboardView.java b/src/visual/RankboardView.java
index ab7a426..bfe5ae8 100644
--- a/src/visual/RankboardView.java
+++ b/src/visual/RankboardView.java
@@ -57,7 +57,8 @@ public class RankboardView extends GameView {
*
*/
private void updateRankText() {
- if (cars == null) return;
+ if (cars == null)
+ return;
// cloner pour de modifier la classe principale
List cars_clone = new ArrayList<>(cars);
cars_clone.sort(Comparator.comparingInt(Car::getScore).reversed());
@@ -84,4 +85,8 @@ public class RankboardView extends GameView {
updateRankText();
return true;
}
+
+ @Override
+ public void end() {
+ }
}