ajout TP3
This commit is contained in:
BIN
TP3/fr/iut_fbleau/GameAPI/AbstractBoard.class
Normal file
BIN
TP3/fr/iut_fbleau/GameAPI/AbstractBoard.class
Normal file
Binary file not shown.
99
TP3/fr/iut_fbleau/GameAPI/AbstractBoard.java
Normal file
99
TP3/fr/iut_fbleau/GameAPI/AbstractBoard.java
Normal file
@@ -0,0 +1,99 @@
|
||||
package fr.iut_fbleau.GameAPI;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Deque;
|
||||
|
||||
/**
|
||||
* An abstract class implementing the interface IBoard.
|
||||
*
|
||||
* used to implement some things to do with the update of the next player
|
||||
* which is the same for all games and provides also a minimal
|
||||
* implantation of the history mechanism.
|
||||
*/
|
||||
public abstract class AbstractBoard implements IBoard{
|
||||
|
||||
private Player currentPlayer ;
|
||||
|
||||
private Deque<AbstractPly> history;
|
||||
|
||||
private void setNextPlayer(){
|
||||
if (this.currentPlayer==Player.PLAYER1){
|
||||
this.currentPlayer= Player.PLAYER2;
|
||||
}
|
||||
else
|
||||
this.currentPlayer= Player.PLAYER1;
|
||||
}
|
||||
|
||||
// Beware not checking if move is legal.
|
||||
// To be used in do(AbstractPly c)
|
||||
private void addPlyToHistory(AbstractPly c){
|
||||
this.history.addLast(c);
|
||||
}
|
||||
|
||||
// Beware not checking if history is not empty
|
||||
// To be used in undo()
|
||||
private void removePlyFromHistory(){
|
||||
this.history.removeLast();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the current player
|
||||
*/
|
||||
public Player getcurrentPlayer(){
|
||||
return this.currentPlayer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the game status
|
||||
*
|
||||
* @return true iff the game is over
|
||||
*/
|
||||
public abstract boolean isGameOver();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the result (null if not over)
|
||||
*/
|
||||
public abstract Result getResult();
|
||||
|
||||
/**
|
||||
* checker of legal moves from this position
|
||||
*
|
||||
* @throws NullPointerException if the game is over
|
||||
* @return the iterator
|
||||
*/
|
||||
public abstract boolean isLegal(AbstractPly c);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* constructor of Iterator over legal moves from this position
|
||||
*
|
||||
* @throws NullPointerException if the game is over
|
||||
* @return the iterator
|
||||
*/
|
||||
public abstract Iterator<AbstractPly> iterator();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Plays a given move on the plateau.
|
||||
* Should update history using
|
||||
* @throws IllegalArgumentException if the move is always illegal (say from the wrong game)
|
||||
* @throws IllegalStateException if the move is not legal in this position
|
||||
*
|
||||
* @param AbstractPly to be played
|
||||
*
|
||||
*/
|
||||
public abstract void doPly(AbstractPly c);
|
||||
|
||||
/**
|
||||
* Resets the plateau to the position before the last move.
|
||||
*
|
||||
* @throws IllegalStateException if nothing to undo in history
|
||||
*
|
||||
*/
|
||||
public abstract void undoPly();
|
||||
|
||||
}
|
BIN
TP3/fr/iut_fbleau/GameAPI/AbstractGamePlayer.class
Normal file
BIN
TP3/fr/iut_fbleau/GameAPI/AbstractGamePlayer.class
Normal file
Binary file not shown.
26
TP3/fr/iut_fbleau/GameAPI/AbstractGamePlayer.java
Normal file
26
TP3/fr/iut_fbleau/GameAPI/AbstractGamePlayer.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package fr.iut_fbleau.GameAPI;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* The abstract class for a game Player.
|
||||
*/
|
||||
public abstract class AbstractGamePlayer {
|
||||
|
||||
// not a band, but which type of player I am in the game (PLAYER1 or PLAYER2).
|
||||
private Player iAm;
|
||||
|
||||
// Le joueur réel pourrait avoir besoin de connaître un constructeur de coup?
|
||||
// pas pour l'instant.
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @throws UnsupportedOperationException if the method is not yet implemented
|
||||
*
|
||||
* @throws IllegalStateException if the Situation is already in the bookmarks
|
||||
*/
|
||||
public abstract AbstractPly giveYourMove(IBoard p);
|
||||
|
||||
}
|
BIN
TP3/fr/iut_fbleau/GameAPI/AbstractPly.class
Normal file
BIN
TP3/fr/iut_fbleau/GameAPI/AbstractPly.class
Normal file
Binary file not shown.
5
TP3/fr/iut_fbleau/GameAPI/AbstractPly.java
Normal file
5
TP3/fr/iut_fbleau/GameAPI/AbstractPly.java
Normal file
@@ -0,0 +1,5 @@
|
||||
package fr.iut_fbleau.GameAPI;
|
||||
|
||||
public abstract class AbstractPly {
|
||||
private Player joueur;
|
||||
}
|
BIN
TP3/fr/iut_fbleau/GameAPI/IBoard.class
Normal file
BIN
TP3/fr/iut_fbleau/GameAPI/IBoard.class
Normal file
Binary file not shown.
69
TP3/fr/iut_fbleau/GameAPI/IBoard.java
Normal file
69
TP3/fr/iut_fbleau/GameAPI/IBoard.java
Normal file
@@ -0,0 +1,69 @@
|
||||
package fr.iut_fbleau.GameAPI;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* The interface Board.
|
||||
*/
|
||||
public interface IBoard {
|
||||
|
||||
|
||||
/**
|
||||
* @return the current player
|
||||
*/
|
||||
public Player getcurrentPlayer();
|
||||
|
||||
/**
|
||||
* Returns the game status
|
||||
*
|
||||
* @return true iff the game is over
|
||||
*/
|
||||
public boolean isGameOver();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the result (null if not over)
|
||||
*/
|
||||
public Result getResult();
|
||||
|
||||
/**
|
||||
* checker of legal moves from this position
|
||||
*
|
||||
* @throws NullPointerException if the game is over
|
||||
* @return the iterator
|
||||
*/
|
||||
public boolean isLegal(AbstractPly c);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* constructor of Iterator over legal moves from this position
|
||||
*
|
||||
* @throws NullPointerException if the game is over
|
||||
* @return the iterator
|
||||
*/
|
||||
public Iterator<AbstractPly> iterator();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Plays a given move on the plateau.
|
||||
* Should update history using
|
||||
* @throws IllegalArgumentException if the move is always illegal (say from the wrong game)
|
||||
* @throws IllegalStateException if the move is not legal in this position
|
||||
*
|
||||
* @param AbstractPly to be played
|
||||
*
|
||||
*/
|
||||
public void doPly(AbstractPly c);
|
||||
|
||||
/**
|
||||
* Resets the plateau to the position before the last move.
|
||||
*
|
||||
* @throws IllegalStateException if nothing to undo in history
|
||||
*
|
||||
*/
|
||||
public void undoPly();
|
||||
|
||||
|
||||
}
|
BIN
TP3/fr/iut_fbleau/GameAPI/Player.class
Normal file
BIN
TP3/fr/iut_fbleau/GameAPI/Player.class
Normal file
Binary file not shown.
6
TP3/fr/iut_fbleau/GameAPI/Player.java
Normal file
6
TP3/fr/iut_fbleau/GameAPI/Player.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package fr.iut_fbleau.GameAPI;
|
||||
|
||||
public enum Player {
|
||||
PLAYER1,
|
||||
PLAYER2
|
||||
}
|
BIN
TP3/fr/iut_fbleau/GameAPI/Result.class
Normal file
BIN
TP3/fr/iut_fbleau/GameAPI/Result.class
Normal file
Binary file not shown.
11
TP3/fr/iut_fbleau/GameAPI/Result.java
Normal file
11
TP3/fr/iut_fbleau/GameAPI/Result.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package fr.iut_fbleau.GameAPI;
|
||||
|
||||
/**
|
||||
* To output the result of a 2 player game that is symmetric.
|
||||
* from the perspective of the player PLAYER1.
|
||||
*/
|
||||
public enum Result {
|
||||
WIN,
|
||||
DRAW,
|
||||
LOSS;
|
||||
}
|
BIN
TP3/fr/iut_fbleau/Nim/NimBoard.class
Normal file
BIN
TP3/fr/iut_fbleau/Nim/NimBoard.class
Normal file
Binary file not shown.
199
TP3/fr/iut_fbleau/Nim/NimBoard.java
Normal file
199
TP3/fr/iut_fbleau/Nim/NimBoard.java
Normal file
@@ -0,0 +1,199 @@
|
||||
package fr.iut_fbleau.Nim;
|
||||
|
||||
import fr.iut_fbleau.GameAPI.AbstractBoard;
|
||||
import fr.iut_fbleau.GameAPI.AbstractPly;
|
||||
import fr.iut_fbleau.GameAPI.Player;
|
||||
import fr.iut_fbleau.GameAPI.Result;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
/**
|
||||
* Représente le plateau du jeu de Nim.
|
||||
* Le jeu de Nim se joue avec un certain nombre d'allumettes.
|
||||
* Les joueurs retirent à tour de rôle entre 1 et maxParCoup allumettes.
|
||||
* Le joueur qui retire la dernière allumette perd (variante misère).
|
||||
*/
|
||||
public class NimBoard extends AbstractBoard {
|
||||
|
||||
private int allumettesRestantes;
|
||||
private int maxParCoup;
|
||||
private int allumettesInitiales;
|
||||
private Player currentPlayer;
|
||||
private Deque<AbstractPly> history;
|
||||
private boolean gameOver;
|
||||
private Result result;
|
||||
|
||||
/**
|
||||
* Constructeur du plateau de Nim
|
||||
*
|
||||
* @param allumettesInitiales le nombre d'allumettes au début du jeu
|
||||
* @param maxParCoup le nombre maximum d'allumettes qu'on peut retirer par coup
|
||||
*/
|
||||
public NimBoard(int allumettesInitiales, int maxParCoup) {
|
||||
if (allumettesInitiales <= 0) {
|
||||
throw new IllegalArgumentException("Le nombre d'allumettes doit être positif");
|
||||
}
|
||||
if (maxParCoup <= 0) {
|
||||
throw new IllegalArgumentException("Le nombre maximum par coup doit être positif");
|
||||
}
|
||||
|
||||
this.allumettesInitiales = allumettesInitiales;
|
||||
this.allumettesRestantes = allumettesInitiales;
|
||||
this.maxParCoup = maxParCoup;
|
||||
this.currentPlayer = Player.PLAYER1;
|
||||
this.history = new ArrayDeque<>();
|
||||
this.gameOver = false;
|
||||
this.result = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return le nombre d'allumettes restantes
|
||||
*/
|
||||
public int getAllumettesRestantes() {
|
||||
return this.allumettesRestantes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return le nombre maximum d'allumettes par coup
|
||||
*/
|
||||
public int getMaxParCoup() {
|
||||
return this.maxParCoup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getcurrentPlayer() {
|
||||
return this.currentPlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGameOver() {
|
||||
return this.gameOver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result getResult() {
|
||||
return this.result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLegal(AbstractPly c) {
|
||||
if (this.gameOver) {
|
||||
throw new NullPointerException("Le jeu est terminé");
|
||||
}
|
||||
|
||||
if (!(c instanceof NimPly)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NimPly coup = (NimPly) c;
|
||||
|
||||
if (coup.getJoueur() != this.currentPlayer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Vérifier que le nombre d'allumettes est valide
|
||||
int nbAllumettes = coup.getNombreAllumettesPrises();
|
||||
return nbAllumettes >= 1 &&
|
||||
nbAllumettes <= this.maxParCoup &&
|
||||
nbAllumettes <= this.allumettesRestantes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<AbstractPly> iterator() {
|
||||
if (this.gameOver) {
|
||||
throw new NullPointerException("Le jeu est terminé");
|
||||
}
|
||||
|
||||
ArrayList<AbstractPly> coups = new ArrayList<>();
|
||||
int maxRetirage = Math.min(this.maxParCoup, this.allumettesRestantes);
|
||||
|
||||
for (int i = 1; i <= maxRetirage; i++) {
|
||||
coups.add(new NimPly(this.currentPlayer, i));
|
||||
}
|
||||
|
||||
return coups.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doPly(AbstractPly c) {
|
||||
if (!(c instanceof NimPly)) {
|
||||
throw new IllegalArgumentException("Le coup doit être un NimPly");
|
||||
}
|
||||
|
||||
if (!isLegal(c)) {
|
||||
throw new IllegalStateException("Ce coup n'est pas légal");
|
||||
}
|
||||
|
||||
NimPly coup = (NimPly) c;
|
||||
|
||||
// Retirer les allumettes
|
||||
this.allumettesRestantes -= coup.getNombreAllumettesPrises();
|
||||
|
||||
// Ajouter le coup à l'historique
|
||||
this.history.addLast(c);
|
||||
|
||||
// Vérifier si le jeu est terminé
|
||||
if (this.allumettesRestantes == 0) {
|
||||
this.gameOver = true;
|
||||
// Dans la variante misère : celui qui prend la dernière allumette perd
|
||||
if (this.currentPlayer == Player.PLAYER1) {
|
||||
this.result = Result.LOSS;
|
||||
} else {
|
||||
this.result = Result.WIN;
|
||||
}
|
||||
}
|
||||
|
||||
// Changer de joueur
|
||||
setNextPlayer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undoPly() {
|
||||
if (this.history.isEmpty()) {
|
||||
throw new IllegalStateException("Rien à annuler dans l'historique");
|
||||
}
|
||||
|
||||
AbstractPly dernierCoup = this.history.removeLast();
|
||||
NimPly coup = (NimPly) dernierCoup;
|
||||
|
||||
// Remettre les allumettes
|
||||
this.allumettesRestantes += coup.getNombreAllumettesPrises();
|
||||
|
||||
// Revenir au joueur précédent
|
||||
setNextPlayer();
|
||||
|
||||
// Réinitialiser l'état du jeu
|
||||
this.gameOver = false;
|
||||
this.result = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change le joueur courant
|
||||
*/
|
||||
private void setNextPlayer() {
|
||||
if (this.currentPlayer == Player.PLAYER1) {
|
||||
this.currentPlayer = Player.PLAYER2;
|
||||
} else {
|
||||
this.currentPlayer = Player.PLAYER1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Jeu de Nim\n");
|
||||
sb.append("Allumettes restantes : ").append(allumettesRestantes).append("\n");
|
||||
sb.append("Maximum par coup : ").append(maxParCoup).append("\n");
|
||||
sb.append("Joueur courant : ").append(currentPlayer).append("\n");
|
||||
|
||||
if (gameOver) {
|
||||
sb.append("Jeu terminé - Résultat (du point de vue de PLAYER1) : ").append(result).append("\n");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
BIN
TP3/fr/iut_fbleau/Nim/NimBotPlayer.class
Normal file
BIN
TP3/fr/iut_fbleau/Nim/NimBotPlayer.class
Normal file
Binary file not shown.
166
TP3/fr/iut_fbleau/Nim/NimBotPlayer.java
Normal file
166
TP3/fr/iut_fbleau/Nim/NimBotPlayer.java
Normal file
@@ -0,0 +1,166 @@
|
||||
package fr.iut_fbleau.Nim;
|
||||
|
||||
import fr.iut_fbleau.GameAPI.AbstractGamePlayer;
|
||||
import fr.iut_fbleau.GameAPI.AbstractPly;
|
||||
import fr.iut_fbleau.GameAPI.IBoard;
|
||||
import fr.iut_fbleau.GameAPI.Player;
|
||||
import fr.iut_fbleau.GameAPI.Result;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Représente un joueur bot pour le jeu de Nim.
|
||||
* Le bot utilise l'algorithme MiniMax avec élagage Alpha-Beta pour choisir le meilleur coup.
|
||||
*/
|
||||
public class NimBotPlayer extends AbstractGamePlayer {
|
||||
|
||||
private Player joueur;
|
||||
|
||||
/**
|
||||
* Constructeur d'un bot joueur de Nim
|
||||
*
|
||||
* @param joueur le type de joueur (PLAYER1 ou PLAYER2)
|
||||
*/
|
||||
public NimBotPlayer(Player joueur) {
|
||||
this.joueur = joueur;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractPly giveYourMove(IBoard p) {
|
||||
if (!(p instanceof NimBoard)) {
|
||||
throw new IllegalArgumentException("Le plateau doit être un NimBoard");
|
||||
}
|
||||
|
||||
NimBoard plateau = (NimBoard) p;
|
||||
|
||||
System.out.println("\n" + plateau);
|
||||
System.out.println("Le bot réfléchit...");
|
||||
|
||||
AbstractPly meilleurCoup = findBestMove(plateau);
|
||||
|
||||
System.out.println("Le bot joue : " + meilleurCoup);
|
||||
|
||||
return meilleurCoup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve le meilleur coup à jouer en utilisant l'algorithme MiniMax avec Alpha-Beta
|
||||
*/
|
||||
private AbstractPly findBestMove(NimBoard plateau) {
|
||||
AbstractPly meilleurCoup = null;
|
||||
int meilleureValeur;
|
||||
|
||||
if (this.joueur == Player.PLAYER1) {
|
||||
meilleureValeur = Integer.MIN_VALUE;
|
||||
|
||||
Iterator<AbstractPly> coups = plateau.iterator();
|
||||
while (coups.hasNext()) {
|
||||
AbstractPly coup = coups.next();
|
||||
|
||||
plateau.doPly(coup);
|
||||
int score = minimax(plateau, Integer.MIN_VALUE, Integer.MAX_VALUE, false);
|
||||
plateau.undoPly();
|
||||
|
||||
if (score > meilleureValeur) {
|
||||
meilleureValeur = score;
|
||||
meilleurCoup = coup;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
meilleureValeur = Integer.MAX_VALUE;
|
||||
|
||||
Iterator<AbstractPly> coups = plateau.iterator();
|
||||
while (coups.hasNext()) {
|
||||
AbstractPly coup = coups.next();
|
||||
|
||||
plateau.doPly(coup);
|
||||
int score = minimax(plateau, Integer.MIN_VALUE, Integer.MAX_VALUE, true);
|
||||
plateau.undoPly();
|
||||
|
||||
if (score < meilleureValeur) {
|
||||
meilleureValeur = score;
|
||||
meilleurCoup = coup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return meilleurCoup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Algorithme MiniMax avec élagage Alpha-Beta
|
||||
*
|
||||
* @param plateau le plateau de jeu
|
||||
* @param alpha la valeur alpha pour l'élagage
|
||||
* @param beta la valeur beta pour l'élagage
|
||||
* @param isMaximizing true si on maximise, false si on minimise
|
||||
* @return l'évaluation de la position
|
||||
*/
|
||||
private int minimax(NimBoard plateau, int alpha, int beta, boolean isMaximizing) {
|
||||
// Condition terminale : jeu fini
|
||||
if (plateau.isGameOver()) {
|
||||
Result result = plateau.getResult();
|
||||
if (result == Result.WIN) {
|
||||
return 1; // PLAYER1 gagne
|
||||
} else if (result == Result.LOSS) {
|
||||
return -1; // PLAYER1 perd (PLAYER2 gagne)
|
||||
} else {
|
||||
return 0; // Match nul
|
||||
}
|
||||
}
|
||||
|
||||
if (isMaximizing) {
|
||||
// Maximiser pour PLAYER1
|
||||
int max = Integer.MIN_VALUE;
|
||||
|
||||
Iterator<AbstractPly> coups = plateau.iterator();
|
||||
while (coups.hasNext()) {
|
||||
AbstractPly coup = coups.next();
|
||||
|
||||
plateau.doPly(coup);
|
||||
int eval = minimax(plateau, alpha, beta, false);
|
||||
plateau.undoPly();
|
||||
|
||||
max = Math.max(max, eval);
|
||||
alpha = Math.max(alpha, eval);
|
||||
|
||||
// Élagage Beta
|
||||
if (beta <= alpha) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return max;
|
||||
} else {
|
||||
// Minimiser pour PLAYER2
|
||||
int min = Integer.MAX_VALUE;
|
||||
|
||||
Iterator<AbstractPly> coups = plateau.iterator();
|
||||
while (coups.hasNext()) {
|
||||
AbstractPly coup = coups.next();
|
||||
|
||||
plateau.doPly(coup);
|
||||
int eval = minimax(plateau, alpha, beta, true);
|
||||
plateau.undoPly();
|
||||
|
||||
min = Math.min(min, eval);
|
||||
beta = Math.min(beta, eval);
|
||||
|
||||
// Élagage Alpha
|
||||
if (beta <= alpha) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return min;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return le type de joueur
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return this.joueur;
|
||||
}
|
||||
}
|
||||
|
BIN
TP3/fr/iut_fbleau/Nim/NimGame.class
Normal file
BIN
TP3/fr/iut_fbleau/Nim/NimGame.class
Normal file
Binary file not shown.
79
TP3/fr/iut_fbleau/Nim/NimGame.java
Normal file
79
TP3/fr/iut_fbleau/Nim/NimGame.java
Normal file
@@ -0,0 +1,79 @@
|
||||
package fr.iut_fbleau.Nim;
|
||||
|
||||
import fr.iut_fbleau.GameAPI.Player;
|
||||
import fr.iut_fbleau.GameAPI.AbstractPly;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Classe principale pour jouer au jeu de Nim.
|
||||
* Cette classe permet de lancer une partie entre deux joueurs.
|
||||
*/
|
||||
public class NimGame {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("=== Jeu de Nim ===\n");
|
||||
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
|
||||
// Demander le nombre d'allumettes
|
||||
int allumettesInitiales = 0;
|
||||
while (allumettesInitiales <= 0) {
|
||||
System.out.print("Avec combien d'allumettes voulez-vous commencer ? (minimum 1) : ");
|
||||
try {
|
||||
allumettesInitiales = scanner.nextInt();
|
||||
if (allumettesInitiales <= 0) {
|
||||
System.out.println("Le nombre doit être positif !");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Entrée invalide. Veuillez entrer un nombre.");
|
||||
scanner.nextLine(); // vider le buffer
|
||||
}
|
||||
}
|
||||
|
||||
// Maximum par coup fixé à 3
|
||||
int maxParCoup = 3;
|
||||
|
||||
NimBoard plateau = new NimBoard(allumettesInitiales, maxParCoup);
|
||||
|
||||
// Créer les joueurs
|
||||
NimPlayer joueur1 = new NimPlayer(Player.PLAYER1);
|
||||
NimBotPlayer joueur2 = new NimBotPlayer(Player.PLAYER2);
|
||||
|
||||
System.out.println("\nConfiguration du jeu :");
|
||||
System.out.println("- Nombre d'allumettes : " + allumettesInitiales);
|
||||
System.out.println("- Maximum par coup : " + maxParCoup);
|
||||
System.out.println("- Règle : Le joueur qui prend la dernière allumette PERD");
|
||||
System.out.println("- PLAYER1 : Humain");
|
||||
System.out.println("- PLAYER2 : Bot (MiniMax avec Alpha-Beta)\n");
|
||||
|
||||
// Boucle de jeu
|
||||
while (!plateau.isGameOver()) {
|
||||
// Obtenir le coup du joueur actif
|
||||
AbstractPly coup;
|
||||
if (plateau.getcurrentPlayer() == Player.PLAYER1) {
|
||||
coup = joueur1.giveYourMove(plateau);
|
||||
} else {
|
||||
coup = joueur2.giveYourMove(plateau);
|
||||
}
|
||||
|
||||
// Jouer le coup
|
||||
plateau.doPly(coup);
|
||||
|
||||
System.out.println("\n>>> " + coup);
|
||||
}
|
||||
|
||||
// Afficher le résultat
|
||||
System.out.println("\n=== Fin de la partie ===");
|
||||
System.out.println(plateau);
|
||||
|
||||
// Déterminer le gagnant en utilisant l'enum Result
|
||||
if (plateau.getResult() == fr.iut_fbleau.GameAPI.Result.WIN) {
|
||||
System.out.println("Le PLAYER1 a gagné !");
|
||||
} else if (plateau.getResult() == fr.iut_fbleau.GameAPI.Result.LOSS) {
|
||||
System.out.println("Le PLAYER2 (Bot) a gagné !");
|
||||
} else {
|
||||
System.out.println("Match nul !");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
BIN
TP3/fr/iut_fbleau/Nim/NimPlayer.class
Normal file
BIN
TP3/fr/iut_fbleau/Nim/NimPlayer.class
Normal file
Binary file not shown.
66
TP3/fr/iut_fbleau/Nim/NimPlayer.java
Normal file
66
TP3/fr/iut_fbleau/Nim/NimPlayer.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package fr.iut_fbleau.Nim;
|
||||
|
||||
import fr.iut_fbleau.GameAPI.AbstractGamePlayer;
|
||||
import fr.iut_fbleau.GameAPI.AbstractPly;
|
||||
import fr.iut_fbleau.GameAPI.IBoard;
|
||||
import fr.iut_fbleau.GameAPI.Player;
|
||||
|
||||
import java.util.Scanner;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Représente un joueur humain pour le jeu de Nim.
|
||||
*/
|
||||
public class NimPlayer extends AbstractGamePlayer {
|
||||
|
||||
private Player joueur;
|
||||
private Scanner scanner;
|
||||
|
||||
public NimPlayer(Player joueur) {
|
||||
this.joueur = joueur;
|
||||
this.scanner = new Scanner(System.in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractPly giveYourMove(IBoard p) {
|
||||
if (!(p instanceof NimBoard)) {
|
||||
throw new IllegalArgumentException("Le plateau doit être un NimBoard");
|
||||
}
|
||||
|
||||
NimBoard plateau = (NimBoard) p;
|
||||
|
||||
System.out.println("\n" + plateau);
|
||||
System.out.println("C'est ton tour joueur : " + this.joueur);
|
||||
|
||||
// Afficher les coups possibles
|
||||
System.out.println("Coups possibles :");
|
||||
Iterator<AbstractPly> coups = plateau.iterator();
|
||||
int compteur = 1;
|
||||
while (coups.hasNext()) {
|
||||
NimPly coup = (NimPly) coups.next();
|
||||
System.out.println(" " + compteur + ". Retirer " + coup.getNombreAllumettesPrises() + " allumette(s)");
|
||||
compteur++;
|
||||
}
|
||||
|
||||
// Demander au joueur de choisir
|
||||
int maxAllumettes = Math.min(plateau.getMaxParCoup(), plateau.getAllumettesRestantes());
|
||||
int choix = -1;
|
||||
|
||||
while (choix < 1 || choix > maxAllumettes) {
|
||||
System.out.print("Combien d'allumettes voulez-vous retirer ? (1-" + maxAllumettes + ") : ");
|
||||
try {
|
||||
choix = scanner.nextInt();
|
||||
if (choix < 1 || choix > maxAllumettes) {
|
||||
System.out.println("Choix invalide. Veuillez choisir entre 1 et " + maxAllumettes);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Entrée invalide. Veuillez entrer un nombre.");
|
||||
scanner.nextLine(); // vider le buffer
|
||||
}
|
||||
}
|
||||
|
||||
return new NimPly(this.joueur, choix);
|
||||
}
|
||||
}
|
||||
|
||||
|
BIN
TP3/fr/iut_fbleau/Nim/NimPly.class
Normal file
BIN
TP3/fr/iut_fbleau/Nim/NimPly.class
Normal file
Binary file not shown.
38
TP3/fr/iut_fbleau/Nim/NimPly.java
Normal file
38
TP3/fr/iut_fbleau/Nim/NimPly.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package fr.iut_fbleau.Nim;
|
||||
|
||||
import fr.iut_fbleau.GameAPI.AbstractPly;
|
||||
import fr.iut_fbleau.GameAPI.Player;
|
||||
|
||||
/**
|
||||
* Représente un coup dans le jeu de Nim.
|
||||
* Un coup consiste à retirer un certain nombre d'allumettes.
|
||||
*/
|
||||
public class NimPly extends AbstractPly {
|
||||
|
||||
private Player joueur;
|
||||
private int nombreAllumettesPrises;
|
||||
|
||||
public NimPly(Player joueur, int nombreAllumettesPrises) {
|
||||
this.joueur = joueur;
|
||||
this.nombreAllumettesPrises = nombreAllumettesPrises;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return le joueur qui effectue le coup
|
||||
*/
|
||||
public Player getJoueur() {
|
||||
return this.joueur;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return le nombre d'allumettes prises
|
||||
*/
|
||||
public int getNombreAllumettesPrises() {
|
||||
return this.nombreAllumettesPrises;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Joueur " + joueur + " retire " + nombreAllumettesPrises + " allumette(s)";
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user