import java.awt.Color; 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 { /** * {@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 record CarInfo(String name, Color color) {} /** * {@link VisualInfo} est un enregistrement (record) qui décrit une vue graphique * à afficher dans le jeu (par exemple un tableau de bord, une piste ou un classement). ** Chaque instance contient toutes les informations nécessaires pour créer et positionner * cette vue à l’écran. *
* * @param type le type concret de la vue (classe héritant de {@link GameView}) * @param title le titre de la fenêtre ou du panneau associé * @param width la largeur en pixels de la vue * @param height la hauteur en pixels de la vue * @param x la position horizontale (en pixels) de la vue sur l’écran * @param y la position verticale (en pixels) de la vue sur l’écran */ public record VisualInfo ( Class extends GameView> type, String title, int width, int height, int x, int y ) {} /** * 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* 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); } Game game = new Game(map, cars, state, time); buildVisual(game); return game; } } 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; /** Liste des voitures du jeu */ private final ArrayList* 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* 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; } /** * 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; } /** * 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; return isPaused; } public void notifyObservers() { for (GObserver o : obs) { boolean isSuccess = o.apply(); if (!isSuccess) { System.err.println("Une erreur s'est produite pendant le jeu."); System.exit(1); } } } /** * 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 void step() throws InterruptedException { for (Car car : cars) { synchronized(this) { while (isPaused) wait(); } car.run(); notifyObservers(); } } /** * 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(); Thread.sleep(time); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Fini!\nVoici le score :"); for (Car c : cars) { System.out.println(c.getName() + "\t" + c.getScore()); } System.exit(0); } public ArrayList