initialisation

This commit is contained in:
2025-05-21 16:15:27 +02:00
commit 8d22ffe40c
154 changed files with 8296 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
package modele;
import java.util.*;
/**
* Représentation des couleurs du jeu utilisées pour les cartes wagon et les joueurs
*/
public enum CouleurWagon {
NOIR, BLANC, JAUNE, ROUGE, ORANGE, BLEU, VERT, ROSE, GRIS, LOCOMOTIVE;
@Override
public String toString() {
return switch (this) {
case NOIR -> "Noir";
case BLANC -> "Blanc";
case JAUNE -> "Jaune";
case ROUGE -> "Rouge";
case ORANGE -> "Orange";
case BLEU -> "Bleu";
case VERT -> "Vert";
case ROSE -> "Rose";
case GRIS -> "Gris"; // représente une couleur indéterminée
case LOCOMOTIVE -> "Locomotive"; // peut remplacer n'importe quelle couleur
};
}
public String toLog() {
return String.format("<img class=\"couleur\" src=\"images/symbole-%s.png\"><span class=\"couleur %s\">%s</span>", name(), name().toLowerCase(), this);
}
/**
* Renvoie la liste des couleurs "simples" c'est-à-dire sans LOCOMOTIVE ni GRIS
*/
public static ArrayList<CouleurWagon> getCouleursSimples() {
return new ArrayList<>(List.of(NOIR, BLANC, JAUNE, ROUGE, ORANGE, BLEU, VERT, ROSE));
}
/**
* Renvoie la représentation sous forme d'une chaîne de caractères d'une liste
* non ordonnée de couleurs.
*
* La chaîne est constituée du nom de chaque couleur qui apparaît dans la liste,
* suivie éventuellement d'une chaîne de la forme " x n" où n est le nombre de
* fois que la couleur apparaît dans la liste, si n > 1. Les couleurs sont
* séparées par des virgules.
*
* @param liste une liste de couleurs (considérée comme non ordonnée)
* @return une chaîne de caractères décrivant les éléments qui apparaissent dans
* la liste
*/
public static String listToString(List<CouleurWagon> liste) {
StringJoiner joiner = new StringJoiner(", ");
for (CouleurWagon c : CouleurWagon.values()) {
int count = Collections.frequency(liste, c);
if (count == 1) {
joiner.add(c.toString());
} else if (count > 1) {
joiner.add(c.toString() + " x" + count);
}
}
return joiner.toString();
}
public static String listToLog(List<CouleurWagon> liste) {
StringJoiner joiner = new StringJoiner(", ");
for (CouleurWagon c : CouleurWagon.values()) {
int count = Collections.frequency(liste, c);
if (count == 1) {
joiner.add(c.toLog());
} else if (count > 1) {
joiner.add(c.toLog() + " x" + count);
}
}
return joiner.toString();
}
}

View File

@@ -0,0 +1,105 @@
package modele;
import java.util.ArrayList;
import java.util.HashMap;
public class Destination {
/**
* Ville de départ
*/
private String ville1;
/**
* Ville d'arrivée
*/
private String ville2;
/**
* Nombre de points que vaut la destination
*/
private int valeur;
public Destination(String ville1, String ville2, int valeur) {
this.ville1 = ville1;
this.ville2 = ville2;
this.valeur = valeur;
}
@Override
public String toString() {
return getNom();
}
public String getNom() {
return String.format("%s - %s (%d)", ville1, ville2, valeur);
}
public Object asPOJO() {
HashMap<String, Object> data = new HashMap<>();
data.put("ville1", ville1);
data.put("ville2", ville2);
data.put("valeur", valeur);
return data;
}
/**
* @return une liste contenant toutes les destinations "normales" du jeu
*/
public static ArrayList<Destination> makeDestinationsEurope() {
ArrayList<Destination> destinations = new ArrayList<>();
destinations.add(new Destination("Athina", "Angora", 5));
destinations.add(new Destination("Budapest", "Sofia", 5));
destinations.add(new Destination("Frankfurt", "Kobenhavn", 5));
destinations.add(new Destination("Rostov", "Erzurum", 5));
destinations.add(new Destination("Sofia", "Smyrna", 5));
destinations.add(new Destination("Kyiv", "Petrograd", 6));
destinations.add(new Destination("Zurich", "Brindisi", 6));
destinations.add(new Destination("Zurich", "Budapest", 6));
destinations.add(new Destination("Warszawa", "Smolensk", 6));
destinations.add(new Destination("Zagrab", "Brindisi", 6));
destinations.add(new Destination("Paris", "Zagrab", 7));
destinations.add(new Destination("Brest", "Marseille", 7));
destinations.add(new Destination("London", "Berlin", 7));
destinations.add(new Destination("Edinburgh", "Paris", 7));
destinations.add(new Destination("Amsterdam", "Pamplona", 7));
destinations.add(new Destination("Roma", "Smyrna", 8));
destinations.add(new Destination("Palermo", "Constantinople", 8));
destinations.add(new Destination("Sarajevo", "Sevastopol", 8));
destinations.add(new Destination("Madrid", "Dieppe", 8));
destinations.add(new Destination("Barcelona", "Bruxelles", 8));
destinations.add(new Destination("Paris", "Wien", 8));
destinations.add(new Destination("Barcelona", "Munchen", 8));
destinations.add(new Destination("Brest", "Venezia", 8));
destinations.add(new Destination("Smolensk", "Rostov", 8));
destinations.add(new Destination("Marseille", "Essen", 8));
destinations.add(new Destination("Kyiv", "Sochi", 8));
destinations.add(new Destination("Madrid", "Zurich", 8));
destinations.add(new Destination("Berlin", "Bucuresti", 8));
destinations.add(new Destination("Bruxelles", "Danzig", 9));
destinations.add(new Destination("Berlin", "Roma", 9));
destinations.add(new Destination("Angora", "Kharkov", 10));
destinations.add(new Destination("Riga", "Bucuresti", 10));
destinations.add(new Destination("Essen", "Kyiv", 10));
destinations.add(new Destination("Venezia", "Constantinople", 10));
destinations.add(new Destination("London", "Wien", 10));
destinations.add(new Destination("Athina", "Wilno", 11));
destinations.add(new Destination("Stockholm", "Wien", 11));
destinations.add(new Destination("Berlin", "Moskva", 12));
destinations.add(new Destination("Amsterdam", "Wilno", 12));
destinations.add(new Destination("Frankfurt", "Smolensk", 13));
return destinations;
}
/**
* @return une liste contenant toutes les destinations "longues" du jeu
*/
public static ArrayList<Destination> makeDestinationsLonguesEurope() {
ArrayList<Destination> destinations = new ArrayList<>();
destinations.add(new Destination("Lisboa", "Danzig", 20));
destinations.add(new Destination("Brest", "Petrograd", 20));
destinations.add(new Destination("Palermo", "Moskva", 20));
destinations.add(new Destination("Kobenhavn", "Erzurum", 21));
destinations.add(new Destination("Edinburgh", "Athina", 21));
destinations.add(new Destination("Cadiz", "Stockholm", 21));
return destinations;
}
}

View File

@@ -0,0 +1,20 @@
package modele;
public class Ferry extends Route {
/**
* Nombre de locomotives qu'un joueur doit payer pour capturer le ferry
*/
private int nbLocomotives;
public Ferry(Ville ville1, Ville ville2, int longueur, CouleurWagon couleur, int nbLocomotives) {
super(ville1, ville2, longueur, couleur);
this.nbLocomotives = nbLocomotives;
}
@Override
public String toString() {
return String.format("[%s - %s (%d, %s, %d)]", getVille1(), getVille2(), getLongueur(), getCouleur(),
nbLocomotives);
}
}

View File

@@ -0,0 +1,309 @@
package modele;
import com.google.gson.Gson;
import vue.GameServer;
import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.stream.Collectors;
public class Jeu implements Runnable {
/**
* Liste des joueurs
*/
private List<Joueur> joueurs;
/**
* Le joueur dont c'est le tour
*/
private Joueur joueurCourant;
/**
* Liste des villes représentées sur le plateau de jeu
*/
private List<Ville> villes;
/**
* Liste des routes du plateau de jeu
*/
private List<Route> routes;
/**
* Pile de pioche (face cachée)
*/
private List<CouleurWagon> pileCartesWagon;
/**
* Cartes de la pioche face visible (normalement il y a 5 cartes face visible)
*/
private List<CouleurWagon> cartesWagonVisibles;
/**
* Pile de cartes qui ont été défaussée au cours de la partie
*/
private List<CouleurWagon> defausseCartesWagon;
/**
* Pile des cartes "Destination" (uniquement les destinations "courtes", les
* destinations "longues" sont distribuées au début de la partie et ne peuvent
* plus être piochées après)
*/
private List<Destination> pileDestinations;
/**
* File d'attente des instructions recues par le serveur
*/
private BlockingQueue<String> inputQueue;
/**
* Messages d'information du jeu
*/
private List<String> log;
public Jeu(String[] nomJoueurs) {
/*
* ATTENTION : Cette méthode est à réécrire.
*
* Le code indiqué ici est un squelette minimum pour que le jeu se lance et que
* l'interface graphique fonctionne.
* Vous devez modifier ce code pour que les différents éléments du jeu soient
* correctement initialisés.
*/
// initialisation des entrées/sorties
inputQueue = new LinkedBlockingQueue<>();
log = new ArrayList<>();
// création des cartes
pileCartesWagon = new ArrayList<>();
cartesWagonVisibles = new ArrayList<>();
defausseCartesWagon = new ArrayList<>();
pileDestinations = new ArrayList<>();
// création des joueurs
ArrayList<Joueur.Couleur> couleurs = new ArrayList<>(Arrays.asList(Joueur.Couleur.values()));
Collections.shuffle(couleurs);
joueurs = new ArrayList<>();
for (String nom : nomJoueurs) {
Joueur joueur = new Joueur(nom, this, couleurs.remove(0));
joueurs.add(joueur);
}
joueurCourant = joueurs.get(0);
// création des villes et des routes
Plateau plateau = Plateau.makePlateauEurope();
villes = plateau.getVilles();
routes = plateau.getRoutes();
}
public List<CouleurWagon> getPileCartesWagon() {
return pileCartesWagon;
}
public List<CouleurWagon> getCartesWagonVisibles() {
return cartesWagonVisibles;
}
public List<Ville> getVilles() {
return villes;
}
public List<Route> getRoutes() {
return routes;
}
public Joueur getJoueurCourant() {
return joueurCourant;
}
/**
* Exécute la partie
*/
public void run() {
/*
* ATTENTION : Cette méthode est à réécrire.
*
* Cette méthode doit :
* - faire choisir à chaque joueur les destinations initiales qu'il souhaite
* garder : on pioche 3 destinations "courtes" et 1 destination "longue", puis
* le
* joueur peut choisir des destinations à défausser ou passer s'il ne veut plus
* en défausser. Il doit en garder au moins 2.
* - exécuter la boucle principale du jeu qui fait jouer le tour de chaque
* joueur à tour de rôle jusqu'à ce qu'un des joueurs n'ait plus que 2 wagons ou
* moins
* - exécuter encore un dernier tour de jeu pour chaque joueur après
*/
/**
* Le code proposé ici n'est qu'un exemple d'utilisation des méthodes pour
* interagir avec l'utilisateur, il n'a rien à voir avec le code de la partie et
* doit donc être entièrement réécrit.
*/
// Exemple d'utilisation
while (true) {
// le joueur doit choisir une valeur parmi "1", "2", "3", "4", "6" ou "8"
// les choix possibles sont présentés sous forme de boutons cliquables
String choix = joueurCourant.choisir(
"Choisissez une taille de route.", // instruction
new ArrayList<>(), // choix (hors boutons, ici aucun)
new ArrayList<>(Arrays.asList("1", "2", "3", "4", "6", "8")), // boutons
false); // le joueur ne peut pas passer (il doit faire un choix)
// une fois la longueur choisie, on filtre les routes pour ne garder que les
// routes de la longueur choisie
int longueurRoute = Integer.parseInt(choix);
ArrayList<String> routesPossibles = new ArrayList<>();
for (Route route : routes) {
if (route.getLongueur() == longueurRoute) {
routesPossibles.add(route.getNom());
}
}
// le joueur doit maintenant choisir une route de la longueur choisie (les
// autres ne sont pas acceptées). Le joueur peut choisir de passer (aucun choix)
String choixRoute = joueurCourant.choisir(
"Choisissez une route de longueur " + longueurRoute, // instruction
routesPossibles, // choix (pas des boutons, il faut cliquer sur la carte)
new ArrayList<>(), // boutons (ici aucun bouton créé)
true); // le joueur peut passer sans faire de choix
if (choixRoute.equals("")) {
// le joueur n'a pas fait de choix (cliqué sur le bouton "passer")
log("Auncune route n'a été choisie");
} else {
// le joueur a choisi une route
log("Vous avez choisi la route " + choixRoute);
}
}
}
/**
* Ajoute une carte dans la pile de défausse.
* Dans le cas peu probable, où il y a moins de 5 cartes wagon face visibles
* (parce que la pioche
* et la défausse sont vides), alors il faut immédiatement rendre cette carte
* face visible.
*
* @param c carte à défausser
*/
public void defausserCarteWagon(CouleurWagon c) {
throw new RuntimeException("Méthode non implémentée !");
}
/**
* Pioche une carte de la pile de pioche
* Si la pile est vide, les cartes de la défausse sont replacées dans la pioche
* puis mélangées avant de piocher une carte
*
* @return la carte qui a été piochée (ou null si aucune carte disponible)
*/
public CouleurWagon piocherCarteWagon() {
throw new RuntimeException("Méthode non implémentée !");
}
/**
* Retire une carte wagon de la pile des cartes wagon visibles.
* Si une carte a été retirée, la pile de cartes wagons visibles est recomplétée
* (remise à 5, éventuellement remélangée si 3 locomotives visibles)
*/
public void retirerCarteWagonVisible(CouleurWagon c) {
throw new RuntimeException("Méthode non implémentée !");
}
/**
* Pioche et renvoie la destination du dessus de la pile de destinations.
*
* @return la destination qui a été piochée (ou `null` si aucune destination
* disponible)
*/
public Destination piocherDestination() {
throw new RuntimeException("Méthode non implémentée !");
}
public List<Joueur> getJoueurs() {
return joueurs;
}
@Override
public String toString() {
StringJoiner joiner = new StringJoiner("\n");
for (Joueur j : joueurs) {
joiner.add(j.toString());
}
return joiner.toString();
}
/**
* Ajoute un message au log du jeu
*/
public void log(String message) {
log.add(message);
}
/**
* Ajoute un message à la file d'entrées
*/
public void addInput(String message) {
inputQueue.add(message);
}
/**
* Lit une ligne de l'entrée standard
* C'est cette méthode qui doit être appelée à chaque fois qu'on veut lire
* l'entrée clavier de l'utilisateur (par exemple dans {@code Player.choisir})
*
* @return une chaîne de caractères correspondant à l'entrée suivante dans la
* file
*/
public String lireLigne() {
try {
return inputQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
return null;
}
}
/**
* Envoie l'état de la partie pour affichage aux joueurs avant de faire un choix
*
* @param instruction l'instruction qui est donnée au joueur
* @param boutons labels des choix proposés s'il y en a
* @param peutPasser indique si le joueur peut passer sans faire de choix
*/
public void prompt(String instruction, Collection<String> boutons, boolean peutPasser) {
System.out.println();
System.out.println(this);
if (boutons.isEmpty()) {
System.out.printf(">>> %s: %s <<<%n", joueurCourant.getNom(), instruction);
} else {
StringJoiner joiner = new StringJoiner(" / ");
for (String bouton : boutons) {
joiner.add(bouton);
}
System.out.printf(">>> %s: %s [%s] <<<%n", joueurCourant.getNom(), instruction, joiner);
}
Map<String, Object> data = Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("prompt", Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("instruction", instruction),
new AbstractMap.SimpleEntry<String, Object>("boutons", boutons),
new AbstractMap.SimpleEntry<String, Object>("nomJoueurCourant", getJoueurCourant().getNom()),
new AbstractMap.SimpleEntry<String, Object>("peutPasser", peutPasser))),
new AbstractMap.SimpleEntry<>("villes",
villes.stream().map(Ville::asPOJO).collect(Collectors.toList())),
new AbstractMap.SimpleEntry<>("routes",
routes.stream().map(Route::asPOJO).collect(Collectors.toList())),
new AbstractMap.SimpleEntry<String, Object>("joueurs",
joueurs.stream().map(Joueur::asPOJO).collect(Collectors.toList())),
new AbstractMap.SimpleEntry<String, Object>("piles", Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("pileCartesWagon", pileCartesWagon.size()),
new AbstractMap.SimpleEntry<String, Object>("pileDestinations", pileDestinations.size()),
new AbstractMap.SimpleEntry<String, Object>("defausseCartesWagon", defausseCartesWagon),
new AbstractMap.SimpleEntry<String, Object>("cartesWagonVisibles", cartesWagonVisibles))),
new AbstractMap.SimpleEntry<String, Object>("log", log));
GameServer.setEtatJeu(new Gson().toJson(data));
}
public List<CouleurWagon> getDefausseCartesWagon() {
return defausseCartesWagon;
}
public List<Destination> getPileDestinations() {
return null;
}
}

View File

@@ -0,0 +1,269 @@
package modele;
import java.util.*;
import java.util.stream.Collectors;
public class Joueur {
public int getNbGares() {
return 0;
}
public int getScore() {
return 0;
}
/**
* Les couleurs possibles pour les joueurs (pour l'interface graphique)
*/
public static enum Couleur {
JAUNE, ROUGE, BLEU, VERT, ROSE;
}
/**
* Jeu auquel le joueur est rattaché
*/
private Jeu jeu;
/**
* Nom du joueur
*/
private String nom;
/**
* CouleurWagon du joueur (pour représentation sur le plateau)
*/
private Couleur couleur;
/**
* Nombre de gares que le joueur peut encore poser sur le plateau
*/
private int nbGares;
/**
* Nombre de wagons que le joueur peut encore poser sur le plateau
*/
private int nbWagons;
/**
* Liste des missions à réaliser pendant la partie
*/
private List<Destination> destinations;
/**
* Liste des cartes que le joueur a en main
*/
private List<CouleurWagon> cartesWagon;
/**
* Liste temporaire de cartes wagon que le joueur est en train de jouer pour
* payer la capture d'une route ou la construction d'une gare
*/
private List<CouleurWagon> cartesWagonPosees;
/**
* Score courant du joueur (somme des valeurs des routes capturées)
*/
private int score;
public Joueur(String nom, Jeu jeu, Joueur.Couleur couleur) {
this.nom = nom;
this.jeu = jeu;
this.couleur = couleur;
nbGares = 3;
nbWagons = 45;
cartesWagon = new ArrayList<>();
cartesWagonPosees = new ArrayList<>();
destinations = new ArrayList<>();
score = 12; // chaque gare non utilisée vaut 4 points
}
public String getNom() {
return nom;
}
public Couleur getCouleur() {
return couleur;
}
public int getNbWagons() {
return nbWagons;
}
public Jeu getJeu() {
return jeu;
}
public List<CouleurWagon> getCartesWagonPosees() {
return cartesWagonPosees;
}
public List<CouleurWagon> getCartesWagon() {
return cartesWagon;
}
public List<Destination> getDestinations() {
return destinations;
}
/**
* Attend une entrée de la part du joueur (au clavier ou sur la websocket) et
* renvoie le choix du joueur.
* <p>
* Cette méthode lit les entrées du jeu ({@code Jeu.lireligne()}) jusqu'à ce
* qu'un choix valide (un élément de {@code choix} ou de {@code boutons} ou
* éventuellement la chaîne vide si l'utilisateur est autorisé à passer) soit
* reçu.
* Lorsqu'un choix valide est obtenu, il est renvoyé par la fonction.
* <p>
* Si l'ensemble des choix valides ({@code choix} + {@code boutons}) ne comporte
* qu'un seul élément et que {@code canPass} est faux, l'unique choix valide est
* automatiquement renvoyé sans lire l'entrée de l'utilisateur.
* <p>
* Si l'ensemble des choix est vide, la chaîne vide ("") est automatiquement
* renvoyée par la méthode (indépendamment de la valeur de {@code canPass}).
* <p>
* Exemple d'utilisation pour demander à un joueur de répondre à une question
* par "oui" ou "non" :
* <p>
* {@code
* List<String> choix = Arrays.asList("Oui", "Non");
* String input = choisir("Voulez vous faire ceci ?", choix, new ArrayList<>(), false);
* }
* <p>
* <p>
* Si par contre on voulait proposer les réponses à l'aide de boutons, on
* pourrait utiliser :
* <p>
* {@code
* List<String> boutons = Arrays.asList("1", "2", "3");
* String input = choisir("Choisissez un nombre.", new ArrayList<>(), boutons, false);
* }
*
* @param instruction message à afficher à l'écran pour indiquer au joueur la
* nature du choix qui est attendu
* @param choix une collection de chaînes de caractères correspondant aux
* choix valides attendus du joueur
* @param boutons une collection de chaînes de caractères correspondant aux
* choix valides attendus du joueur qui doivent être
* représentés par des boutons sur l'interface graphique.
* @param peutPasser booléen indiquant si le joueur a le droit de passer sans
* faire de choix. S'il est autorisé à passer, c'est la
* chaîne de caractères vide ("") qui signifie qu'il désire
* passer.
* @return le choix de l'utilisateur (un élément de {@code choix}, ou de
* {@code boutons} ou la chaîne vide)
*/
public String choisir(String instruction, Collection<String> choix, Collection<String> boutons,
boolean peutPasser) {
// on retire les doublons de la liste des choix
HashSet<String> choixDistincts = new HashSet<>();
choixDistincts.addAll(choix);
choixDistincts.addAll(boutons);
// Aucun choix disponible
if (choixDistincts.isEmpty()) {
return "";
} else {
// Un seul choix possible (renvoyer cet unique élément)
if (choixDistincts.size() == 1 && !peutPasser)
return choixDistincts.iterator().next();
else {
String entree;
// Lit l'entrée de l'utilisateur jusqu'à obtenir un choix valide
while (true) {
jeu.prompt(instruction, boutons, peutPasser);
entree = jeu.lireLigne();
// si une réponse valide est obtenue, elle est renvoyée
if (choixDistincts.contains(entree) || (peutPasser && entree.equals("")))
return entree;
}
}
}
}
/**
* Affiche un message dans le log du jeu (visible sur l'interface graphique)
*
* @param message le message à afficher (peut contenir des balises html pour la
* mise en forme)
*/
public void log(String message) {
jeu.log(message);
}
@Override
public String toString() {
StringJoiner joiner = new StringJoiner("\n");
joiner.add(String.format("=== %s (%d pts) ===", nom, score));
joiner.add(String.format(" Gares: %d, Wagons: %d", nbGares, nbWagons));
joiner.add(" Destinations: "
+ destinations.stream().map(Destination::toString).collect(Collectors.joining(", ")));
joiner.add(" Cartes wagon: " + CouleurWagon.listToString(cartesWagon));
return joiner.toString();
}
/**
* @return une chaîne de caractères contenant le nom du joueur, avec des balises
* HTML pour être mis en forme dans le log
*/
public String toLog() {
return String.format("<span class=\"joueur\">%s</span>", nom);
}
/**
* Renvoie une représentation du joueur sous la forme d'un objet Java simple
* (POJO)
*/
public Object asPOJO() {
HashMap<String, Object> data = new HashMap<>();
data.put("nom", nom);
data.put("couleur", couleur);
data.put("score", score);
data.put("nbGares", nbGares);
data.put("nbWagons", nbWagons);
data.put("estJoueurCourant", this == jeu.getJoueurCourant());
data.put("destinations", destinations.stream().map(Destination::asPOJO).collect(Collectors.toList()));
data.put("cartesWagon", cartesWagon.stream().sorted().map(CouleurWagon::name).collect(Collectors.toList()));
data.put("cartesWagonPosees",
cartesWagonPosees.stream().sorted().map(CouleurWagon::name).collect(Collectors.toList()));
return data;
}
/**
* Propose une liste de cartes destinations, parmi lesquelles le joueur doit en
* garder un nombre minimum n.
* <p>
* Tant que le nombre de destinations proposées est strictement supérieur à n,
* le joueur peut choisir une des destinations qu'il retire de la liste des
* choix, ou passer (en renvoyant la chaîne de caractères vide).
* <p>
* Les destinations qui ne sont pas écartées sont ajoutées à la liste des
* destinations du joueur. Les destinations écartées sont renvoyées par la
* fonction.
*
* @param destinationsPossibles liste de destinations proposées parmi lesquelles
* le joueur peut choisir d'en écarter certaines
* @param n nombre minimum de destinations que le joueur
* doit garder
* @return liste des destinations qui n'ont pas été gardées par le joueur
*/
public List<Destination> choisirDestinations(List<Destination> destinationsPossibles, int n) {
throw new RuntimeException("Méthode non implémentée !");
}
/**
* Exécute un tour de jeu du joueur.
* <p>
* Cette méthode attend que le joueur choisisse une des options suivantes :
* - le nom d'une carte wagon face visible à prendre ;
* - le nom "GRIS" pour piocher une carte wagon face cachée s'il reste des
* cartes à piocher dans la pile de pioche ou dans la pile de défausse ;
* - la chaîne "destinations" pour piocher des cartes destination ;
* - le nom d'une ville sur laquelle il peut construire une gare (ville non
* prise par un autre joueur, le joueur a encore des gares en réserve et assez
* de cartes wagon pour construire la gare) ;
* - le nom d'une route que le joueur peut capturer (pas déjà capturée, assez de
* wagons et assez de cartes wagon) ;
* - la chaîne de caractères vide pour passer son tour
* <p>
* Lorsqu'un choix valide est reçu, l'action est exécutée (il est possible que
* l'action nécessite d'autres choix de la part de l'utilisateur, comme "choisir les cartes wagon à défausser pour capturer une route" ou
* "construire une gare", "choisir les destinations à défausser", etc.)
*/
public void jouerTour() {
throw new RuntimeException("Méthode non implémentée !");
}
}

View File

@@ -0,0 +1,197 @@
package modele;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Plateau {
/**
* Liste des villes
*/
private final List<Ville> villes;
/**
* Liste des routes
*/
private final List<Route> routes;
public Plateau(List<Ville> villes, List<Route> routes) {
this.villes = villes;
this.routes = routes;
}
public List<Ville> getVilles() {
return villes;
}
public List<Route> getRoutes() {
return routes;
}
static public Plateau makePlateauEurope() {
Map<String, Ville> villes = new HashMap<>();
villes.put("amsterdam", new Ville("Amsterdam"));
villes.put("angora", new Ville("Angora"));
villes.put("athina", new Ville("Athina"));
villes.put("barcelona", new Ville("Barcelona"));
villes.put("berlin", new Ville("Berlin"));
villes.put("brest", new Ville("Brest"));
villes.put("brindisi", new Ville("Brindisi"));
villes.put("bruxelles", new Ville("Bruxelles"));
villes.put("bucuresti", new Ville("Bucuresti"));
villes.put("budapest", new Ville("Budapest"));
villes.put("cadiz", new Ville("Cadiz"));
villes.put("constantinople", new Ville("Constantinople"));
villes.put("danzig", new Ville("Danzig"));
villes.put("dieppe", new Ville("Dieppe"));
villes.put("edinburgh", new Ville("Edinburgh"));
villes.put("erzurum", new Ville("Erzurum"));
villes.put("essen", new Ville("Essen"));
villes.put("frankfurt", new Ville("Frankfurt"));
villes.put("kharkov", new Ville("Kharkov"));
villes.put("kobenhavn", new Ville("Kobenhavn"));
villes.put("kyiv", new Ville("Kyiv"));
villes.put("lisboa", new Ville("Lisboa"));
villes.put("london", new Ville("London"));
villes.put("madrid", new Ville("Madrid"));
villes.put("marseille", new Ville("Marseille"));
villes.put("moskva", new Ville("Moskva"));
villes.put("munchen", new Ville("Munchen"));
villes.put("palermo", new Ville("Palermo"));
villes.put("pamplona", new Ville("Pamplona"));
villes.put("paris", new Ville("Paris"));
villes.put("petrograd", new Ville("Petrograd"));
villes.put("riga", new Ville("Riga"));
villes.put("roma", new Ville("Roma"));
villes.put("rostov", new Ville("Rostov"));
villes.put("sarajevo", new Ville("Sarajevo"));
villes.put("sevastopol", new Ville("Sevastopol"));
villes.put("smolensk", new Ville("Smolensk"));
villes.put("smyrna", new Ville("Smyrna"));
villes.put("sochi", new Ville("Sochi"));
villes.put("sofia", new Ville("Sofia"));
villes.put("stockholm", new Ville("Stockholm"));
villes.put("venezia", new Ville("Venezia"));
villes.put("warszawa", new Ville("Warszawa"));
villes.put("wien", new Ville("Wien"));
villes.put("wilno", new Ville("Wilno"));
villes.put("zagrab", new Ville("Zagrab"));
villes.put("zurich", new Ville("Zurich"));
ArrayList<Route> routes = new ArrayList<>();
routes.add(new Route(villes.get("amsterdam"), villes.get("bruxelles"), 1, CouleurWagon.NOIR));
routes.add(new Route(villes.get("amsterdam"), villes.get("essen"), 3, CouleurWagon.JAUNE));
routes.add(new Route(villes.get("amsterdam"), villes.get("frankfurt"), 2, CouleurWagon.BLANC));
routes.add(new Ferry(villes.get("amsterdam"), villes.get("london"), 2, CouleurWagon.GRIS, 2));
routes.add(new Tunnel(villes.get("angora"), villes.get("constantinople"), 2, CouleurWagon.GRIS));
routes.add(new Route(villes.get("angora"), villes.get("erzurum"), 3, CouleurWagon.NOIR));
routes.add(new Tunnel(villes.get("angora"), villes.get("smyrna"), 3, CouleurWagon.ORANGE));
routes.add(new Ferry(villes.get("athina"), villes.get("brindisi"), 4, CouleurWagon.GRIS, 1));
routes.add(new Route(villes.get("athina"), villes.get("sarajevo"), 4, CouleurWagon.VERT));
routes.add(new Ferry(villes.get("athina"), villes.get("smyrna"), 2, CouleurWagon.GRIS, 1));
routes.add(new Route(villes.get("athina"), villes.get("sofia"), 3, CouleurWagon.ROSE));
routes.add(new Route(villes.get("barcelona"), villes.get("madrid"), 2, CouleurWagon.JAUNE));
routes.add(new Route(villes.get("barcelona"), villes.get("marseille"), 4, CouleurWagon.GRIS));
routes.add(new Tunnel(villes.get("barcelona"), villes.get("pamplona"), 2, CouleurWagon.GRIS));
routes.add(new Route(villes.get("berlin"), villes.get("danzig"), 4, CouleurWagon.GRIS));
routes.add(new Route(villes.get("berlin"), villes.get("essen"), 2, CouleurWagon.BLEU));
routes.add(new Route(villes.get("berlin"), villes.get("frankfurt"), 3, CouleurWagon.ROUGE));
routes.add(new Route(villes.get("berlin"), villes.get("frankfurt"), 3, CouleurWagon.NOIR));
routes.add(new Route(villes.get("berlin"), villes.get("warszawa"), 4, CouleurWagon.JAUNE));
routes.add(new Route(villes.get("berlin"), villes.get("warszawa"), 4, CouleurWagon.ROSE));
routes.add(new Route(villes.get("berlin"), villes.get("wien"), 3, CouleurWagon.VERT));
routes.add(new Route(villes.get("brest"), villes.get("dieppe"), 2, CouleurWagon.ORANGE));
routes.add(new Route(villes.get("brest"), villes.get("pamplona"), 4, CouleurWagon.ROSE));
routes.add(new Route(villes.get("brest"), villes.get("paris"), 3, CouleurWagon.NOIR));
routes.add(new Ferry(villes.get("brindisi"), villes.get("palermo"), 3, CouleurWagon.GRIS, 1));
routes.add(new Route(villes.get("brindisi"), villes.get("roma"), 2, CouleurWagon.BLANC));
routes.add(new Route(villes.get("bruxelles"), villes.get("dieppe"), 2, CouleurWagon.VERT));
routes.add(new Route(villes.get("bruxelles"), villes.get("frankfurt"), 2, CouleurWagon.BLEU));
routes.add(new Route(villes.get("bruxelles"), villes.get("paris"), 2, CouleurWagon.JAUNE));
routes.add(new Route(villes.get("bruxelles"), villes.get("paris"), 2, CouleurWagon.ROUGE));
routes.add(new Tunnel(villes.get("bucuresti"), villes.get("budapest"), 4, CouleurWagon.GRIS));
routes.add(new Route(villes.get("bucuresti"), villes.get("constantinople"), 3, CouleurWagon.JAUNE));
routes.add(new Route(villes.get("bucuresti"), villes.get("kyiv"), 4, CouleurWagon.GRIS));
routes.add(new Route(villes.get("bucuresti"), villes.get("sevastopol"), 4, CouleurWagon.BLANC));
routes.add(new Tunnel(villes.get("bucuresti"), villes.get("sofia"), 2, CouleurWagon.GRIS));
routes.add(new Tunnel(villes.get("budapest"), villes.get("kyiv"), 6, CouleurWagon.GRIS));
routes.add(new Route(villes.get("budapest"), villes.get("sarajevo"), 3, CouleurWagon.ROSE));
routes.add(new Route(villes.get("budapest"), villes.get("wien"), 1, CouleurWagon.ROUGE));
routes.add(new Route(villes.get("budapest"), villes.get("wien"), 1, CouleurWagon.BLANC));
routes.add(new Route(villes.get("budapest"), villes.get("zagrab"), 2, CouleurWagon.ORANGE));
routes.add(new Route(villes.get("cadiz"), villes.get("lisboa"), 2, CouleurWagon.BLEU));
routes.add(new Route(villes.get("cadiz"), villes.get("madrid"), 3, CouleurWagon.ORANGE));
routes.add(new Ferry(villes.get("constantinople"), villes.get("sevastopol"), 4, CouleurWagon.GRIS, 2));
routes.add(new Tunnel(villes.get("constantinople"), villes.get("smyrna"), 2, CouleurWagon.GRIS));
routes.add(new Route(villes.get("constantinople"), villes.get("sofia"), 3, CouleurWagon.BLEU));
routes.add(new Route(villes.get("danzig"), villes.get("riga"), 3, CouleurWagon.NOIR));
routes.add(new Route(villes.get("danzig"), villes.get("warszawa"), 2, CouleurWagon.GRIS));
routes.add(new Ferry(villes.get("dieppe"), villes.get("london"), 2, CouleurWagon.GRIS, 1));
routes.add(new Ferry(villes.get("dieppe"), villes.get("london"), 2, CouleurWagon.GRIS, 1));
routes.add(new Route(villes.get("dieppe"), villes.get("paris"), 1, CouleurWagon.ROSE));
routes.add(new Route(villes.get("edinburgh"), villes.get("london"), 4, CouleurWagon.ORANGE));
routes.add(new Route(villes.get("edinburgh"), villes.get("london"), 4, CouleurWagon.NOIR));
routes.add(new Ferry(villes.get("erzurum"), villes.get("sevastopol"), 4, CouleurWagon.GRIS, 2));
routes.add(new Tunnel(villes.get("erzurum"), villes.get("sochi"), 3, CouleurWagon.ROUGE));
routes.add(new Route(villes.get("essen"), villes.get("frankfurt"), 2, CouleurWagon.VERT));
routes.add(new Ferry(villes.get("essen"), villes.get("kobenhavn"), 3, CouleurWagon.GRIS, 1));
routes.add(new Ferry(villes.get("essen"), villes.get("kobenhavn"), 3, CouleurWagon.GRIS, 1));
routes.add(new Route(villes.get("frankfurt"), villes.get("munchen"), 2, CouleurWagon.ROSE));
routes.add(new Route(villes.get("frankfurt"), villes.get("paris"), 3, CouleurWagon.ORANGE));
routes.add(new Route(villes.get("frankfurt"), villes.get("paris"), 3, CouleurWagon.BLANC));
routes.add(new Route(villes.get("kharkov"), villes.get("kyiv"), 4, CouleurWagon.GRIS));
routes.add(new Route(villes.get("kharkov"), villes.get("moskva"), 4, CouleurWagon.GRIS));
routes.add(new Route(villes.get("kharkov"), villes.get("rostov"), 2, CouleurWagon.VERT));
routes.add(new Route(villes.get("kobenhavn"), villes.get("stockholm"), 3, CouleurWagon.JAUNE));
routes.add(new Route(villes.get("kobenhavn"), villes.get("stockholm"), 3, CouleurWagon.BLANC));
routes.add(new Route(villes.get("kyiv"), villes.get("smolensk"), 3, CouleurWagon.ROUGE));
routes.add(new Route(villes.get("kyiv"), villes.get("warszawa"), 4, CouleurWagon.GRIS));
routes.add(new Route(villes.get("kyiv"), villes.get("wilno"), 2, CouleurWagon.GRIS));
routes.add(new Route(villes.get("lisboa"), villes.get("madrid"), 3, CouleurWagon.ROSE));
routes.add(new Tunnel(villes.get("madrid"), villes.get("pamplona"), 3, CouleurWagon.BLANC));
routes.add(new Tunnel(villes.get("madrid"), villes.get("pamplona"), 3, CouleurWagon.NOIR));
routes.add(new Route(villes.get("marseille"), villes.get("pamplona"), 4, CouleurWagon.ROUGE));
routes.add(new Route(villes.get("marseille"), villes.get("paris"), 4, CouleurWagon.GRIS));
routes.add(new Tunnel(villes.get("marseille"), villes.get("roma"), 4, CouleurWagon.GRIS));
routes.add(new Tunnel(villes.get("marseille"), villes.get("zurich"), 2, CouleurWagon.ROSE));
routes.add(new Route(villes.get("moskva"), villes.get("petrograd"), 4, CouleurWagon.BLANC));
routes.add(new Route(villes.get("moskva"), villes.get("smolensk"), 2, CouleurWagon.ORANGE));
routes.add(new Tunnel(villes.get("munchen"), villes.get("venezia"), 2, CouleurWagon.BLEU));
routes.add(new Route(villes.get("munchen"), villes.get("wien"), 3, CouleurWagon.ORANGE));
routes.add(new Tunnel(villes.get("munchen"), villes.get("zurich"), 2, CouleurWagon.JAUNE));
routes.add(new Ferry(villes.get("palermo"), villes.get("roma"), 4, CouleurWagon.GRIS, 1));
routes.add(new Ferry(villes.get("palermo"), villes.get("smyrna"), 6, CouleurWagon.GRIS, 2));
routes.add(new Route(villes.get("pamplona"), villes.get("paris"), 4, CouleurWagon.BLEU));
routes.add(new Route(villes.get("pamplona"), villes.get("paris"), 4, CouleurWagon.VERT));
routes.add(new Tunnel(villes.get("paris"), villes.get("zurich"), 3, CouleurWagon.GRIS));
routes.add(new Route(villes.get("petrograd"), villes.get("riga"), 4, CouleurWagon.GRIS));
routes.add(new Tunnel(villes.get("petrograd"), villes.get("stockholm"), 8, CouleurWagon.GRIS));
routes.add(new Route(villes.get("petrograd"), villes.get("wilno"), 4, CouleurWagon.BLEU));
routes.add(new Route(villes.get("riga"), villes.get("wilno"), 4, CouleurWagon.VERT));
routes.add(new Route(villes.get("roma"), villes.get("venezia"), 2, CouleurWagon.NOIR));
routes.add(new Route(villes.get("rostov"), villes.get("sevastopol"), 4, CouleurWagon.GRIS));
routes.add(new Route(villes.get("rostov"), villes.get("sochi"), 2, CouleurWagon.GRIS));
routes.add(new Tunnel(villes.get("sarajevo"), villes.get("sofia"), 2, CouleurWagon.GRIS));
routes.add(new Route(villes.get("sarajevo"), villes.get("zagrab"), 3, CouleurWagon.ROUGE));
routes.add(new Ferry(villes.get("sevastopol"), villes.get("sochi"), 2, CouleurWagon.GRIS, 1));
routes.add(new Route(villes.get("smolensk"), villes.get("wilno"), 3, CouleurWagon.JAUNE));
routes.add(new Route(villes.get("venezia"), villes.get("zagrab"), 2, CouleurWagon.GRIS));
routes.add(new Tunnel(villes.get("venezia"), villes.get("zurich"), 2, CouleurWagon.VERT));
routes.add(new Route(villes.get("warszawa"), villes.get("wien"), 4, CouleurWagon.BLEU));
routes.add(new Route(villes.get("warszawa"), villes.get("wilno"), 3, CouleurWagon.ROUGE));
routes.add(new Route(villes.get("wien"), villes.get("zagrab"), 2, CouleurWagon.GRIS));
// Correction du nom pour les routes doubles
for (int i = 0; i < routes.size(); i++) {
Route r1 = routes.get(i);
if (i < routes.size() - 1) {
Route r2 = routes.get(i + 1);
if (r1.getNom().equals(r2.getNom())) {
r1.setNom(r1.getNom() + "(1)");
r2.setNom(r2.getNom() + "(2)");
}
}
}
return new Plateau(new ArrayList<>(villes.values()), routes);
}
}

View File

@@ -0,0 +1,93 @@
package modele;
import java.util.HashMap;
public class Route {
/**
* Première extrémité
*/
private Ville ville1;
/**
* Deuxième extrémité
*/
private Ville ville2;
/**
* Nombre de segments
*/
private int longueur;
/**
* CouleurWagon pour capturer la route (éventuellement GRIS, mais pas LOCOMOTIVE)
*/
private CouleurWagon couleur;
/**
* Joueur qui a capturé la route (`null` si la route est encore à prendre)
*/
private Joueur proprietaire;
/**
* Nom unique de la route. Ce nom est nécessaire pour résoudre l'ambiguïté entre les routes doubles
* (voir la classe Plateau pour plus de clarté)
*/
private String nom;
public Route(Ville ville1, Ville ville2, int longueur, CouleurWagon couleur) {
this.ville1 = ville1;
this.ville2 = ville2;
this.longueur = longueur;
this.couleur = couleur;
nom = ville1.getNom() + " - " + ville2.getNom();
proprietaire = null;
}
public Ville getVille1() {
return ville1;
}
public Ville getVille2() {
return ville2;
}
public int getLongueur() {
return longueur;
}
public CouleurWagon getCouleur() {
return couleur;
}
public Joueur getProprietaire() {
return proprietaire;
}
public void setProprietaire(Joueur proprietaire) {
this.proprietaire = proprietaire;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public String toLog() {
return String.format("<span class=\"route\">%s - %s</span>", ville1.getNom(), ville2.getNom());
}
@Override
public String toString() {
return String.format("[%s - %s (%d, %s)]", ville1, ville2, longueur, couleur);
}
/**
* @return un objet simple représentant les informations de la route
*/
public Object asPOJO() {
HashMap<String, Object> data = new HashMap<>();
data.put("nom", getNom());
if (proprietaire != null) {
data.put("proprietaire", proprietaire.getCouleur());
}
return data;
}
}

View File

@@ -0,0 +1,13 @@
package modele;
public class Tunnel extends Route {
public Tunnel(Ville ville1, Ville ville2, int longueur, CouleurWagon couleur) {
super(ville1, ville2, longueur, couleur);
}
@Override
public String toString() {
return "[" + super.toString() + "]";
}
}

View File

@@ -0,0 +1,48 @@
package modele;
import java.util.HashMap;
public class Ville {
/**
* Nom complet de la ville
*/
private String nom;
/**
* Joueur qui a construit une gare sur la ville (ou `null` si pas de gare)
*/
private Joueur proprietaire;
public Ville(String nom) {
this.nom = nom;
}
public String getNom() {
return nom;
}
public Joueur getProprietaire() {
return proprietaire;
}
public void setProprietaire(Joueur proprietaire) {
this.proprietaire = proprietaire;
}
@Override
public String toString() {
return nom;
}
public String toLog() {
return String.format("<span class=\"ville\">%s</span>", nom);
}
public Object asPOJO() {
HashMap<String, Object> data = new HashMap<>();
data.put("nom", nom);
if (proprietaire != null) {
data.put("proprietaire", proprietaire.getCouleur());
}
return data;
}
}

View File

@@ -0,0 +1,98 @@
package vue;
import modele.Jeu;
import org.glassfish.tyrus.server.Server;
import javax.websocket.DeploymentException;
import javax.websocket.Session;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
public class GameServer {
/**
* Liste des clients connectés au serveur
*/
private static ArrayList<Session> clients = new ArrayList<>();
/**
* Description de l'état du jeu, envoyé aux clients pour la mise à jour de l'interface graphique
*/
private static String etatJeu = "";
/**
* Instance de jeu exécutée par le serveur
*/
private static Jeu jeu;
public static void main(String[] args) {
// Lancement de la partie
jeu = new Jeu(new String[]{"Guybrush", "Largo", "LeChuck", "Elaine"});
// Prépare le serveur websocket
Server server = new Server("localhost", 3232, "/", WebSocketClient.class);
try (Scanner scanner = new Scanner(System.in)) {
server.start(); // lance le serveur
new Thread(jeu).start(); // démarre le jeu (exécute la méthode Jeu.run() dans un nouveau thread)
while (true) {
jeu.addInput(scanner.nextLine());
}
} catch (DeploymentException e) {
throw new RuntimeException(e);
} finally {
server.stop();
}
}
/**
* Ajoute une nouvelle instruction à la file d'instructions
* (cette méthode est appelée lorsqu'un message est reçue sur la websocket)
*
* @param message l'instruction à ajouter
*/
public static void addInput(String message) {
jeu.addInput(message);
}
/**
* Met à jour l'état de la partie, et envoie le nouvel état à tous les clients connectés
*
* @param etatJeu l'état de la partie
*/
public static void setEtatJeu(String etatJeu) {
GameServer.etatJeu = etatJeu;
// Envoie l'état de la partie à tous les clients
try {
for (Session session : clients) {
session.getBasicRemote().sendText(etatJeu);
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Ajoute un nouveau client à la liste, et lui transmet l'état actuel de la partie
* (cette méthode est appelée lorsqu'une nouvelle connexion est établie)
*
* @param session la session du nouveau client
*/
public static void addClient(Session session) {
GameServer.clients.add(session);
try {
session.getBasicRemote().sendText(etatJeu);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Retire un client de la liste
* (cette méthode est appelée lorsqu'une connexion est fermée)
*
* @param session la session du client à retirer
*/
public static void removeClient(Session session) {
GameServer.clients.remove(session);
}
}

View File

@@ -0,0 +1,28 @@
package vue;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint(value = "/")
public class WebSocketClient {
@OnOpen
public void onOpen(Session session) {
GameServer.addClient(session);
}
@OnMessage
public void onMessage(String message, Session session) {
GameServer.addInput(message);
}
@OnClose
public void onClose(Session session) {
GameServer.removeClient(session);
}
@OnError
public void onError(Throwable exception, Session session) {
exception.printStackTrace();
System.err.println("Error for client: " + session.getId());
}
}

View File

@@ -0,0 +1,38 @@
package modele;
import modele.Jeu;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class IOJeu extends Jeu {
/**
* Liste contenant les instructions <20> lire (qui remplacent les entr<74>es au clavier)
*/
private List<String> instructions;
/**
* Constructeur, qui reprend exactement le constructeur de Game
*/
public IOJeu(String[] nomJoueurs) {
super(nomJoueurs);
this.instructions = new ArrayList<>();
}
/**
* Lit et renvoie une instruction dans la liste
*/
public String lireLigne() {
return instructions.remove(0);
}
/**
* Fixe la liste d'instructions du jeu.
*
* @param args liste de cha<68>nes de caract<63>res. Chaque <20>l<EFBFBD>ment est une instruction (sans '\n' <20> la fin)
*/
public void setInput(String... args) {
instructions.clear();
Collections.addAll(instructions, args);
}
}

View File

@@ -0,0 +1,95 @@
package modele;
import modele.CouleurWagon;
import modele.Destination;
import modele.Joueur;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class JeuProfTest {
private IOJeu jeu;
@BeforeEach
public void setUp() {
jeu = new IOJeu(new String[] { "Guybrush", "Largo", "LeChuck", "Elaine" });
}
@Test
void testCartesWagon() {
// regrouper toutes les cartes wagon du jeu
List<CouleurWagon> cartes = new ArrayList<>();
cartes.addAll(jeu.getPileCartesWagon());
cartes.addAll(jeu.getCartesWagonVisibles());
cartes.addAll(jeu.getDefausseCartesWagon());
for (Joueur j : jeu.getJoueurs()) {
cartes.addAll(j.getCartesWagon());
}
// compter le nombre de chaque couleur
HashMap<CouleurWagon, Integer> compteur = new HashMap<>();
for (CouleurWagon c : cartes) {
if (compteur.containsKey(c)) {
compteur.put(c, compteur.get(c) + 1);
} else {
compteur.put(c, 1);
}
}
// varifier le nombre d'exemplaires de chaque couleur
assertEquals(110, cartes.size());
assertEquals(12, compteur.get(CouleurWagon.NOIR));
assertEquals(12, compteur.get(CouleurWagon.BLANC));
assertEquals(12, compteur.get(CouleurWagon.JAUNE));
assertEquals(12, compteur.get(CouleurWagon.ROUGE));
assertEquals(12, compteur.get(CouleurWagon.ORANGE));
assertEquals(12, compteur.get(CouleurWagon.BLEU));
assertEquals(12, compteur.get(CouleurWagon.VERT));
assertEquals(12, compteur.get(CouleurWagon.ROSE));
assertEquals(14, compteur.get(CouleurWagon.LOCOMOTIVE));
}
@Test
void testInitialisationCartesVisibles() {
// v<>rifie que les cartes wagon face visible sont bien distribu<62>es dans le
// constructeur du jeu
assertEquals(5, jeu.getCartesWagonVisibles().size());
}
@Test
void testDestinationsInitialesTousLesJoueursPassent() {
jeu.setInput("", "", "", "");
try {
jeu.run();
} catch (IndexOutOfBoundsException e) {
// on v<>rifie que chaque joueur a 3 destinations normales et 1 destination
// longue
List<String> nomsDestinations = new ArrayList<>();
for (Destination d : Destination.makeDestinationsEurope()) {
nomsDestinations.add(d.getNom());
}
List<String> nomsDestinationsLongues = new ArrayList<>();
for (Destination d : Destination.makeDestinationsLonguesEurope()) {
nomsDestinationsLongues.add(d.getNom());
}
for (Joueur j : jeu.getJoueurs()) {
int nbDestinations = 0;
int nbDestinationsLongues = 0;
for (Destination d : j.getDestinations()) {
if (nomsDestinations.contains(d.getNom())) {
nbDestinations += 1;
} else if (nomsDestinationsLongues.contains(d.getNom())) {
nbDestinationsLongues += 1;
}
}
assertEquals(3, nbDestinations);
assertEquals(1, nbDestinationsLongues);
}
}
}
}

View File

@@ -0,0 +1,438 @@
package modele;
import modele.CouleurWagon;
import modele.Destination;
import modele.Ville;
import modele.Route;
import modele.Joueur;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class JoueurProfTest {
private IOJeu jeu;
private Joueur joueur1;
private Joueur joueur2;
private Joueur joueur3;
private Joueur joueur4;
/**
* Renvoie la route du jeu dont le nom est pass<73> en argument
*
* @param nom le nom de la route
* @return la route du jeu dont le nom est pass<73> en argument (ou null si aucune
* route ne correspond)
*/
public Route getRouteParNom(String nom) {
for (Route route : jeu.getRoutes()) {
if (route.getNom().equals(nom)) {
return route;
}
}
return null;
}
/**
* Renvoie la ville du jeu dont le nom est pass<73> en argument
*
* @param nom le nom de la ville
* @return la ville du jeu dont le nom est pass<73> en argument (ou null si aucune
* ville ne correspond)
*/
public Ville getVilleParNom(String nom) {
for (Ville ville : jeu.getVilles()) {
if (ville.getNom().equals(nom)) {
return ville;
}
}
return null;
}
@BeforeEach
void init() {
jeu = new IOJeu(new String[] { "Guybrush", "Largo", "LeChuck", "Elaine" });
List<Joueur> joueurs = jeu.getJoueurs();
joueur1 = joueurs.get(0);
joueur2 = joueurs.get(1);
joueur3 = joueurs.get(2);
joueur4 = joueurs.get(3);
}
/**
* Place 5 cartes ROUGE dans les cartes visibles, vide la pioche, la d<>fausse et
* les mains des joueurs
*/
void clear() {
List<CouleurWagon> cartesVisibles = jeu.getCartesWagonVisibles();
cartesVisibles.clear();
cartesVisibles.add(CouleurWagon.ROUGE);
cartesVisibles.add(CouleurWagon.ROUGE);
cartesVisibles.add(CouleurWagon.ROUGE);
cartesVisibles.add(CouleurWagon.ROUGE);
cartesVisibles.add(CouleurWagon.ROUGE);
jeu.getPileCartesWagon().clear();
jeu.getDefausseCartesWagon().clear();
joueur1.getCartesWagon().clear();
joueur2.getCartesWagon().clear();
joueur3.getCartesWagon().clear();
joueur4.getCartesWagon().clear();
}
@Test
void testInitialisation() {
for (Joueur joueur : jeu.getJoueurs()) {
assertEquals(3, joueur.getNbGares());
assertEquals(4, joueur.getCartesWagon().size());
assertEquals(45, joueur.getNbWagons());
}
}
@Test
void testChoisirDestinations() {
clear();
jeu.setInput("Athina - Angora (5)", "Frankfurt - Kobenhavn (5)");
ArrayList<Destination> destinationsPossibles = new ArrayList<>();
Destination d1 = new Destination("Athina", "Angora", 5);
Destination d2 = new Destination("Budapest", "Sofia", 5);
Destination d3 = new Destination("Frankfurt", "Kobenhavn", 5);
Destination d4 = new Destination("Rostov", "Erzurum", 5);
destinationsPossibles.add(d1);
destinationsPossibles.add(d2);
destinationsPossibles.add(d3);
destinationsPossibles.add(d4);
List<Destination> destinationsDefaussees = joueur1.choisirDestinations(destinationsPossibles, 2);
assertEquals(2, joueur1.getDestinations().size());
assertEquals(2, destinationsDefaussees.size());
assertTrue(destinationsDefaussees.contains(d1));
assertTrue(destinationsDefaussees.contains(d3));
assertTrue(joueur1.getDestinations().contains(d2));
assertTrue(joueur1.getDestinations().contains(d4));
}
@Test
void testJouerTourPrendreCartesWagon() {
clear();
List<CouleurWagon> cartesWagonVisibles = jeu.getCartesWagonVisibles();
// On met VERT x3, BLEU, LOCOMOTIVE (haut de pile) dans la pile de cartes wagon
List<CouleurWagon> pileCartesWagon = jeu.getPileCartesWagon();
pileCartesWagon.add(0, CouleurWagon.VERT);
pileCartesWagon.add(0, CouleurWagon.VERT);
pileCartesWagon.add(0, CouleurWagon.VERT);
pileCartesWagon.add(0, CouleurWagon.BLEU);
pileCartesWagon.add(0, CouleurWagon.LOCOMOTIVE);
jeu.setInput(
"JAUNE", // non valide (il n'y a que du ROUGE dans les cartes visibles)
"GRIS", // ok, pioche une LOCOMOTIVE sur le haut de la pile
"ROUGE"); // ok, prend dans les cartes visibles (remplac<61>e par BLEU)
joueur1.jouerTour();
// le joueur devrait piocher la LOCOMOTIVE, prendre une carte ROUGE
// puis le jeu devrait remettre une carte visible BLEU
assertTrue(TestUtils.contientExactement(
joueur1.getCartesWagon(),
CouleurWagon.ROUGE,
CouleurWagon.LOCOMOTIVE));
assertTrue(TestUtils.contientExactement(
cartesWagonVisibles,
CouleurWagon.BLEU,
CouleurWagon.ROUGE,
CouleurWagon.ROUGE,
CouleurWagon.ROUGE,
CouleurWagon.ROUGE));
assertTrue(TestUtils.contientExactement(
jeu.getPileCartesWagon(),
CouleurWagon.VERT,
CouleurWagon.VERT,
CouleurWagon.VERT));
}
@Test
void testJouerTourPiocherDestinations() {
clear();
Destination d1 = new Destination("Brest", "Marseille", 7);
Destination d2 = new Destination("London", "Berlin", 7);
Destination d3 = new Destination("Edinburgh", "Paris", 7);
Destination d4 = new Destination("Amsterdam", "Pamplona", 7);
Destination d5 = new Destination("Roma", "Smyrna", 8);
// le joueur choisir de piocher des destinations, pioche les destinations d1,
// d2, d3, choisit
// de d<>fausser d3 et passe (il garde donc d1 et d2)
jeu.setInput("destinations", d3.getNom(), "");
List<Destination> pileDestinations = jeu.getPileDestinations();
pileDestinations.clear();
pileDestinations.add(d1); // d<>but de la liste : haut de la pile
pileDestinations.add(d2);
pileDestinations.add(d3);
pileDestinations.add(d4);
pileDestinations.add(d5); // fin de la liste : fond de la pile
joueur1.jouerTour();
assertEquals(d4, pileDestinations.get(0));
assertEquals(d5, pileDestinations.get(1));
assertEquals(d3, pileDestinations.get(2)); // d3 est remise en fond de pile
assertEquals(2, joueur1.getDestinations().size());
assertTrue(joueur1.getDestinations().contains(d1));
assertTrue(joueur1.getDestinations().contains(d2));
}
@Test
void testJouerTourCapturerRoute() {
clear();
List<CouleurWagon> cartesWagon = joueur2.getCartesWagon();
cartesWagon.add(CouleurWagon.BLEU);
cartesWagon.add(CouleurWagon.BLEU);
cartesWagon.add(CouleurWagon.ROUGE);
cartesWagon.add(CouleurWagon.ROUGE);
cartesWagon.add(CouleurWagon.LOCOMOTIVE);
jeu.setInput(
"Brest - Pamplona", // co<63>te 4 ROSE (ne peut pas capturer)
"Bruxelles - Frankfurt", // co<63>te 2 BLEU
"BLEU", // ok
"ROUGE", // ne convient pas pour une route de 2 BLEU
"LOCOMOTIVE" // ok
);
joueur2.jouerTour();
assertEquals(null, getRouteParNom("Brest - Pamplona").getProprietaire());
assertEquals(joueur2, getRouteParNom("Bruxelles - Frankfurt").getProprietaire());
assertTrue(TestUtils.contientExactement(
joueur2.getCartesWagon(),
CouleurWagon.BLEU, CouleurWagon.ROUGE, CouleurWagon.ROUGE));
assertTrue(TestUtils.contientExactement(
jeu.getDefausseCartesWagon(),
CouleurWagon.BLEU,
CouleurWagon.LOCOMOTIVE));
assertEquals(14, joueur2.getScore());
}
@Test
void testJouerTourCapturerRoutePlusieursCouleursPossibles() {
clear();
List<CouleurWagon> cartesWagon = joueur2.getCartesWagon();
cartesWagon.add(CouleurWagon.VERT);
cartesWagon.add(CouleurWagon.BLEU);
cartesWagon.add(CouleurWagon.BLEU);
cartesWagon.add(CouleurWagon.BLEU);
cartesWagon.add(CouleurWagon.ROUGE);
cartesWagon.add(CouleurWagon.ROUGE);
cartesWagon.add(CouleurWagon.ROUGE);
cartesWagon.add(CouleurWagon.LOCOMOTIVE);
cartesWagon.add(CouleurWagon.LOCOMOTIVE);
jeu.setInput(
"Marseille - Paris", // co<63>te 4 GRIS
"VERT", // ne convient pas (impossible de payer en VERT)
"LOCOMOTIVE", // ok
"BLEU", // ok (paye tout le reste en BLEU ou LOCOMOTIVE)
"ROUGE", // ne convient pas car d<>j<EFBFBD> pay<61> BLEU
"BLEU", // ok
"LOCOMOTIVE" // ok
);
joueur2.jouerTour();
assertEquals(joueur2, getRouteParNom("Marseille - Paris").getProprietaire());
assertTrue(TestUtils.contientExactement(
joueur2.getCartesWagon(),
CouleurWagon.VERT,
CouleurWagon.BLEU,
CouleurWagon.ROUGE, CouleurWagon.ROUGE, CouleurWagon.ROUGE));
assertTrue(TestUtils.contientExactement(
jeu.getDefausseCartesWagon(),
CouleurWagon.BLEU,
CouleurWagon.BLEU,
CouleurWagon.LOCOMOTIVE,
CouleurWagon.LOCOMOTIVE));
assertEquals(19, joueur2.getScore());
}
@Test
void testJouerTourCapturerTunnelOK() {
clear();
List<CouleurWagon> cartesWagon = joueur2.getCartesWagon();
cartesWagon.add(CouleurWagon.ROSE);
cartesWagon.add(CouleurWagon.ROSE);
cartesWagon.add(CouleurWagon.ROUGE);
cartesWagon.add(CouleurWagon.ROUGE);
cartesWagon.add(CouleurWagon.LOCOMOTIVE);
// cartes qui seront pioch<63>es apr<70>s avoir pay<61> le prix initial du tunnel
jeu.getPileCartesWagon().add(0, CouleurWagon.BLEU);
jeu.getPileCartesWagon().add(0, CouleurWagon.ROSE);
jeu.getPileCartesWagon().add(0, CouleurWagon.JAUNE);
jeu.setInput(
"Marseille - Zurich", // co<63>te 2 ROSE (tunnel)
"ROSE", // ok
"LOCOMOTIVE", // ok
"ROSE" // co<63>t suppl<70>mentaire du tunnel
);
joueur2.jouerTour();
assertEquals(joueur2, getRouteParNom("Marseille - Zurich").getProprietaire());
assertTrue(TestUtils.contientExactement(
joueur2.getCartesWagon(),
CouleurWagon.ROUGE, CouleurWagon.ROUGE));
assertTrue(TestUtils.contientExactement(
jeu.getDefausseCartesWagon(),
CouleurWagon.ROSE,
CouleurWagon.ROSE,
CouleurWagon.LOCOMOTIVE,
CouleurWagon.BLEU,
CouleurWagon.ROSE,
CouleurWagon.JAUNE));
assertEquals(14, joueur2.getScore());
}
@Test
void testJouerTourCapturerTunnelImpossible() {
clear();
List<CouleurWagon> cartesWagon = joueur2.getCartesWagon();
cartesWagon.add(CouleurWagon.ROSE);
cartesWagon.add(CouleurWagon.ROUGE);
cartesWagon.add(CouleurWagon.ROUGE);
cartesWagon.add(CouleurWagon.LOCOMOTIVE);
// cartes qui seront pioch<63>es apr<70>s avoir pay<61> le prix initial du tunnel
jeu.getPileCartesWagon().add(0, CouleurWagon.ROSE);
jeu.getPileCartesWagon().add(0, CouleurWagon.BLEU);
jeu.getPileCartesWagon().add(0, CouleurWagon.JAUNE);
jeu.setInput(
"Marseille - Zurich", // co<63>te 2 ROSE (tunnel)
"ROSE", // ok
"LOCOMOTIVE" // ok, mais le joueur ne peut pas payer le co<63>t suppl<70>mentaire
);
joueur2.jouerTour();
assertEquals(null, getRouteParNom("Marseille - Zurich").getProprietaire());
assertTrue(TestUtils.contientExactement(
joueur2.getCartesWagon(),
CouleurWagon.ROSE, CouleurWagon.ROUGE, CouleurWagon.ROUGE, CouleurWagon.LOCOMOTIVE));
assertTrue(TestUtils.contientExactement(
jeu.getDefausseCartesWagon(),
CouleurWagon.ROSE,
CouleurWagon.BLEU,
CouleurWagon.JAUNE));
assertEquals(12, joueur2.getScore());
}
@Test
void testJouerTourCapturerTunnelAbandonne() {
clear();
List<CouleurWagon> cartesWagon = joueur2.getCartesWagon();
cartesWagon.add(CouleurWagon.ROSE);
cartesWagon.add(CouleurWagon.ROSE);
cartesWagon.add(CouleurWagon.ROUGE);
cartesWagon.add(CouleurWagon.ROUGE);
cartesWagon.add(CouleurWagon.LOCOMOTIVE);
// cartes qui seront pioch<63>es apr<70>s avoir pay<61> le prix initial du tunnel
jeu.getPileCartesWagon().add(0, CouleurWagon.BLEU);
jeu.getPileCartesWagon().add(0, CouleurWagon.JAUNE);
jeu.getPileCartesWagon().add(0, CouleurWagon.ROSE);
jeu.setInput(
"Marseille - Zurich", // co<63>te 2 ROSE (tunnel)
"ROSE", // ok
"LOCOMOTIVE", // ok
"" // le joueur pourrait payer mais choisit d'abandonner la capture
);
joueur2.jouerTour();
assertEquals(null, getRouteParNom("Marseille - Zurich").getProprietaire());
assertTrue(TestUtils.contientExactement(
joueur2.getCartesWagon(),
CouleurWagon.ROSE, CouleurWagon.ROSE, CouleurWagon.ROUGE, CouleurWagon.ROUGE,
CouleurWagon.LOCOMOTIVE));
assertTrue(TestUtils.contientExactement(
jeu.getDefausseCartesWagon(),
CouleurWagon.ROSE,
CouleurWagon.BLEU,
CouleurWagon.JAUNE));
assertEquals(12, joueur2.getScore());
}
@Test
void testJouerTourCapturerFerry() {
clear();
List<CouleurWagon> cartesWagon = joueur3.getCartesWagon();
cartesWagon.add(CouleurWagon.ROSE);
cartesWagon.add(CouleurWagon.JAUNE);
cartesWagon.add(CouleurWagon.JAUNE);
cartesWagon.add(CouleurWagon.JAUNE);
cartesWagon.add(CouleurWagon.LOCOMOTIVE);
// Remarque:
// Il est possible de faire en sorte que la locomotive impos<6F>e par le ferry soit
// imm<6D>diatement pay<61>e par le joueur sans demander d'input (l'utilisateur doit
// alors choisir les cartes restantes pour payer) ou bien de demander <20>
// l'utilisateur de choisir toutes les cartes pour payer (y compris la
// locomotive impos<6F>e). Le test devrait fonctionner dans les deux cas.
jeu.setInput(
"Constantinople - Sevastopol", // (ferry) co<63>te 4 GRIS dont 2 LOCOMOTIVE (ne peut pas acheter)
"Palermo - Roma", // (ferry) co<63>te 4 GRIS dont 1 LOCOMOTIVE (peut acheter)
"ROSE", // non valide (ne peut pas couvrir le co<63>t)
"JAUNE", // OK
"JAUNE", // OK
"JAUNE", // OK
"LOCOMOTIVE" // OK
);
joueur3.jouerTour();
assertEquals(joueur3, getRouteParNom("Palermo - Roma").getProprietaire());
assertTrue(TestUtils.contientExactement(
joueur3.getCartesWagon(),
CouleurWagon.ROSE));
assertTrue(TestUtils.contientExactement(
jeu.getDefausseCartesWagon(),
CouleurWagon.JAUNE, CouleurWagon.JAUNE, CouleurWagon.JAUNE,
CouleurWagon.LOCOMOTIVE));
assertEquals(null, getRouteParNom("Constantinople - Sevastopol").getProprietaire());
assertEquals(19, joueur3.getScore());
}
@Test
void testJouerTourConstruireUneGare() {
clear();
List<CouleurWagon> cartesWagon = joueur3.getCartesWagon();
cartesWagon.add(CouleurWagon.VERT);
cartesWagon.add(CouleurWagon.BLEU);
cartesWagon.add(CouleurWagon.BLEU);
cartesWagon.add(CouleurWagon.ROUGE);
cartesWagon.add(CouleurWagon.ROUGE);
jeu.setInput("Paris", "ROUGE");
joueur3.jouerTour();
assertEquals(joueur3, getVilleParNom("Paris").getProprietaire());
assertTrue(TestUtils.contientExactement(
joueur3.getCartesWagon(),
CouleurWagon.VERT, CouleurWagon.BLEU, CouleurWagon.BLEU, CouleurWagon.ROUGE));
assertTrue(TestUtils.contientExactement(
jeu.getDefausseCartesWagon(),
CouleurWagon.ROUGE));
assertEquals(2, joueur3.getNbGares());
}
}

View File

@@ -0,0 +1,96 @@
package modele;
import modele.CouleurWagon;
import modele.Destination;
import modele.Joueur;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class JoueurTest {
private IOJeu jeu;
private Joueur joueur1;
private Joueur joueur2;
private Joueur joueur3;
private Joueur joueur4;
@BeforeEach
void init() {
jeu = new IOJeu(new String[] { "Guybrush", "Largo", "LeChuck", "Elaine" });
List<Joueur> joueurs = jeu.getJoueurs();
joueur1 = joueurs.get(0);
joueur2 = joueurs.get(1);
joueur3 = joueurs.get(2);
joueur4 = joueurs.get(3);
joueur1.getCartesWagon().clear();
joueur2.getCartesWagon().clear();
joueur3.getCartesWagon().clear();
joueur4.getCartesWagon().clear();
}
@Test
void testChoisirDestinations() {
jeu.setInput("Athina - Angora (5)", "Frankfurt - Kobenhavn (5)");
ArrayList<Destination> destinationsPossibles = new ArrayList<>();
Destination d1 = new Destination("Athina", "Angora", 5);
Destination d2 = new Destination("Budapest", "Sofia", 5);
Destination d3 = new Destination("Frankfurt", "Kobenhavn", 5);
Destination d4 = new Destination("Rostov", "Erzurum", 5);
destinationsPossibles.add(d1);
destinationsPossibles.add(d2);
destinationsPossibles.add(d3);
destinationsPossibles.add(d4);
List<Destination> destinationsDefaussees = joueur1.choisirDestinations(destinationsPossibles, 2);
assertEquals(2, joueur1.getDestinations().size());
assertEquals(2, destinationsDefaussees.size());
assertTrue(destinationsDefaussees.contains(d1));
assertTrue(destinationsDefaussees.contains(d3));
assertTrue(joueur1.getDestinations().contains(d2));
assertTrue(joueur1.getDestinations().contains(d4));
}
@Test
void testJouerTourPrendreCartesWagon() {
jeu.setInput("GRIS", "ROUGE");
// On met 5 cartes ROUGE dans les cartes wagon visibles
List<CouleurWagon> cartesWagonVisibles = jeu.getCartesWagonVisibles();
cartesWagonVisibles.clear();
cartesWagonVisibles.add(CouleurWagon.ROUGE);
cartesWagonVisibles.add(CouleurWagon.ROUGE);
cartesWagonVisibles.add(CouleurWagon.ROUGE);
cartesWagonVisibles.add(CouleurWagon.ROUGE);
cartesWagonVisibles.add(CouleurWagon.ROUGE);
// On met VERT, BLEU, LOCOMOTIVE (haut de pile) dans la pile de cartes wagon
List<CouleurWagon> pileCartesWagon = jeu.getPileCartesWagon();
pileCartesWagon.add(0, CouleurWagon.BLEU);
pileCartesWagon.add(0, CouleurWagon.LOCOMOTIVE);
int nbCartesWagon = pileCartesWagon.size();
joueur1.jouerTour();
// le joueur devrait piocher la LOCOMOTIVE, prendre une carte ROUGE
// puis le jeu devrait remettre une carte visible BLEU
assertTrue(TestUtils.contientExactement(
joueur1.getCartesWagon(),
CouleurWagon.ROUGE,
CouleurWagon.LOCOMOTIVE));
assertTrue(TestUtils.contientExactement(
cartesWagonVisibles,
CouleurWagon.BLEU,
CouleurWagon.ROUGE,
CouleurWagon.ROUGE,
CouleurWagon.ROUGE,
CouleurWagon.ROUGE));
assertEquals(nbCartesWagon - 2, pileCartesWagon.size());
}
}

View File

@@ -0,0 +1,76 @@
package modele;
import modele.CouleurWagon;
import modele.Joueur;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class TestUtils {
/**
* Renvoie un attribut d'un objet <20> partir de son nom.
* La m<>thode cherche s'il existe un champ d<>clar<61> dans la classe de l'objet et
* si ce n'est pas le cas remonte dans la hi<68>rarchie des classes jusqu'<27> trouver
* un champ avec le nom voulu ou renvoie null.
*
* @param obj objet dont on cherche le champ
* @param name nom du champ
* @return le champ de l'objet, avec un type statique Object
*/
public static Object getAttribute(Object obj, String name) {
Class c = obj.getClass();
while (c != null) {
try {
Field field = c.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException e) {
c = c.getSuperclass();
continue;
} catch (IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
return null;
}
/**
* Met les cartes wagon pass<73>es en argument dans la main d'un joueur (la main
* est vid<69>e avant, pour contenir exactement les cartes indiqu<71>es)
*
* @param joueur le joueur dont on fixe les cartes en main
*/
public static void setCartesWagon(Joueur joueur, CouleurWagon... cartesWagon) {
while (!joueur.getCartesWagon().isEmpty()) {
joueur.getCartesWagon().remove(0);
}
Collections.addAll(joueur.getCartesWagon(), cartesWagon);
}
/**
* Teste si la liste de CouleurWagon pass<73>e en premier argument contient
* exactement les couleurs indiqu<71>es, ind<6E>pendamment de leur ordre
*
* @param liste la liste de CouleurWagon <20> tester
* @param couleurs les couleurs que la liste devrait contenir (avec leur
* multiplicit<69>)
* @return true si la liste contient exactement les couleurs indiqu<71>es, avec
* leur multiplicit<69>, false sinon
*/
public static boolean contientExactement(List<CouleurWagon> liste, CouleurWagon... couleurs) {
if (liste.size() != couleurs.length) {
return false;
}
Arrays.sort(couleurs);
Collections.sort(liste);
for (int i = 0; i < couleurs.length; i++) {
if (couleurs[i] != liste.get(i)) {
return false;
}
}
return true;
}
}