199 lines
5.8 KiB
Java
199 lines
5.8 KiB
Java
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();
|
|
}
|
|
}
|