init
This commit is contained in:
commit
30c2482ec2
7
.vscode/settings.json
vendored
Normal file
7
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"java.project.referencedLibraries": [
|
||||||
|
"lib/**/*.jar",
|
||||||
|
"/usr/share/java/junit.jar",
|
||||||
|
"/usr/share/java/hamcrest-core.jar"
|
||||||
|
]
|
||||||
|
}
|
65
LISEZ-MOI.txt
Normal file
65
LISEZ-MOI.txt
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
Nom : Fainsin
|
||||||
|
Prénom : Laurent
|
||||||
|
Groupe TP : I
|
||||||
|
|
||||||
|
Les « ... » indiquent les endroits à compléter.
|
||||||
|
|
||||||
|
=====[ Temps passé ]============================================================
|
||||||
|
|
||||||
|
Ces informations de temps sont demandées à titre indicatif et ne sont pas
|
||||||
|
prises en compte dans la notation du projet.
|
||||||
|
|
||||||
|
Toutes les durées sont à saisir en heures. Par exemple, si vous avez passé
|
||||||
|
1h45, il faudra indiquer 1.75. Si vous avez passé 2h30, il faudra indiquer
|
||||||
|
2.5.
|
||||||
|
|
||||||
|
* Temps passé sur la V1 (en h) : 7.5
|
||||||
|
* Temps passé sur la V2 (en h) : 0.5
|
||||||
|
|
||||||
|
|
||||||
|
=====[ Questions ]==============================================================
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
Pourquoi l'exception OperationInterditeException ne peut pas être définie
|
||||||
|
comme vérifiée par le compilateur ?
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PartieSafe.retirer doit lever l'exception OperationInterditeException, mais on ne
|
||||||
|
peut pas (à cause de l'override) lui faire lever plus d'exceptions que
|
||||||
|
CoupInvalideException. Il faut alors que OperationInterditeException ne soit pas
|
||||||
|
vérifié à la compilation, on construit alors OperationInterditeException comme
|
||||||
|
héritant de RuntimeException.
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
Expliquer ce qu'il faut faire pour ajouter un nouveau niveau de jeu, par
|
||||||
|
exemple la stratégie lente (C13). Pour plus de précision, on numérotera
|
||||||
|
les étapes à faire.
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
1. Créer une nouvelle Classe implémentant l'interface Stratégie
|
||||||
|
2. Définir sa méthode nbPrise
|
||||||
|
3. Ajouter son identifiant (nom) dans le switch de Jouer.parsePlayer()
|
||||||
|
4. Dans le cas de sa sélection (case), affecter à strat la stratégie (constructeur)
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
Expliquer ce qui permet, dans votre conception, de changer dynamiquement
|
||||||
|
(en cours d'exécution du programme) la stratégie d'un joueur (C14).
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
La stratégie du joueur est un attribut (de la classe) on peut donc la ré-attribuer en
|
||||||
|
cours de partie.
|
||||||
|
On peut créer la méthode de classe setStrat(Stratégie) dans cet unique but.
|
||||||
|
|
||||||
|
|
||||||
|
=====[ Explications ]===========================================================
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
Donner ici les explications supplémentaires utiles à la compréhension du
|
||||||
|
travail rendu.
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Utiliser un Tab size de 4 pour avoir une lecture correcte.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
125
allumettes/Arbitre.java
Normal file
125
allumettes/Arbitre.java
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
public class Arbitre {
|
||||||
|
|
||||||
|
// Attributs
|
||||||
|
|
||||||
|
/** Joueurs de la partie */
|
||||||
|
private Joueur j1;
|
||||||
|
private Joueur j2;
|
||||||
|
|
||||||
|
/** Joueur jouant actuellement */
|
||||||
|
private Joueur courant;
|
||||||
|
|
||||||
|
/** Détermine si l'arbitre vérifie la triche */
|
||||||
|
private Boolean confiant = false;
|
||||||
|
|
||||||
|
// Constructeurs
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construire un arbitre à partir de deux joueurs.
|
||||||
|
*
|
||||||
|
* @param j1 Joueur n°1
|
||||||
|
* @param j2 Joueur n°2
|
||||||
|
*/
|
||||||
|
public Arbitre(Joueur j1, Joueur j2) throws ConfigurationException {
|
||||||
|
if (j1 == null) {
|
||||||
|
throw new ConfigurationException("j1 n'existe pas");
|
||||||
|
} else if (j2 == null) {
|
||||||
|
throw new ConfigurationException("j2 n'existe pas");
|
||||||
|
} else {
|
||||||
|
this.j1 = j1;
|
||||||
|
this.j2 = j2;
|
||||||
|
this.courant = j1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GETS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Déterminer quel joueur ne joue pas actuellement.
|
||||||
|
*/
|
||||||
|
private Joueur getAutre() {
|
||||||
|
if (this.courant == j1) {
|
||||||
|
return this.j2;
|
||||||
|
} else {
|
||||||
|
return this.j1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SETs
|
||||||
|
|
||||||
|
public void setConfiant(Boolean confiant) {
|
||||||
|
this.confiant = confiant;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de changer le joueur courant de la partie
|
||||||
|
*/
|
||||||
|
private void swapCourant() {
|
||||||
|
if (this.courant == this.j1) {
|
||||||
|
this.courant = this.j2;
|
||||||
|
} else {
|
||||||
|
this.courant = this.j1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Méthodes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arbitrer un jeu d'allumettes.
|
||||||
|
*
|
||||||
|
* @param game Jeu que l'on arbitre
|
||||||
|
*/
|
||||||
|
public void arbitrer(Jeu game) {
|
||||||
|
while (true) {
|
||||||
|
int nbPrise;
|
||||||
|
System.out.format("Nombre d'allumettes restantes : %d\n", game.getNombreAllumettes());
|
||||||
|
try {
|
||||||
|
|
||||||
|
// le joueur choisit sont coup
|
||||||
|
if (this.confiant) {
|
||||||
|
nbPrise = this.courant.getPrise(game);
|
||||||
|
} else {
|
||||||
|
nbPrise = this.courant.getPrise(new PartieSafe(game));
|
||||||
|
}
|
||||||
|
|
||||||
|
// l'arbitre énonce le coup
|
||||||
|
if (nbPrise == 1 || nbPrise == 0 || nbPrise == -1) {
|
||||||
|
System.out.format("%s prend %d allumette.\n", this.courant.getNom(), nbPrise);
|
||||||
|
} else {
|
||||||
|
System.out.format("%s prend %d allumettes.\n", this.courant.getNom(), nbPrise);
|
||||||
|
}
|
||||||
|
|
||||||
|
// l'arbitre vérifie la validité du coup
|
||||||
|
if (nbPrise > game.getNombreAllumettes()) {
|
||||||
|
throw new CoupInvalideException(nbPrise, String.format("> %d", game.getNombreAllumettes()));
|
||||||
|
} else if (nbPrise > Jeu.PRISE_MAX) {
|
||||||
|
throw new CoupInvalideException(nbPrise, String.format("> %d", Jeu.PRISE_MAX));
|
||||||
|
} else {
|
||||||
|
game.retirer(nbPrise);
|
||||||
|
}
|
||||||
|
|
||||||
|
// l'arbitre passe la main
|
||||||
|
this.swapCourant();
|
||||||
|
System.out.println();
|
||||||
|
break;
|
||||||
|
|
||||||
|
} catch (OperationInterditeException e) {
|
||||||
|
System.out.format("Abandon de la partie car %s triche !\n", this.courant.getNom());
|
||||||
|
throw e;
|
||||||
|
} catch (CoupInvalideException e) {
|
||||||
|
System.out.format("Impossible ! %s\n\n", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Déterminer le vainqueur en fin de partie.
|
||||||
|
*/
|
||||||
|
public void afficherGagnant() {
|
||||||
|
System.out.format("%s perd !\n", this.getAutre().getNom());
|
||||||
|
System.out.format("%s gagne !\n", this.courant.getNom());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
16
allumettes/ConfigurationException.java
Normal file
16
allumettes/ConfigurationException.java
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
/** Exception qui indique que la configuration d'une partie est incorrecte.
|
||||||
|
* @author Xavier Crégut
|
||||||
|
* @version 1.4
|
||||||
|
*/
|
||||||
|
public class ConfigurationException extends RuntimeException {
|
||||||
|
|
||||||
|
/** Initaliser une ConfigurationException avec le message précisé.
|
||||||
|
* @param message le message explicatif
|
||||||
|
*/
|
||||||
|
public ConfigurationException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
29
allumettes/CoupInvalideException.java
Normal file
29
allumettes/CoupInvalideException.java
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
/** Exception qui indique qu'un coup invalide est joué.
|
||||||
|
* @author Xavier Crégut
|
||||||
|
* @version $Revision: 1.3 $
|
||||||
|
*/
|
||||||
|
public class CoupInvalideException extends Exception {
|
||||||
|
|
||||||
|
/** Nombre d'allumettes prises. */
|
||||||
|
private int nbAllumettes;
|
||||||
|
|
||||||
|
/** Initialiser CoupInvalideException à partir du nombre d'allumettes
|
||||||
|
* prises et le problème constaté. Par exemple, on peut avoir nombre
|
||||||
|
* d'allumettes qui vaut 0 et le problème "< 1".
|
||||||
|
* @param nb le nombre d'allumettes prises
|
||||||
|
* @param probleme le problème sur le nombre d'allumettes
|
||||||
|
*/
|
||||||
|
public CoupInvalideException(int nb, String probleme) {
|
||||||
|
super("Nombre d'allumettes invalide : " + nb + " (" + probleme + ")");
|
||||||
|
this.nbAllumettes = nb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Indiquer le nombre d'allumettes qu'un joueur a voulu prendre.
|
||||||
|
* @return le nombre d'allumettes qu'un joueur a voulu prendre. */
|
||||||
|
public int getNombreAllumettes() {
|
||||||
|
return this.nbAllumettes;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
allumettes/Expert.java
Normal file
25
allumettes/Expert.java
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
public class Expert implements Strategie {
|
||||||
|
|
||||||
|
// TODO: à généraliser ?
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nbPrise(Jeu game, String nom) {
|
||||||
|
int prise = 0;
|
||||||
|
switch (game.getNombreAllumettes() % 4) {
|
||||||
|
case 0:
|
||||||
|
prise = 3;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
prise = 1;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
prise = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return prise;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
34
allumettes/Humain.java
Normal file
34
allumettes/Humain.java
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
public class Humain implements Strategie {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scanner qui permet de récupérer les entrées des joueurs humains sc est static
|
||||||
|
* car avoir plus d'un scanner ouvert à la fois semble faire bugger la lecture.
|
||||||
|
*/
|
||||||
|
private static Scanner sc = new Scanner(System.in);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nbPrise(Jeu game, String nom) throws CoupInvalideException {
|
||||||
|
int prise = 1;
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
System.out.printf("%s, combien d'allumettes ? ", nom);
|
||||||
|
String input = sc.nextLine();
|
||||||
|
if (input.equals("triche")) {
|
||||||
|
game.retirer(1);
|
||||||
|
System.out.format("[Une allumette en moins, plus que %d. Chut !]\n", game.getNombreAllumettes());
|
||||||
|
} else {
|
||||||
|
prise = Integer.parseInt(input);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (java.lang.NumberFormatException e) {
|
||||||
|
System.out.println("Vous devez donner un entier.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prise;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
21
allumettes/Jeu.java
Normal file
21
allumettes/Jeu.java
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
public interface Jeu {
|
||||||
|
|
||||||
|
/** Nombre maximal d'allumettes pouvant être prises. */
|
||||||
|
int PRISE_MAX = 3;
|
||||||
|
|
||||||
|
/** Obtenir le nombre d'allumettes encore en jeu.
|
||||||
|
* @return nombre d'allumettes encore en jeu
|
||||||
|
*/
|
||||||
|
int getNombreAllumettes();
|
||||||
|
|
||||||
|
/** Retirer des allumettes. Le nombre d'allumettes doit être compris
|
||||||
|
* entre 1 et PRISE_MAX, dans la limite du nombre d'allumettes encore
|
||||||
|
* en jeu.
|
||||||
|
* @param nbPrises nombre d'allumettes prises.
|
||||||
|
* @throws CoupInvalideException tentative de prendre un nombre invalide d'alumettes
|
||||||
|
*/
|
||||||
|
void retirer(int nbPrises) throws CoupInvalideException;
|
||||||
|
|
||||||
|
}
|
130
allumettes/Jouer.java
Normal file
130
allumettes/Jouer.java
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lance une partie du jeu des allumettes en fonction des arguments fournis sur
|
||||||
|
* la ligne de commande.
|
||||||
|
*
|
||||||
|
* @author Xavier Crégut
|
||||||
|
* @version $Revision: 1.5$
|
||||||
|
*/
|
||||||
|
public class Jouer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lancer une partie. En argument sont donnés les deux joueurs sous la forme
|
||||||
|
* nom@stratégie.
|
||||||
|
*
|
||||||
|
* @param args la description des deux joueurs
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
Joueur j1 = null;
|
||||||
|
Joueur j2 = null;
|
||||||
|
Arbitre arbitre = null;
|
||||||
|
Jeu game = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
verifierNombreArguments(args);
|
||||||
|
|
||||||
|
if (args.length > 2) {
|
||||||
|
j1 = parsePlayer(args[1]);
|
||||||
|
j2 = parsePlayer(args[2]);
|
||||||
|
} else {
|
||||||
|
j1 = parsePlayer(args[0]);
|
||||||
|
j2 = parsePlayer(args[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
arbitre = new Arbitre(j1, j2);
|
||||||
|
arbitre.setConfiant(args[0].equals("-confiant"));
|
||||||
|
game = new Partie();
|
||||||
|
|
||||||
|
} catch (ConfigurationException e) {
|
||||||
|
System.out.println("\nErreur : " + e.getMessage());
|
||||||
|
afficherUsage();
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (game.getNombreAllumettes() > 0) {
|
||||||
|
arbitre.arbitrer(game);
|
||||||
|
}
|
||||||
|
arbitre.afficherGagnant();
|
||||||
|
} finally {
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Créer un joueur à partir d'une chaine de caractères.
|
||||||
|
*
|
||||||
|
* @param arg chaine de caractère permettant de créer le joueur
|
||||||
|
* @throws ConfigurationException si le joueur ne peut pas être créé
|
||||||
|
*/
|
||||||
|
private static Joueur parsePlayer(String arg) throws ConfigurationException {
|
||||||
|
String[] pre = arg.split("@");
|
||||||
|
if (pre.length != 2) {
|
||||||
|
throw new ConfigurationException("Configuration d'un joueur invalide");
|
||||||
|
}
|
||||||
|
|
||||||
|
String nom = pre[0];
|
||||||
|
|
||||||
|
Strategie strat;
|
||||||
|
switch (pre[1].toLowerCase()) {
|
||||||
|
case "naif":
|
||||||
|
strat = new Naif();
|
||||||
|
break;
|
||||||
|
case "rapide":
|
||||||
|
strat = new Rapide();
|
||||||
|
break;
|
||||||
|
case "expert":
|
||||||
|
strat = new Expert();
|
||||||
|
break;
|
||||||
|
case "humain":
|
||||||
|
strat = new Humain();
|
||||||
|
break;
|
||||||
|
case "lente":
|
||||||
|
strat = new Lente();
|
||||||
|
break;
|
||||||
|
case "tricheur":
|
||||||
|
strat = new Tricheur();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ConfigurationException(String.format("Stratégie de %s invalide", nom));
|
||||||
|
}
|
||||||
|
return new Joueur(nom, strat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vérifier si le nombre d'arguments fournis dans la ligne de commande est
|
||||||
|
* cohérent.
|
||||||
|
*
|
||||||
|
* @param args arguments de la ligne de commande
|
||||||
|
* @throws ConfigurationException si les argument ne sont pas correctes
|
||||||
|
*/
|
||||||
|
private static void verifierNombreArguments(String[] args) throws ConfigurationException {
|
||||||
|
final int nbJoueurs = 2;
|
||||||
|
if (args.length < nbJoueurs) {
|
||||||
|
throw new ConfigurationException("Trop peu d'arguments : " + args.length);
|
||||||
|
}
|
||||||
|
if (args.length > nbJoueurs + 1) {
|
||||||
|
throw new ConfigurationException("Trop d'arguments : " + args.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Afficher des indications sur la manière d'exécuter cette classe.
|
||||||
|
*/
|
||||||
|
public static void afficherUsage() {
|
||||||
|
System.out.println("\n"
|
||||||
|
+ "Usage :"
|
||||||
|
+ "\n\t" + "java allumettes.Jouer joueur1 joueur2"
|
||||||
|
+ "\n\t\t" + "joueur est de la forme nom@stratégie"
|
||||||
|
+ "\n\t\t" + "strategie = naif | rapide | expert | humain | tricheur | lente"
|
||||||
|
|
||||||
|
+ "\n\n\t" + "Exemple :"
|
||||||
|
+ "\n\t\t" + "java allumettes.Jouer Xavier@humain Ordinateur@naif"
|
||||||
|
+ "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
75
allumettes/Joueur.java
Normal file
75
allumettes/Joueur.java
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
public class Joueur {
|
||||||
|
|
||||||
|
// Attributs
|
||||||
|
|
||||||
|
/** Le nom du joueur */
|
||||||
|
private String nom;
|
||||||
|
|
||||||
|
/** Stratégie adoptée par le joueur */
|
||||||
|
private Strategie strat;
|
||||||
|
|
||||||
|
// Constructeurs
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construire un joueur à partir de son nom et du nom de sa stratégie.
|
||||||
|
*
|
||||||
|
* @param nom nom du joueur
|
||||||
|
* @param strat stratégie à adopter
|
||||||
|
*/
|
||||||
|
public Joueur(String nom, Strategie strat) {
|
||||||
|
|
||||||
|
if (nom == null) {
|
||||||
|
throw new ConfigurationException("Un joueur n'a pas de nom");
|
||||||
|
} else if (strat == null) {
|
||||||
|
throw new ConfigurationException(this.nom + " n'a pas de stratégie");
|
||||||
|
} else {
|
||||||
|
this.nom = nom;
|
||||||
|
this.strat = strat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GETs
|
||||||
|
|
||||||
|
public String getNom() {
|
||||||
|
return this.nom;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SETs
|
||||||
|
|
||||||
|
public void setNom(String nom) throws ConfigurationException {
|
||||||
|
if (nom == null) {
|
||||||
|
throw new ConfigurationException(this.nom + "doit avoir un nouveau nom valide");
|
||||||
|
} else {
|
||||||
|
this.nom = nom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrat(Strategie strat) throws ConfigurationException {
|
||||||
|
if (strat == null) {
|
||||||
|
throw new ConfigurationException(this.nom + "doit avoir une stratégie valide");
|
||||||
|
} else {
|
||||||
|
this.strat = strat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Méthodes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtenir le nombre d'allumettes que le joueur prends.
|
||||||
|
*
|
||||||
|
* @param game Le jeu auquel on prend des allumettes
|
||||||
|
* @return le nombre d'allumettes que le joueur prends
|
||||||
|
* @throws CoupInvalideException si le coup
|
||||||
|
* @throws ConfigurationException si le jeu fournis est null
|
||||||
|
*/
|
||||||
|
public int getPrise(Jeu game) throws CoupInvalideException, ConfigurationException {
|
||||||
|
if (game == null) {
|
||||||
|
throw new ConfigurationException(this.nom + " ne trouve pas la partie");
|
||||||
|
} else {
|
||||||
|
return this.strat.nbPrise(game, this.nom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
allumettes/Lente.java
Normal file
10
allumettes/Lente.java
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
public class Lente implements Strategie {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nbPrise(Jeu game, String nom) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
21
allumettes/Naif.java
Normal file
21
allumettes/Naif.java
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class Naif implements Strategie {
|
||||||
|
|
||||||
|
/** Générateur de nombres aléatoire */
|
||||||
|
private Random random = new Random();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nbPrise(Jeu game, String nom) {
|
||||||
|
int rd = random.nextInt(Jeu.PRISE_MAX) + 1;
|
||||||
|
int nb = game.getNombreAllumettes();
|
||||||
|
if (rd > nb) {
|
||||||
|
return nb;
|
||||||
|
} else {
|
||||||
|
return rd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
5
allumettes/OperationInterditeException.java
Normal file
5
allumettes/OperationInterditeException.java
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
public class OperationInterditeException extends RuntimeException {
|
||||||
|
|
||||||
|
}
|
48
allumettes/Partie.java
Normal file
48
allumettes/Partie.java
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
public class Partie implements Jeu {
|
||||||
|
|
||||||
|
// Attributs
|
||||||
|
|
||||||
|
/** variable stockant le nombre d'allumettes encore en jeu */
|
||||||
|
private int nbAllumettes;
|
||||||
|
|
||||||
|
// Constructeurs
|
||||||
|
|
||||||
|
/** Constructeur par défaut de la classe Partie. */
|
||||||
|
public Partie() {
|
||||||
|
this.nbAllumettes = 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur de la classe Partie.
|
||||||
|
*
|
||||||
|
* @param nbAllumettes nombre d'allumettes initiales ( > 0 )
|
||||||
|
*/
|
||||||
|
public Partie(int nbAllumettes) {
|
||||||
|
if (nbAllumettes < 1) {
|
||||||
|
throw new ConfigurationException("Nombre d'allumettes initiales incorrectes ( < 1 )");
|
||||||
|
} else {
|
||||||
|
this.nbAllumettes = nbAllumettes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GETs
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNombreAllumettes() {
|
||||||
|
return this.nbAllumettes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Méthodes
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void retirer(int nbPrises) throws CoupInvalideException {
|
||||||
|
if (nbPrises < 1) {
|
||||||
|
throw new CoupInvalideException(nbPrises, "< 1");
|
||||||
|
} else {
|
||||||
|
this.nbAllumettes -= nbPrises;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
32
allumettes/PartieSafe.java
Normal file
32
allumettes/PartieSafe.java
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
public class PartieSafe implements Jeu {
|
||||||
|
|
||||||
|
// ATTRIBUTS
|
||||||
|
|
||||||
|
Jeu vraiGame;
|
||||||
|
|
||||||
|
// CONSTRUCTEUR
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur d'une partie dont le nombre d'allumettes ne peut être modifié.
|
||||||
|
*
|
||||||
|
* @param game Jeu que l'on utilise pour créer le proxy
|
||||||
|
*/
|
||||||
|
public PartieSafe(Jeu game) {
|
||||||
|
this.vraiGame = game;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MÉTHODES
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void retirer(int nbPrises) {
|
||||||
|
throw new OperationInterditeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNombreAllumettes() {
|
||||||
|
return vraiGame.getNombreAllumettes();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
15
allumettes/Rapide.java
Normal file
15
allumettes/Rapide.java
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
public class Rapide implements Strategie {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nbPrise(Jeu game, String nom) {
|
||||||
|
int nb = game.getNombreAllumettes();
|
||||||
|
if (nb > Jeu.PRISE_MAX) {
|
||||||
|
return Jeu.PRISE_MAX;
|
||||||
|
} else {
|
||||||
|
return nb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
allumettes/Strategie.java
Normal file
14
allumettes/Strategie.java
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
public interface Strategie {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renvoyer le nombre d'allumettes que le joueur doit prendre.
|
||||||
|
*
|
||||||
|
* @param nb nombre d'allumettes encore en jeu
|
||||||
|
* @param nom nom du joueur
|
||||||
|
* @return nombre d'allumettes à prendre
|
||||||
|
*/
|
||||||
|
int nbPrise(Jeu game, String nom) throws CoupInvalideException;
|
||||||
|
|
||||||
|
}
|
41
allumettes/TestArbitre.java
Normal file
41
allumettes/TestArbitre.java
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
import org.junit.*;
|
||||||
|
|
||||||
|
public class TestArbitre {
|
||||||
|
|
||||||
|
Partie game = new Partie(100);
|
||||||
|
|
||||||
|
Joueur j1 = new Joueur("j1", new Rapide());
|
||||||
|
Joueur j2 = new Joueur("j2", new Lente());
|
||||||
|
Joueur j3 = new Joueur("j3", new Tricheur());
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void TestConstructeur() {
|
||||||
|
Arbitre a1 = new Arbitre(j1, j2);
|
||||||
|
Arbitre a2 = new Arbitre(j1, j2);
|
||||||
|
a1.setConfiant(true);
|
||||||
|
a2.setConfiant(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void TestArbitrer() {
|
||||||
|
Arbitre a1 = new Arbitre(j1, j2);
|
||||||
|
a1.setConfiant(false);
|
||||||
|
a1.arbitrer(game);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = OperationInterditeException.class)
|
||||||
|
public void TestArbitrerTricheur() {
|
||||||
|
Arbitre a1 = new Arbitre(j3, j2);
|
||||||
|
a1.arbitrer(game);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void TestArbitrerTricheurConfiant() {
|
||||||
|
Arbitre a1 = new Arbitre(j3, j2);
|
||||||
|
a1.setConfiant(true);
|
||||||
|
a1.arbitrer(game);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
allumettes/TestLente.java
Normal file
26
allumettes/TestLente.java
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.junit.*;
|
||||||
|
|
||||||
|
public class TestLente {
|
||||||
|
|
||||||
|
Strategie strat = new Lente();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void TestRetirer() throws CoupInvalideException {
|
||||||
|
|
||||||
|
Random rd = new Random();
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
Partie game = new Partie(rd.nextInt(100) + 1);
|
||||||
|
int nb = strat.nbPrise(game, "nom");
|
||||||
|
assertEquals(nb, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
48
allumettes/TestPartie.java
Normal file
48
allumettes/TestPartie.java
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
import org.junit.*;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class TestPartie {
|
||||||
|
|
||||||
|
@Test(expected = ConfigurationException.class)
|
||||||
|
public void TestConstructeurNegatif() {
|
||||||
|
new Partie(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = ConfigurationException.class)
|
||||||
|
public void TestConstructeurNul() {
|
||||||
|
new Partie(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void TestConstructeurPositif() {
|
||||||
|
new Partie(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = CoupInvalideException.class)
|
||||||
|
public void TestRetirerNegatif() throws CoupInvalideException {
|
||||||
|
new Partie(1).retirer(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = CoupInvalideException.class)
|
||||||
|
public void TestRetirerNul() throws CoupInvalideException {
|
||||||
|
new Partie(1).retirer(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void TestRetirerPositif() throws CoupInvalideException {
|
||||||
|
Partie game = new Partie(20);
|
||||||
|
game.retirer(1);
|
||||||
|
assertEquals(game.getNombreAllumettes(), 19);
|
||||||
|
game.retirer(2);
|
||||||
|
assertEquals(game.getNombreAllumettes(), 17);
|
||||||
|
game.retirer(3);
|
||||||
|
assertEquals(game.getNombreAllumettes(), 14);
|
||||||
|
game.retirer(4);
|
||||||
|
assertEquals(game.getNombreAllumettes(), 10);
|
||||||
|
game.retirer(10);
|
||||||
|
assertEquals(game.getNombreAllumettes(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
24
allumettes/TestPartieSafe.java
Normal file
24
allumettes/TestPartieSafe.java
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
import org.junit.*;
|
||||||
|
|
||||||
|
public class TestPartieSafe {
|
||||||
|
|
||||||
|
PartieSafe game = new PartieSafe(new Partie(10));
|
||||||
|
|
||||||
|
@Test(expected = OperationInterditeException.class)
|
||||||
|
public void TestRetirerNegatif() throws CoupInvalideException {
|
||||||
|
game.retirer(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = OperationInterditeException.class)
|
||||||
|
public void TestRetirerNul() throws CoupInvalideException {
|
||||||
|
game.retirer(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = OperationInterditeException.class)
|
||||||
|
public void TestRetirerPositif() throws CoupInvalideException {
|
||||||
|
game.retirer(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
54
allumettes/TestRapide.java
Normal file
54
allumettes/TestRapide.java
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotEquals;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.junit.*;
|
||||||
|
|
||||||
|
public class TestRapide {
|
||||||
|
|
||||||
|
Strategie strat = new Rapide();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void TestSuperieur() throws CoupInvalideException {
|
||||||
|
|
||||||
|
Random rd = new Random();
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
Partie game = new Partie(rd.nextInt(1000) + Jeu.PRISE_MAX);
|
||||||
|
int nb = strat.nbPrise(game, "nom");
|
||||||
|
assertEquals(nb, Jeu.PRISE_MAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void TestInferieur() throws CoupInvalideException {
|
||||||
|
|
||||||
|
for (int i = 1; i < Jeu.PRISE_MAX; i++) {
|
||||||
|
Partie game = new Partie(i);
|
||||||
|
int nb = strat.nbPrise(game, "nom");
|
||||||
|
assertNotEquals(nb, Jeu.PRISE_MAX);
|
||||||
|
assertEquals(nb, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void TestArbitre() throws CoupInvalideException {
|
||||||
|
|
||||||
|
Joueur j1 = new Joueur("j1", new Rapide());
|
||||||
|
Joueur j2 = new Joueur("j2", new Rapide());
|
||||||
|
Arbitre arbitre = new Arbitre(j1, j2);
|
||||||
|
|
||||||
|
for (int i = 1; i < 100; i++) {
|
||||||
|
Partie game = new Partie(i);
|
||||||
|
while (game.getNombreAllumettes() > 0) {
|
||||||
|
arbitre.arbitrer(game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
13
allumettes/Tricheur.java
Normal file
13
allumettes/Tricheur.java
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package allumettes;
|
||||||
|
|
||||||
|
public class Tricheur implements Strategie {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nbPrise(Jeu game, String nom) throws CoupInvalideException {
|
||||||
|
System.out.println("[Je triche...]");
|
||||||
|
game.retirer(game.getNombreAllumettes() - 2);
|
||||||
|
System.out.format("[Allumettes restantes : %d]\n", game.getNombreAllumettes());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
104
testeur.sh
Normal file
104
testeur.sh
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# -------------------------------------------------------
|
||||||
|
# Programme de test en boîte noire pour les 13 allumettes
|
||||||
|
# -------------------------------------------------------
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Erreur : $1"
|
||||||
|
echo
|
||||||
|
echo "Usage : sh testeur.sh [-d dossier] fichier.run..."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
warning() {
|
||||||
|
echo "**** $1" 1>&2
|
||||||
|
}
|
||||||
|
|
||||||
|
mainClass=allumettes.Jouer
|
||||||
|
mainFile=`echo $mainClass | tr . /`.java
|
||||||
|
|
||||||
|
# Déterminer si l'option -enconding latin1 est nécessaire
|
||||||
|
javacOpt=
|
||||||
|
if file -i $mainFile | grep iso-8859 > /dev/null 2>&1 ; then
|
||||||
|
echo "Le fichier $mainClass est en latin1. Utilisation de l'option -encoding latin1 de javac"
|
||||||
|
javacOpt="-encoding latin1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Traiter les arguments de la ligne de commande
|
||||||
|
# | Un seul argument possible -d pour déterminer le dossier dans lequel
|
||||||
|
# | mettre les résutlats du test (.computed et .diff)
|
||||||
|
if [ "$1" = "-d" ] ; then
|
||||||
|
shift
|
||||||
|
testdiropt="$1"
|
||||||
|
shift
|
||||||
|
[ -d "$testdiropt" ] || mkdir "$testdiropt"
|
||||||
|
if [ ! -d "$testdiropt" ] ; then
|
||||||
|
usage "$testdiropt n'est pas un dossier"
|
||||||
|
elif [ ! -w "$testdiropt" ] ; then
|
||||||
|
usage "impossible d'écrire dans $testdiropt"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "$testdiropt" ] ; then
|
||||||
|
echo "Les résultats seront dans $testdiropt"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Jouer les tests
|
||||||
|
if javac $javacOpt $mainFile ; then
|
||||||
|
while [ "$1" ] ; do
|
||||||
|
test="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [ ! -f "$test" ] ; then
|
||||||
|
warning "Fichier de test inexitant : $test"
|
||||||
|
continue
|
||||||
|
elif [ ! -r "$test" ] ; then
|
||||||
|
warning "Fichier de test interdit en lecture : $test"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
testName=$(basename $test .run)
|
||||||
|
outputDir=${testdiropt:-$(dirname $test)}
|
||||||
|
|
||||||
|
if [ "$testName" = "$(basename $test)" ] ; then
|
||||||
|
warning "Test ignoré (le suffixe doit être .run) : $test"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Définir les noms de fichiers utilisés
|
||||||
|
computed=$outputDir/$testName.computed
|
||||||
|
expected=${test%.run}.expected
|
||||||
|
diff=$outputDir/$testName.diff
|
||||||
|
|
||||||
|
|
||||||
|
if [ ! -r "$expected" ] ; then
|
||||||
|
warning "Fichier de résultat absent ou interdit en lecture : $expected"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Lancer le test
|
||||||
|
sh $test > $computed 2>&1
|
||||||
|
|
||||||
|
# Transformer le résultat en utf8 (si nécessaire)
|
||||||
|
if file -i $computed | grep iso-8859 > /dev/null 2>&1 ; then
|
||||||
|
echo "Résultat en latin1. Je transforme en utf8."
|
||||||
|
recode latin1..utf8 $computed
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Afficher le résultat
|
||||||
|
echo -n "$testName : "
|
||||||
|
if diff -Bbw $computed $expected > $diff 2>&1 ; then
|
||||||
|
echo "ok"
|
||||||
|
else
|
||||||
|
echo "ERREUR"
|
||||||
|
cat $diff
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "Erreur de compilation !"
|
||||||
|
fi
|
||||||
|
|
BIN
to-1sn-2020-pr-02-sujet.pdf
Normal file
BIN
to-1sn-2020-pr-02-sujet.pdf
Normal file
Binary file not shown.
Loading…
Reference in a new issue