mirror of
https://github.com/guezoloic/racing-game.git
synced 2026-03-28 18:03:50 +00:00
- ajout nouveau constructor pour clone la voiture - ajout de la fonction reversing pour faire revenir en arriere la voiture
349 lines
9.7 KiB
Java
349 lines
9.7 KiB
Java
import java.awt.Color;
|
||
import java.awt.Point;
|
||
import java.util.List;
|
||
import java.util.Random;
|
||
|
||
/**
|
||
* {@link Car} représente une voiture qui avance sur un circuit en boucles.
|
||
* Chaque appel à {@link #run()} avance la voiture d'une certaine position et
|
||
* fait perdre de l'essence.
|
||
* Quand la position atteint la fin de la boucle, un nouveau tour est compté.
|
||
* <p>
|
||
* La voiture consomme du carburant à chaque déplacement, et son score
|
||
* est calculé en fonction du nombre de tours complétés et de sa progression sur
|
||
* le tour actuel.
|
||
* </p>
|
||
*/
|
||
public class Car {
|
||
/** Générateur de nombres aléatoires pour simuler la progression */
|
||
protected static final Random RANDOM = new Random();
|
||
|
||
/** Couleur de la voiture pour l'affichage */
|
||
private final Color COLOR;
|
||
/** Nom de la voiture */
|
||
private final String NAME;
|
||
/** Position actuelle dans la boucle (entre 0 et loop) */
|
||
private int pos = 0;
|
||
/** Nombre de tours complétés */
|
||
private int round = 0;
|
||
/** Nombre de cases dans une boucle (doit être > 0) */
|
||
private final Map MAP;
|
||
/** Carburant restant */
|
||
private int fuel = 60;
|
||
|
||
private boolean isReversing = false;
|
||
|
||
/**
|
||
* Construit une nouvelle voiture.
|
||
*
|
||
* @param name nom de la voiture
|
||
* @param color couleur de la voiture
|
||
* @param map
|
||
*/
|
||
public Car(String name, Color color, Map map) {
|
||
this.NAME = name;
|
||
this.COLOR = color;
|
||
this.MAP = map;
|
||
}
|
||
|
||
public Car(Car other) {
|
||
this.NAME = other.NAME;
|
||
this.COLOR = other.COLOR;
|
||
this.MAP = other.MAP;
|
||
}
|
||
|
||
public static enum State {
|
||
/**
|
||
* L'état NORMAL du Vehicule avance selon un chiffre au alentour de 1 à 6 cases
|
||
* par tour. Il consomme 2 unités de carburant à chaque tour. Si l'on
|
||
* accelere, il passe à l'état BOOST. Si on Rallenti, il passe à l'état LOW.
|
||
*/
|
||
// @formatter:off
|
||
NORMAL(2, 1, 6) {
|
||
public State accelerate() { return BOOST; }
|
||
public State decelerate() { return LOW; }
|
||
},
|
||
|
||
/**
|
||
* L'état BOOST du Vehicule avance selon un chiffre au alentour de 5 à 10 cases
|
||
* par tour. Il consomme 5 unités de carburant à chaque tour. Si l'on
|
||
* accelere, il reste sur son état et indique un message sur le tableau de bord.
|
||
* Si on Rallenti, il passe à l'état LOW.
|
||
*/
|
||
BOOST(5, 5, 10) {
|
||
public State accelerate() { return this; }
|
||
public State decelerate() { return NORMAL; }
|
||
},
|
||
|
||
/**
|
||
* L'état LOW du Vehicule avance selon un chiffre au alentour de 1 à 3 cases
|
||
* par tour. Il consomme 1 unités de carburant à chaque tour. Si l'on
|
||
* accelere, il passe à l'état NORMAL. Si on Rallenti, il passe à l'état STOPPED.
|
||
*/
|
||
LOW(1, 1, 3) {
|
||
public State accelerate() { return NORMAL; }
|
||
public State decelerate() { return STOPPED; }
|
||
},
|
||
|
||
/**
|
||
* L'état STOPPED du Vehicule n'avance pas. Il consomme aucune unités de
|
||
* carburant à chaque tour. Si l'on
|
||
* accelere, il passe à l'état LOW. Si on Rallenti, il reste sur son état et
|
||
* indique un message sur le tableau de bord.
|
||
*/
|
||
STOPPED(0, 0, 0) {
|
||
public State accelerate() { return LOW; }
|
||
public State decelerate() { return this; }
|
||
@Override
|
||
public int move(int pos, int jump) { return pos; }
|
||
@Override
|
||
public int fuelConsumption(int fuel) { return fuel; }
|
||
},
|
||
/**
|
||
* L'état STOPPED du Vehicule n'avance pas. Il consomme aucune unités de
|
||
* carburant à chaque tour. Il reste immobile.
|
||
*/
|
||
DAMAGED(0, 0, 0) {
|
||
public State accelerate() { return this; }
|
||
public State decelerate() { return this; }
|
||
|
||
@Override
|
||
public int move(int pos, int jump) { return pos; }
|
||
@Override
|
||
public int fuelConsumption(int fuel) { return fuel; }
|
||
@Override
|
||
public boolean isDamaged() { return true; }
|
||
@Override
|
||
public State onDamageEnd() { return LOW; }
|
||
};
|
||
// @formatter:on
|
||
|
||
public final int FUELCOST;
|
||
public final int MAX;
|
||
public final int MIN;
|
||
|
||
private State(int fuelCost, int min, int max) {
|
||
this.FUELCOST = fuelCost;
|
||
this.MAX = max + 1;
|
||
this.MIN = min;
|
||
}
|
||
|
||
public List<Integer> getInterval() {
|
||
return List.of(MIN, MAX);
|
||
}
|
||
|
||
public int fuelConsumption(int fuel) {
|
||
return fuel - FUELCOST;
|
||
}
|
||
|
||
public int move(int pos, int jump) {
|
||
return pos + jump;
|
||
}
|
||
|
||
public boolean isDamaged() {
|
||
return false;
|
||
}
|
||
|
||
public State onDamageEnd() {
|
||
return this;
|
||
}
|
||
|
||
public abstract State accelerate();
|
||
|
||
public abstract State decelerate();
|
||
}
|
||
|
||
/**
|
||
* Référence à l'état du jeu, pour récupérer les paramètres comme la
|
||
* consommation
|
||
*/
|
||
private State state = State.NORMAL;
|
||
|
||
private int damageRound = 0;
|
||
|
||
public void setDamage() {
|
||
damageRound = 5;
|
||
state = State.DAMAGED;
|
||
}
|
||
|
||
private boolean decreaseDamage() {
|
||
if (state.isDamaged()) {
|
||
if (--damageRound <= 0) {
|
||
state = state.onDamageEnd();
|
||
}
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
public Car setState(State state) {
|
||
this.state = state;
|
||
return this;
|
||
}
|
||
|
||
/**
|
||
* @return la position actuelle dans la boucle
|
||
*/
|
||
public int getPosition() {
|
||
return pos;
|
||
}
|
||
|
||
/**
|
||
* @return le score de la voiture, calculé comme :
|
||
* (nombre de tours + progression du tour) × 100
|
||
*/
|
||
public int getScore() {
|
||
return (int) ((round + (float) pos / MAP.getPathSize()) * 100);
|
||
}
|
||
|
||
/**
|
||
* @return le nombre de tours complétés
|
||
*/
|
||
public int getRound() {
|
||
return round;
|
||
}
|
||
|
||
/**
|
||
* @return le carburant restant
|
||
*/
|
||
public int getFuel() {
|
||
return fuel;
|
||
}
|
||
|
||
/** Retourne l'état courant de la voiture. */
|
||
public State getState() {
|
||
return state;
|
||
}
|
||
|
||
/**
|
||
* Clique sur "Accelerer" : change d'état et retourne un message (si
|
||
* nécessaire).
|
||
*/
|
||
public String accelerate() {
|
||
// Si endommagée => l'énoncé dit qu'on ne peut pas bouger
|
||
if (state.isDamaged()) {
|
||
return "Voiture endommagée : impossible d'accélérer";
|
||
}
|
||
State next = state.accelerate();
|
||
|
||
// Énoncé : en BOOST, si on accélère encore => message "déjà max"
|
||
if (state == State.BOOST && next == State.BOOST) {
|
||
return "Déjà à la vitesse maximale";
|
||
}
|
||
state = next;
|
||
return "";
|
||
}
|
||
|
||
/**
|
||
* Clique sur "Rallentir" : change d'état et retourne un message (si
|
||
* nécessaire).
|
||
*/
|
||
public String decelerate() {
|
||
if (state.isDamaged()) {
|
||
return "Voiture endommagée : impossible de ralentir";
|
||
}
|
||
|
||
State next = state.decelerate();
|
||
|
||
// Énoncé : en STOPPED, si on ralentit encore => message "déjà arrêtée"
|
||
if (state == State.STOPPED && next == State.STOPPED) {
|
||
return "Déjà arrêtée";
|
||
}
|
||
|
||
state = next;
|
||
return "";
|
||
}
|
||
|
||
/**
|
||
* Fait avancer la voiture d'un certain nombre de positions.
|
||
* <p>
|
||
* Si la position atteint la fin de la boucle, le compteur de tours est
|
||
* incrémenté et
|
||
* la position revient à zéro.
|
||
* </p>
|
||
*
|
||
* @param move nombre de positions à avancer
|
||
* @return cette même instance (pour chaînage fluide)
|
||
*/
|
||
public void move() {
|
||
if (decreaseDamage()) {
|
||
System.out.println(NAME + " est en\taccident " + damageRound);
|
||
return;
|
||
}
|
||
|
||
int jump = RANDOM.nextInt(state.MIN, state.MAX);
|
||
int direction = (isReversing) ? -1 : 1;
|
||
|
||
for (int i = 0; i < jump; i++) {
|
||
pos = state.move(pos, direction);
|
||
|
||
Point point = MAP.getPath(pos);
|
||
Map.Circuit element = MAP.getElement(point.x, point.y);
|
||
|
||
if (hasAccident(element, jump)) {
|
||
System.out.println(NAME + " a un\taccident");
|
||
setDamage();
|
||
return;
|
||
}
|
||
round = pos / MAP.getPathSize();
|
||
}
|
||
|
||
isReversing = false;
|
||
}
|
||
|
||
private boolean hasAccident(Map.Circuit element, int jump) {
|
||
return element.isYRoad() && element.getValue() <= jump;
|
||
}
|
||
|
||
public void reverse() {
|
||
isReversing = !isReversing;
|
||
}
|
||
|
||
/**
|
||
* 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é
|
||
}
|
||
|
||
/**
|
||
* Exécute une "étape" de la voiture : avance d'une position aléatoire et
|
||
* consomme du carburant.
|
||
* <p>
|
||
* La progression est déterminée par un intervalle aléatoire fourni par l'état
|
||
* du jeu.
|
||
* </p>
|
||
*/
|
||
public void run() {
|
||
if (fuel > 0) {
|
||
move();
|
||
consumeFuel();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @return la position actuelle (synonyme de getPosition)
|
||
*/
|
||
public int getPos() {
|
||
return pos;
|
||
}
|
||
|
||
/**
|
||
* @return la couleur de la voiture
|
||
*/
|
||
public Color getColor() {
|
||
return COLOR;
|
||
}
|
||
|
||
/**
|
||
* @return nom de la voiture
|
||
*/
|
||
public String getName() {
|
||
return NAME;
|
||
}
|
||
}
|