feat: ajout Menu selection

This commit is contained in:
2025-12-19 16:18:40 +01:00
parent 203ed3c94d
commit 25c3e8dbd7
12 changed files with 254 additions and 80 deletions

View File

@@ -5,6 +5,7 @@ import model.car.BasicCar;
import model.car.DrunkCar; import model.car.DrunkCar;
import model.car.HybridCar; import model.car.HybridCar;
import model.map.Map; import model.map.Map;
import visual.SelectionView;
public class Main { public class Main {
public static void main(String[] args) throws InterruptedException { public static void main(String[] args) throws InterruptedException {
@@ -21,14 +22,12 @@ public class Main {
{ 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, 0, 0, 0, 0, 0 },
}); });
Game game = new Game.Builder() SelectionView game = new SelectionView(3);
.car(new HybridCar(new BasicCar("Luwik", Color.RED)))
.car(new DrunkCar(new BasicCar("Charazade", Color.PINK))) game.getGameBuilder()
.track("Piste Formule 1", 1000, 500, 1, 1) .track("Piste Formule 1", 1000, 500, 1, 1)
.rankboard("Score", 200, 200, 0, 510) .rankboard("Score", 200, 200, 0, 510)
.dashboards(300, 200, 1000, 0) .dashboards(300, 200, 1000, 0)
.map(map) .map(map);
.build();
game.run();
} }
} }

View File

@@ -39,19 +39,19 @@ public class Game {
public Builder rankboard(String title, int width, public Builder rankboard(String title, int width,
int height, int x, int y) { int height, int x, int y) {
this.OBSERVERS.add(new Rankboard(null, title, width, height, x, y)); this.OBSERVERS.add(new RankboardView(null, title, width, height, x, y));
return this; return this;
} }
public Builder track(String title, int width, public Builder track(String title, int width,
int height, int x, int y) { int height, int x, int y) {
this.OBSERVERS.add(new Track(null, title, width, height, x, y)); this.OBSERVERS.add(new TrackView(null, title, width, height, x, y));
return this; return this;
} }
public Builder dashboard(Car car, String title, int width, public Builder dashboard(Car car, String title, int width,
int height, int x, int y) { int height, int x, int y) {
this.OBSERVERS.add(new Dashboard(null, car, title, width, height, x, y)); this.OBSERVERS.add(new DashboardView(null, car, title, width, height, x, y));
return this; return this;
} }

View File

@@ -122,7 +122,7 @@ public class BasicCar implements Car {
state = next; state = next;
return ""; return "";
} }
/** /**
* Fait avancer la voiture d'un certain nombre de positions. * Fait avancer la voiture d'un certain nombre de positions.
* <p> * <p>
@@ -130,73 +130,78 @@ public class BasicCar implements Car {
* incrémenté et * incrémenté et
* la position revient à zéro. * la position revient à zéro.
* </p> * </p>
* *
* @param move nombre de positions à avancer * @param move nombre de positions à avancer
* @return cette même instance (pour chaînage fluide) * @return cette même instance (pour chaînage fluide)
*/ */
private void move() { private void move() {
int jump = RANDOM.nextInt(state.MIN, state.MAX); int jump = RANDOM.nextInt(state.MIN, state.MAX);
for (int i = 0; i < jump; i++) { for (int i = 0; i < jump; i++) {
pos = state.move(pos, movement); pos = state.move(pos, movement);
Point point = map.getPath(pos); Point point = map.getPath(pos);
Circuit element = map.getElement(point.x, point.y); Circuit element = map.getElement(point.x, point.y);
if (hasAccident(element, jump)) { if (hasAccident(element, jump)) {
setDamage(); setDamage();
return; return;
} }
round = pos / map.getPathSize(); round = pos / map.getPathSize();
} }
} }
private boolean hasAccident(Circuit element, int jump) { private boolean hasAccident(Circuit element, int jump) {
return element.isYRoad() && element.getValue() <= jump; return element.isYRoad() && element.getValue() <= jump;
} }
/** /**
* Consomme du carburant en fonction de l'état du jeu. * Consomme du carburant en fonction de l'état du jeu.
* *
* @return cette même instance pour chaînage * @return cette même instance pour chaînage
*/ */
public void consumeFuel() { public void consumeFuel() {
fuel = state.fuelConsumption(fuel); fuel = state.fuelConsumption(fuel);
if (fuel < 0) if (fuel < 0)
fuel = 0; // sécurité fuel = 0; // sécurité
} }
public boolean hasFinished() { public boolean hasFinished() {
return 3 < round; return 3 < round;
} }
/** /**
* Exécute une "étape" de la voiture : avance d'une position aléatoire et * Exécute une "étape" de la voiture : avance d'une position aléatoire et
* consomme du carburant. * consomme du carburant.
* <p> * <p>
* La progression est déterminée par un intervalle aléatoire fourni par l'état * La progression est déterminée par un intervalle aléatoire fourni par l'état
* du jeu. * du jeu.
* </p> * </p>
*/ */
@Override @Override
public boolean apply() { public boolean apply() {
if (state.isDamaged()) { if (state.isDamaged()) {
decreaseDamage(); decreaseDamage();
} else if (fuel > 0) { } else if (fuel > 0) {
move(); move();
if (isConsuming) if (isConsuming)
consumeFuel(); consumeFuel();
}
return !hasFinished();
} }
return !hasFinished();
}
@Override
public void consumption(boolean active) {
isConsuming = active;
}
@Override @Override
public void consumption(boolean active) { public Car remove() {
isConsuming = active; return this;
} }
@Override @Override
public void reverse(boolean active) { public void reverse(boolean active) {
movement = (active) ? -1 : 1; movement = (active) ? -1 : 1;
} }

View File

@@ -13,18 +13,21 @@ public interface Car extends Observer {
public void reverse(boolean active); public void reverse(boolean active);
public void consumption(boolean active); public void consumption(boolean active);
public Car remove();
public String getName(); public String getName();
public int getPosition(); public int getPosition();
public int getScore(); public int getScore();
public int getRound(); public int getRound();
public int getFuel(); public int getFuel();
public State getState(); public State getState();
public Color getColor(); public Color getColor();
public void setMap(Map map); public void setMap(Map map);

View File

@@ -11,6 +11,11 @@ public abstract class CarDecorator implements Car {
this.car = car; this.car = car;
} }
@Override
public Car remove() {
return car;
}
@Override @Override
public String accelerate() { public String accelerate() {
return car.accelerate(); return car.accelerate();

View File

@@ -1,7 +1,5 @@
package model.car; package model.car;
import java.util.Random;
/** /**
* DrunkCar = décorateur "pilote ivre". * DrunkCar = décorateur "pilote ivre".
* *
@@ -14,8 +12,7 @@ import java.util.Random;
* sans modifier la classe Car. * sans modifier la classe Car.
*/ */
public class DrunkCar extends CarDecorator { public class DrunkCar extends CarDecorator {
/** Générateur de nombres aléatoires pour simuler la progression */ private boolean reverse = false;
protected static final Random RANDOM = new Random();
public DrunkCar(Car car) { public DrunkCar(Car car) {
super(car); super(car);
@@ -25,9 +22,9 @@ public class DrunkCar extends CarDecorator {
// 50% : fait l'inverse // 50% : fait l'inverse
@Override @Override
public boolean apply() { public boolean apply() {
car.reverse(RANDOM.nextBoolean()); car.reverse(reverse);
car.apply(); car.apply();
car.reverse(false); reverse = !reverse;
return true; return true;
} }
} }

View File

@@ -0,0 +1,80 @@
package model.car;
import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import model.Game;
public class Selection {
private final Game.Builder gameBuilder;
private final List<Car> cars = new ArrayList<>();
public Selection(Game.Builder gameBuilder) {
this.gameBuilder = gameBuilder;
}
public List<Car> getCars() {
return new ArrayList<>(cars);
}
public Car addCar(String name, Color color) {
Car car = new BasicCar(name, color);
cars.add(car);
return car;
}
public void removeCar(Car car) {
cars.remove(car);
}
private Car addDecorator(Function<Car, Car> fn, Car car) throws IllegalArgumentException {
int index = cars.indexOf(car);
if (index < 0) {
throw new IllegalArgumentException(
"Aucune voiture dans la classe interne.");
}
car = fn.apply(car);
cars.set(index, car);
return car;
}
public Car addHybridCarDecorator(Car car) throws IllegalArgumentException {
return addDecorator(HybridCar::new, car);
}
public Car addDrunkCarDecorator(Car car) throws IllegalArgumentException {
return addDecorator(DrunkCar::new, car);
}
public Car addBoostCarDecorator(Car car) throws IllegalArgumentException {
return addDecorator(BoostCar::new, car);
}
public Car removeDecorator(Car car) throws IllegalArgumentException {
int index = cars.indexOf(car);
if (index < 0) {
throw new IllegalArgumentException(
"Aucune voiture dans la classe interne.");
}
car = car.remove();
cars.set(index, car);
return car;
}
public Game.Builder select() {
for (Car car : cars) {
gameBuilder.car(car);
System.out.println("hello world");
}
return gameBuilder;
}
public int size() {
return cars.size();
}
}

View File

@@ -24,7 +24,7 @@ import model.car.HybridCar;
* - un bouton Accelerer * - un bouton Accelerer
* - un bouton Rallentir * - un bouton Rallentir
*/ */
public class Dashboard extends GameView { public class DashboardView extends GameView {
/** Label affichant carburant et nombre de tours */ /** Label affichant carburant et nombre de tours */
private final JLabel infoLabel = new JLabel(); private final JLabel infoLabel = new JLabel();
@@ -58,7 +58,7 @@ public class Dashboard extends GameView {
* @param x position horizontale de la fenêtre * @param x position horizontale de la fenêtre
* @param y position verticale de la fenêtre * @param y position verticale de la fenêtre
*/ */
public Dashboard(Game game, Car car, String title, int width, int height, int x, int y) { public DashboardView(Game game, Car car, String title, int width, int height, int x, int y) {
super(game, "Dashboard: " + title, width, height, x, y); super(game, "Dashboard: " + title, width, height, x, y);
this.car = car; this.car = car;

View File

@@ -66,7 +66,8 @@ public abstract class GameView extends JComponent implements Game.Observer {
// mettre un layout (la disposition des elements de la fenetre) // mettre un layout (la disposition des elements de la fenetre)
frame.setLayout(new BorderLayout()); frame.setLayout(new BorderLayout());
game.addObserver(this); if (game != null)
game.addObserver(this);
} }
protected GameView(Game game, String title, int width, int height, int x, int y) { protected GameView(Game game, String title, int width, int height, int x, int y) {

View File

@@ -18,7 +18,7 @@ import model.car.Car;
* Les scores sont triés du plus grand au plus petit. * Les scores sont triés du plus grand au plus petit.
* </p> * </p>
*/ */
public class Rankboard extends GameView { public class RankboardView extends GameView {
/** Liste des voitures à afficher */ /** Liste des voitures à afficher */
List<Car> cars; List<Car> cars;
@@ -43,7 +43,7 @@ public class Rankboard extends GameView {
* @param x Position horizontale de la fenêtre * @param x Position horizontale de la fenêtre
* @param y Position verticale de la fenêtre * @param y Position verticale de la fenêtre
*/ */
public Rankboard(Game game, String title, int width, int height, int x, int y) { public RankboardView(Game game, String title, int width, int height, int x, int y) {
super(game, title, width, height, x, y); super(game, title, width, height, x, y);
if (game != null) if (game != null)
init(game); init(game);

View File

@@ -0,0 +1,84 @@
package visual;
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JPanel;
import model.Game;
import model.car.Car;
import model.car.Selection;
public class SelectionView extends GameView {
private Game.Builder gameBuilder = new Game.Builder();
private Selection selection = new Selection(gameBuilder);
private JPanel buttonPanel = new JPanel();
public Game.Builder getGameBuilder() {
return gameBuilder;
}
public SelectionView(int ncar) {
super(null, "Menu de sélection", 500, 300, 400, 400);
init(null); // forcer le init
buttonPanel.setLayout(new GridLayout(0, 3, 5, 5));
frame.add(buttonPanel, BorderLayout.CENTER);
for (int i = 1; i <= ncar; i++) {
Car car = selection.addCar("Car " + i, Color.getHSBColor(i / 3f, 0.8f, 0.8f));
// bouton Hybrid
JButton hybridBtn = new JButton("Hybrid " + car.getName());
// bouton Drunk
JButton drunkBtn = new JButton("Drunk " + car.getName());
// bouton boost
JButton boostBtn = new JButton("Boost " + car.getName());
final int I = i;
hybridBtn.addActionListener((ActionEvent e) -> {
try {
Car current = selection.getCars().get(I-1);
selection.addHybridCarDecorator(current);
hybridBtn.setEnabled(false);
} catch (Exception ex) {
ex.printStackTrace();
}
});
drunkBtn.addActionListener((ActionEvent e) -> {
try {
Car current = selection.getCars().get(I-1);
selection.addDrunkCarDecorator(current);
drunkBtn.setEnabled(false);
} catch (Exception ex) {
ex.printStackTrace();
}
});
boostBtn.addActionListener((ActionEvent e) -> {
try {
Car current = selection.getCars().get(I-1);
selection.addBoostCarDecorator(current);
boostBtn.setEnabled(false);
} catch (Exception ex) {
ex.printStackTrace();
}
});
buttonPanel.add(hybridBtn);
buttonPanel.add(drunkBtn);
buttonPanel.add(boostBtn);
}
JButton startBtn = new JButton("Start");
startBtn.addActionListener((ActionEvent e) -> {
frame.dispose();
new Thread(() -> selection.select().build().run()).start();
});
this.frame.add(startBtn, BorderLayout.SOUTH);
frame.revalidate();
frame.repaint();
}
}

View File

@@ -23,7 +23,7 @@ import model.map.Map;
* est dessinée selon son type. Les voitures sont superposées sur la grille. * est dessinée selon son type. Les voitures sont superposées sur la grille.
* </p> * </p>
*/ */
public class Track extends GameView { public class TrackView extends GameView {
/** La carte du circuit */ /** La carte du circuit */
private Map map; private Map map;
/** Liste des voitures à dessiner */ /** Liste des voitures à dessiner */
@@ -49,7 +49,7 @@ public class Track extends GameView {
* @param x Position X de la fenêtre * @param x Position X de la fenêtre
* @param y Position Y de la fenêtre * @param y Position Y de la fenêtre
*/ */
public Track(Game game, String title, int width, int height, int x, int y) { public TrackView(Game game, String title, int width, int height, int x, int y) {
super(game, title, width, height, x, y); super(game, title, width, height, x, y);
if (game != null) if (game != null)
init(game); init(game);