167 lines
5.0 KiB
Java
167 lines
5.0 KiB
Java
![]() |
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;
|
||
|
}
|
||
|
}
|
||
|
|