diff --git a/src/Circuit.java b/src/Circuit.java deleted file mode 100644 index 8f52aee..0000000 --- a/src/Circuit.java +++ /dev/null @@ -1,138 +0,0 @@ -/** - * Représente une cellule du circuit. - *

- * Chaque cellule possède un type ({@link Cell}) et éventuellement une valeur - * numérique (par exemple pour indiquer une intensité, une vitesse, ou un identifiant de route). - *

- */ -public class Circuit -{ - /** - * Cell est un enum - * représentant les différents types de - * cases qui composent le circuit de - * course. - */ - public static enum Cell - { - /** - * Case hors piste, non - * praticable par les - * voitures. */ - EMPTY, - - /** - * Case de route normale - * sur laquelle les voitures - * peuvent circuler. - */ - ROAD, - - /** - * Case correspondant à la - * ligne de départ du circuit. - */ - START, - - /** - * Case correspondant à la - * ligne d'arrivée du circuit. - */ - FINISH, - - /** - * Case de route jaune, plus - * d'information sur le - * livrable 2 - */ - YROAD; - } - - /** Type de la cellule (vide, route, départ, arrivée, etc.) */ - private final Cell type; - - /** Valeur associée à la cellule (optionnelle, dépend du type) */ - private int value; - - /** - * Construit une cellule avec un type défini et une valeur par défaut - * égale à l’indice ordinal du type. - * - * @param type le type de la cellule - */ - public Circuit(Cell type) - { - this.type = type; - this.value = type.ordinal(); - } - - /** - * Construit une cellule avec un type et une valeur spécifique. - * - * @param type le type de la cellule - * @param value la valeur associée à la cellule - */ - public Circuit(Cell type, int value) - { - this.type = type; - this.value = value; - } - - /** - * Modifie la valeur associée à la cellule. - * - * @param value la nouvelle valeur - * @return cette même instance (pour chaînage fluide) - */ - public Circuit setValue(int value) - { - this.value = value; - return this; - } - - /** - * @return le type de la cellule - */ - public Cell getType() - { - return type; - } - - /** - * @return la valeur associée à la cellule - */ - public int getValue() - { - return value; - } - - /** - * Vérifie si la cellule est une route (ROAD ou YROAD). - * - * @return vrai si la cellule représente une route - */ - public boolean isRoad() - { - return type == Cell.ROAD || type == Cell.YROAD; - } - - /** - * Vérifie si la cellule est un point de départ. - * - * @return vrai si la cellule représente le départ - */ - public boolean isStart() - { - return type == Cell.START; - } - - /** - * Vérifie si la cellule est un point d’arrivée. - * - * @return vrai si la cellule représente la fin du circuit - */ - public boolean isFinish() - { - return type == Cell.FINISH; - } -} \ No newline at end of file diff --git a/src/GObserver.java b/src/GObserver.java deleted file mode 100644 index 6ad48c9..0000000 --- a/src/GObserver.java +++ /dev/null @@ -1,13 +0,0 @@ -@FunctionalInterface -/** - * L'interface utilisée pour Game. - */ -public interface GObserver -{ - /** - * - * @return true si la fonction s'est bien passé sinon false (le programme va se - * stopper) - */ - public boolean apply(); -} diff --git a/src/Game.java b/src/Game.java index 266fd54..4648a53 100644 --- a/src/Game.java +++ b/src/Game.java @@ -9,19 +9,34 @@ import java.util.ArrayList; * (pause, boucle de jeu, observateurs). *

*/ -public class Game -{ +public class Game { + @FunctionalInterface + /** + * L'interface utilisée pour Game. + */ + public interface observer { + /** + * + * @return true si la fonction s'est bien passé sinon false (le programme va se + * stopper) + */ + public boolean apply(); + } + /** * {@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) {} - + private 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). + * {@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 + * Chaque instance contient toutes les informations nécessaires pour créer et + * positionner * cette vue à l’écran. *

* @@ -32,13 +47,41 @@ public class Game * @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 type, - String title, - int width, int height, - int x, int y - ) {} + private record VisualInfo(Class type, + String title, int width, int height, int x, int y) { + } + + public static class GameFactory { + public static Map defaultMap() { + return Map.fromInts(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 }, + }); + } + + public static Game defaultGame(Map map) { + return new Game.Builder() + .addCar("Voiture à LUWIK", Color.BLUE) + .addCar("Voiture à CHARAZADE", Color.PINK) + .addCar("Voiture de UPEC", Color.RED) + .addVisual(Dashboard.class, "Voiture à LUWIK", 300, 200, 1000, 0) + .addVisual(Dashboard.class, "Voiture à CHARAZADE", 300, 200, 1000, 200) + .addVisual(Dashboard.class, "Voiture de UPEC", 300, 200, 1000, 400) + .addVisual(Track.class, "Piste Formule 1", 1000, 500, 1, 1) + .addVisual(Rankboard.class, "Score", 200, 200, 0, 510) + .setTime(1000) + .setMap(map) + .build(); + } + } /** * Builder pour créer une instance de {@link Game} de façon fluide. @@ -47,84 +90,80 @@ public class Game * le temps entre les étapes du jeu avant de construire l'objet final. *

*/ - public static class Builder - { + public static class Builder { /** Liste des voitures à créer pour le jeu */ private ArrayList cars = new ArrayList<>(); /** Liste des voitures à créer pour le jeu */ private ArrayList visuals = new ArrayList<>(); /** État initial du jeu */ - private State state = new State(); + private Car.State state = Car.State.NORMAL; /** Temps entre chaque step du jeu */ private int time = 1000; /** Carte sur laquelle se déroule le jeu */ private Map map = null; /** Ajoute une voiture à la liste */ - public Builder addCar(CarInfo car) - { - cars.add(car); + public Builder addCar(String name, Color color) { + cars.add(new CarInfo(name, color)); return this; } /** Supprime une voiture de la liste */ - public Builder remCar(CarInfo car) - { - cars.remove(car); + public Builder removeCar(String name, Color color) { + cars.forEach((car) -> { + if (car.name == name && car.color == color) + cars.remove(car); + }); return this; } /** Définit la carte du jeu */ - public Builder setMap(Map map) - { + public Builder setMap(Map map) { this.map = map; return this; } /** Définit l'état initial du jeu */ - public Builder setState(State s) - { + public Builder setState(Car.State s) { this.state = s; return this; } /** Définit le temps entre chaque étape du jeu */ - public Builder setTime(int time) - { + public Builder setTime(int time) { this.time = time; return this; } - public Builder addVisual(Class type, String title, int width, int height, int x, int y) - { + public Builder addVisual(Class type, String title, + int width, int height, int x, int y) { visuals.add(new VisualInfo(type, title, width, height, x, y)); return this; } - private void buildVisual(Game game) - { - for (VisualInfo v : visuals) - { - if (v.type == Rankboard.class) - game.addObserver(new Rankboard(game, v.title, v.width, v.height, v.x, v.y)); - else if (v.type == Track.class) - game.addObserver(new Track(game, v.title, v.width, v.height, v.x, v.y)); - else if (v.type == Dashboard.class) - { - for (CarInfo info : cars) - { - if (info.name.equals(v.title)) - { - Car car = game.getCars().stream() - .filter(c -> c.getName().equals(info.name)) - .findFirst() - .orElse(null); - if (car != null) - game.addObserver(new Dashboard(game, car, v.title, v.width, v.height, v.x, v.y)); - break; - } - } + private void buildVisual(Game game) { + for (VisualInfo visual : visuals) { + GameView view = null; + + if (visual.type == Rankboard.class) { + view = new Rankboard(game, visual.title, visual.width, + visual.height, visual.x, visual.y); + } else if (visual.type == Track.class) { + view = new Track(game, visual.title, visual.width, + visual.height, visual.x, visual.y); + } else if (visual.type == Dashboard.class) { + Car car = game.getCars().stream() + .filter((e) -> visual.title.equals(e.getName())) + .findFirst() + .orElseThrow(); + + view = new Dashboard(game, + car, + visual.title, visual.width, + visual.height, visual.x, visual.y); } + if (view != null) + game.addObserver(view); } } @@ -134,10 +173,8 @@ public class Game * Si la carte n'a pas été définie, le programme s'arrête. *

*/ - public Game build() - { - if (map == null) - { + public Game build() { + if (map == null) { System.err.println("Vous devez définir une carte avant de construire le jeu !"); System.exit(1); } @@ -147,38 +184,37 @@ public class Game return game; } } - + private final Map map; /** État du jeu (par exemple, positions, carburant) */ - private final State state; + private final Car.State state; /** Temps entre chaque étape du jeu en millisecondes */ private final int time; - + /** 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<>(); - + private final ArrayList obs = new ArrayList<>(); + /** Indique si le jeu est en pause */ private boolean isPaused = false; - + /** * Constructeur principal. * - * @param map carte du jeu + * @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 + * @param state état initial du jeu + * @param time temps entre chaque étape du jeu */ - public Game(Map map, ArrayList carInfos, State state, int time) - { + public Game(Map map, ArrayList carInfos, Car.State state, int time) { this.map = map; this.state = state; this.time = time; - + init(carInfos); } - + /** * Initialise le jeu en créant les vues et les objets {@link Car}. *

@@ -189,17 +225,15 @@ public class Game * @param carInfos liste des informations des voitures * @return l'instance de Game */ - private Game init(ArrayList carInfos) - { - final int loop = map.getPathSize(); - + private Game init(ArrayList carInfos) { // Création de chaque voiture avec son Dashboard for (CarInfo ci : carInfos) - cars.add(new Car(ci.name, ci.color, loop, state)); - + cars.add(new Car(ci.name, ci.color, map) + .setState(state)); + return this; } - + /** * Vérifie si le jeu est terminé. *

@@ -208,68 +242,62 @@ public class Game * * @return true si le jeu est terminé */ - private boolean isFinish() - { - for (Car car : cars) - { + private boolean isFinish() { + for (Car car : cars) { if (car.getFuel() == 0) - return true; + 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) - { + public Game addObserver(observer o) { obs.add(o); return this; } - + /** * Supprime un observateur. * * @param o observateur * @return instance de Game pour chaîner */ - public Game remObserver(GObserver o) - { + public Game remObserver(observer 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. + * 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(); + public synchronized boolean togglePause() { + if (isPaused) + notifyAll(); isPaused = !isPaused; return isPaused; } - - public void notifyObservers() - { - for (GObserver o : obs) - { + + public void notifyObservers() { + for (observer o : obs) { boolean isSuccess = o.apply(); - if (!isSuccess) - { + if (!isSuccess) { System.err.println("Une erreur s'est produite pendant le jeu."); System.exit(1); } } } - + /** * Exécute un cycle du jeu *

@@ -279,21 +307,18 @@ public class Game * * @throws InterruptedException si le thread est interrompu pendant wait() */ - private void step() throws InterruptedException - { - for (Car car : cars) - { - synchronized(this) - { + private void step() throws InterruptedException { + for (Car car : cars) { + synchronized (this) { while (isPaused) - wait(); - } - + wait(); + } + car.run(); notifyObservers(); } } - + /** * Boucle principale du jeu. *

@@ -301,46 +326,36 @@ public class Game * les vues toutes les 'time' millisecondes. *

*/ - public void run() - { - while (!isFinish()) - { - try - { + public void run() { + while (!isFinish()) { + try { step(); Thread.sleep(time); - } - catch (InterruptedException e) - { + } catch (InterruptedException e) { e.printStackTrace(); } } - + System.out.println("Fini!\nVoici le score :"); - for (Car c : cars) - { + for (Car c : cars) { System.out.println(c.getName() + "\t" + c.getScore()); } System.exit(0); } - - public ArrayList getCars() - { + + public ArrayList getCars() { return cars; } - - public Map getMap() - { + + public Map getMap() { return map; } - - public State getState() - { + + public Car.State getState() { return state; } - - public boolean getPause() - { + + public boolean getPause() { return isPaused; } }