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 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 iterator() { if (this.gameOver) { throw new NullPointerException("Le jeu est terminé"); } ArrayList 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(); } }