remove static methods

This commit is contained in:
cleme 2025-04-23 12:49:21 +02:00
parent c1210f2141
commit 2133960585
4 changed files with 133 additions and 214 deletions

View File

@ -97,7 +97,10 @@ public class Board {
private void setHighlightedPositions(Piece piece) { private void setHighlightedPositions(Piece piece) {
this.highlightedPositions.clear(); this.highlightedPositions.clear();
if (piece != null) { if (piece != null) {
Set<String> validMoves = Move.calculateValidMoves(this, piece); // Create a temporary Move object to call calculateValidMoves
// We can use dummy coordinates and null for pieceCaptured since they aren't used in calculateValidMoves
Move tempMove = new Move(0, 0, 0, 0, piece, null);
Set<String> validMoves = tempMove.calculateValidMoves(this, piece);
this.highlightedPositions.addAll(validMoves); this.highlightedPositions.addAll(validMoves);
} }
} }

View File

@ -1,35 +1,22 @@
package backend; package backend;
import windowInterface.MyInterface; // Assurez-vous que ce chemin d'importation est correct import windowInterface.MyInterface;
/**
* Représente la logique principale du jeu d'échecs.
* Gère l'état du plateau (Board), les joueurs (humain/IA), le déroulement des tours,
* et interagit avec l'interface utilisateur (MyInterface).
* Fonctionne dans un thread séparé pour permettre le jeu de l'IA sans bloquer l'UI.
*/
public class Game extends Thread { public class Game extends Thread {
// Dépendances private final Board board;
private final Board board; // L'état actuel de l'échiquier (final car l'instance Board ne change pas, seul son état interne) private final AutoPlayer aiPlayer;
private final AutoPlayer aiPlayer; // Le moteur d'IA private final MyInterface mjf;
private final MyInterface mjf; // Référence à l'interface graphique pour les mises à jour
// Constantes de configuration
private static final int DEFAULT_WIDTH = 8; private static final int DEFAULT_WIDTH = 8;
private static final int DEFAULT_HEIGHT = 8; private static final int DEFAULT_HEIGHT = 8;
private static final int DEFAULT_LOOP_DELAY = 250; // ms entre les vérifications de l'IA private static final int DEFAULT_LOOP_DELAY = 250;
// État de contrôle du jeu private int loopDelay;
private int loopDelay; // Délai actuel de la boucle (peut être modifié)
private final boolean[] activationAIFlags; // Index 0 pour Noir (isWhite=false), Index 1 pour Blanc (isWhite=true) private final boolean[] activationAIFlags; // Index 0 pour Noir (isWhite=false), Index 1 pour Blanc (isWhite=true)
/**
* Constructeur de la partie.
* Initialise le plateau, l'IA, les flags de contrôle et la configuration initiale.
*
* @param mjfParam Référence à l'interface graphique pour pouvoir la mettre à jour. Doit être non-null.
*/
public Game(MyInterface mjfParam) { public Game(MyInterface mjfParam) {
if (mjfParam == null) { if (mjfParam == null) {
throw new IllegalArgumentException("MyInterface parameter cannot be null."); throw new IllegalArgumentException("MyInterface parameter cannot be null.");
@ -49,197 +36,131 @@ public class Game extends Thread {
System.out.println(this.board.toString()); System.out.println(this.board.toString());
} }
// --- Getters délégués au Board ---
/** @return La largeur du plateau. */
public int getWidth() { public int getWidth() {
return board.getWidth(); return board.getWidth();
} }
/** @return La hauteur du plateau. */ public int getHeight() {
public int getHeight() {
return board.getHeight(); return board.getHeight();
} }
/**
* @return Une collection itérable des pièces actuellement sur le plateau.
* Renvoie une copie pour éviter les modifications externes non contrôlées.
*/
public Iterable<Piece> getPieces() { public Iterable<Piece> getPieces() {
return board.getPieces(); return board.getPieces();
} }
/**
* Vérifie si la case (x, y) correspond à la pièce actuellement sélectionnée.
* @param x Coordonnée x.
* @param y Coordonnée y.
* @return true si la pièce à (x,y) est sélectionnée, false sinon.
*/
public boolean isSelected(int x, int y) { public boolean isSelected(int x, int y) {
return board.isSelected(x, y); return board.isSelected(x, y);
} }
/**
* Vérifie si la case (x, y) est mise en surbrillance comme destination possible.
* @param x Coordonnée x.
* @param y Coordonnée y.
* @return true si la case (x,y) est en surbrillance, false sinon.
*/
public boolean isHighlighted(int x, int y) { public boolean isHighlighted(int x, int y) {
return board.isHighlighted(x, y); return board.isHighlighted(x, y);
} }
/** @return true si c'est le tour des blancs, false si c'est le tour des noirs. */ //return true si c'est le tour des blancs, false si c'est le tour des noirs.
public boolean isWhiteTurn() { public boolean isWhiteTurn() {
return board.isTurnWhite(); return board.isTurnWhite();
} }
/** @return Le numéro du tour actuel (commence à 0 ou 1 selon l'implémentation de Board). */
public int getTurnNumber() { public int getTurnNumber() {
return board.getTurnNumber(); return board.getTurnNumber();
} }
// --- Logique principale du Thread ---
/**
* Boucle principale du jeu exécutée dans le thread.
* Vérifie périodiquement si c'est au tour de l'IA de jouer,
* met à jour l'interface graphique et attend.
*/
@Override
public void run() { public void run() {
System.out.println("Game thread started."); System.out.println("Game thread started.");
while (!Thread.currentThread().isInterrupted()) { // Continue tant que le thread n'est pas interrompu while (!Thread.currentThread().isInterrupted()) {
try { try {
// 1. Gérer le tour de l'IA si applicable
aiPlayerTurn(); aiPlayerTurn();
// 2. Mettre à jour l'interface graphique
// (Numéro de tour, à qui le tour, et potentiellement repaint)
// On le fait à chaque itération pour refléter l'état même si aucun coup n'est joué.
mjf.update(board.getTurnNumber(), board.isTurnWhite()); mjf.update(board.getTurnNumber(), board.isTurnWhite());
// Note: mjf.update() devrait idéalement déclencher un repaint dans l'UI.
// 3. Pause avant la prochaine vérification
Thread.sleep(loopDelay); Thread.sleep(loopDelay);
} catch (InterruptedException e) { } catch (InterruptedException e) {
System.err.println("Game thread interrupted during sleep or operation."); System.err.println("Game thread interrupted during sleep or operation.");
Thread.currentThread().interrupt(); // Important: Rétablir le statut d'interruption Thread.currentThread().interrupt();
// Sortir de la boucle car le thread doit s'arrêter
} catch (Exception e) { } catch (Exception e) {
// Capturer d'autres exceptions pour la robustesse
System.err.println("Unexpected error in game loop: " + e.getMessage()); System.err.println("Unexpected error in game loop: " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
// Optionnel : Mettre une pause plus longue pour éviter de spammer les logs en cas d'erreur répétée
try { Thread.sleep(5000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } try { Thread.sleep(5000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); }
} }
} }
System.out.println("Game thread finished."); System.out.println("Game thread finished.");
} }
/**
* Vérifie si le joueur dont c'est le tour est actuellement contrôlé par l'IA.
*
* @return true si c'est le tour de l'IA, false si c'est un tour humain.
*/
private boolean isAITurn() { private boolean isAITurn() {
int playerIndex = board.isTurnWhite() ? 1 : 0; // 1 pour Blanc, 0 pour Noir int playerIndex = board.isTurnWhite() ? 1 : 0; // 1 pour Blanc, 0 pour Noir
return activationAIFlags[playerIndex]; return activationAIFlags[playerIndex];
} }
/**
* Si c'est le tour de l'IA, lui demande de calculer un coup et le joue sur le plateau.
*/
private void aiPlayerTurn() { private void aiPlayerTurn() {
if (isAITurn()) { if (isAITurn()) {
String colorTurn = board.isTurnWhite() ? "White" : "Black"; String colorTurn = board.isTurnWhite() ? "White" : "Black";
System.out.println("AI's turn (" + colorTurn + "). Computing move..."); System.out.println("AI's turn (" + colorTurn + "). Computing move...");
// Créer une copie *indépendante* du plateau pour l'analyse par l'IA.
// Ceci est crucial pour que l'IA puisse explorer des coups sans modifier l'état réel du jeu. Board boardCopy = new Board(board);
Board boardCopy = new Board(board); // Utilise le constructeur de copie de Board
// Demander à l'IA de calculer le meilleur coup sur la copie
Move bestMove = aiPlayer.computeBestMove(boardCopy); Move bestMove = aiPlayer.computeBestMove(boardCopy);
// Si l'IA retourne un coup (elle n'est pas échec et mat ou pat)
if (bestMove != null) { if (bestMove != null) {
System.out.println("AI computed move: " + bestMove.getPieceMoved().getType() + System.out.println("AI computed move: " + bestMove.getPieceMoved().getType() +
" from (" + bestMove.getFromX() + "," + bestMove.getFromY() + " from (" + bestMove.getFromX() + "," + bestMove.getFromY() +
") to (" + bestMove.getToX() + "," + bestMove.getToY() + ")"); ") to (" + bestMove.getToX() + "," + bestMove.getToY() + ")");
// Jouer le coup sur le plateau *principal*
board.playMove(bestMove); board.playMove(bestMove);
// playMove met à jour l'état interne du board (pièces, tour, etc.)
// L'UI sera mise à jour à la prochaine itération de run()
} else { } else {
// L'IA n'a trouvé aucun coup (peut indiquer échec et mat, pat, ou une erreur)
System.err.println("AI returned null move! Possible stalemate, checkmate, or error in AI for " + colorTurn + "."); System.err.println("AI returned null move! Possible stalemate, checkmate, or error in AI for " + colorTurn + ".");
// Optionnel: Désactiver l'IA ou afficher un message de fin de partie.
// Pour l'instant, le jeu continue (ou se bloque si c'est vraiment mat/pat).
} }
} }
} }
// --- Gestion des interactions utilisateur ---
/**
* Gère un clic de l'utilisateur sur la case (x, y) de l'échiquier.
* Vérifie si le clic est dans les limites et si ce n'est pas au tour de l'IA.
* Si les conditions sont remplies, délègue toute la logique d'interaction
* (sélection, désélection, déplacement) à la méthode `userTouch` du `Board`.
*
* @param x Coordonnée x (colonne) de la case cliquée.
* @param y Coordonnée y (ligne) de la case cliquée.
*/
public void clickCoords(int x, int y) { public void clickCoords(int x, int y) {
// System.out.println("Game received click at (" + x + "," + y + ")"); // Debug
// 1. Ignorer si clic hors limites
if (x < 0 || x >= getWidth() || y < 0 || y >= getHeight()) { if (x < 0 || x >= getWidth() || y < 0 || y >= getHeight()) {
System.out.println("Click ignored: out of bounds."); System.out.println("Click ignored: out of bounds.");
return; return;
} }
// 2. Ignorer si c'est le tour de l'IA (le joueur humain ne peut pas interagir)
if (isAITurn()) { if (isAITurn()) {
System.out.println("Click ignored: AI's turn."); System.out.println("Click ignored: AI's turn.");
return; return;
} }
// 3. Si c'est un tour humain et clic dans les limites, déléguer au Board
// Board.userTouch gère la sélection, la mise en surbrillance, la désélection et le jeu du coup.
board.userTouch(x, y); board.userTouch(x, y);
// L'état du jeu (sélection, highlights, pièces) peut avoir changé.
// La boucle `run` mettra à jour l'interface graphique.
// Si une mise à jour VISUELLE immédiate est cruciale après chaque clic humain :
// mjf.update(board.getTurnNumber(), board.isTurnWhite()); // Forcer update + repaint
} }
// --- Méthodes de Contrôle et Configuration ---
/**
* Active ou désactive l'IA pour la couleur spécifiée.
*
* @param isWhite true pour contrôler l'IA blanche, false pour l'IA noire.
*/
public void toggleAI(boolean isWhite) { public void toggleAI(boolean isWhite) {
int playerIndex = isWhite ? 1 : 0; int playerIndex = isWhite ? 1 : 0;
activationAIFlags[playerIndex] = !activationAIFlags[playerIndex]; // Bascule l'état activationAIFlags[playerIndex] = !activationAIFlags[playerIndex]; // Bascule l'état
String color = isWhite ? "White" : "Black"; String color = isWhite ? "White" : "Black";
String status = activationAIFlags[playerIndex] ? "enabled" : "disabled"; String status = activationAIFlags[playerIndex] ? "enabled" : "disabled";
System.out.println("AI for " + color + " player is now " + status + "."); System.out.println("AI for " + color + " player is now " + status + ".");
// Si on active l'IA et que c'est son tour, elle jouera à la prochaine itération de run()
} }
/**
* Modifie le délai (en millisecondes) entre les itérations de la boucle du thread.
* Un délai plus court rend l'IA plus réactive (si elle calcule vite),
* un délai plus long économise des ressources CPU.
*
* @param delay Le nouveau délai en millisecondes (doit être positif).
*/
public void setLoopDelay(int delay) { public void setLoopDelay(int delay) {
if (delay > 0) { if (delay > 0) {
this.loopDelay = delay; this.loopDelay = delay;
@ -249,10 +170,7 @@ public class Game extends Thread {
} }
} }
/**
* Réinitialise le plateau à la configuration de départ standard des échecs.
* Efface l'état actuel et remet les pièces à leur place initiale.
*/
public void setDefaultSetup() { public void setDefaultSetup() {
System.out.println("Setting default board setup..."); System.out.println("Setting default board setup...");
board.cleanBoard(); // Nettoie le plateau (pièces, sélection, highlights, tour) board.cleanBoard(); // Nettoie le plateau (pièces, sélection, highlights, tour)
@ -263,90 +181,51 @@ public class Game extends Thread {
mjf.update(board.getTurnNumber(), board.isTurnWhite()); mjf.update(board.getTurnNumber(), board.isTurnWhite());
} }
// --- Méthodes déléguées au Board (pour manipulation externe, sauvegarde/chargement, etc.) ---
/**
* Place directement une pièce sur le plateau.
* Attention : Utiliser principalement pour le débogage ou la mise en place de positions spécifiques.
* Écrase toute pièce existante à cet endroit.
*
* @param isWhite Couleur de la pièce (true=blanc).
* @param type Type de la pièce (Pawn, Rook...).
* @param x Coordonnée x.
* @param y Coordonnée y.
*/
public void setPiece(boolean isWhite, PieceType type, int x, int y) { public void setPiece(boolean isWhite, PieceType type, int x, int y) {
board.setPiece(isWhite, type, x, y); board.setPiece(isWhite, type, x, y);
// Mettre à jour l'interface pour voir le changement
mjf.update(board.getTurnNumber(), board.isTurnWhite()); mjf.update(board.getTurnNumber(), board.isTurnWhite());
} }
/**
* Récupère une représentation du plateau sous forme de tableau de chaînes de caractères.
* Utile pour la sauvegarde ou le débogage.
* (Nécessite que la méthode `toFileRep` soit implémentée dans la classe Board).
*
* @return Un tableau de String représentant l'état du plateau, ou null si non supporté.
*/
public String[] getFileRepresentation() { public String[] getFileRepresentation() {
// TODO: Implémenter Board.toFileRep() pour que cela fonctionne.
System.out.println("Getting file representation from board..."); System.out.println("Getting file representation from board...");
return board.toFileRep(); return board.toFileRep();
} }
/**
* Configure l'état du plateau à partir d'une représentation sous forme de tableau de chaînes.
* Remplace complètement l'état actuel du plateau.
* (Nécessite que le constructeur `Board(String[] array)` soit implémenté).
*
* @param boardData Le tableau de String décrivant le nouvel état du plateau.
*/
public void setBoard(String[] boardData) { public void setBoard(String[] boardData) {
System.out.println("Setting board state from string array..."); System.out.println("Setting board state from string array...");
// TODO: Implémenter le constructeur Board(String[] array) pour que cela fonctionne.
// Ceci remplacera l'instance actuelle du board ou modifiera son état interne.
// Si on remplace l'instance, il faut s'assurer que la référence 'board' est mise à jour.
// Exemple (si le constructeur existe) :
// this.board = new Board(boardData);
try { try {
// Tentative de créer un nouveau board (si le constructeur existe)
// Note: Ceci ne fonctionnera que si 'board' n'est PAS final.
// Si 'board' est final, il faudrait une méthode dans Board pour charger l'état.
// Exemple: this.board.loadFromArray(boardData);
System.err.println("setBoard(String[]) is not fully implemented yet (requires Board constructor or load method)."); System.err.println("setBoard(String[]) is not fully implemented yet (requires Board constructor or load method).");
// Pour l'instant, on ne fait rien pour éviter une erreur si Board(String[]) n'existe pas
// this.board = new Board(boardData);
} catch (Exception e) { } catch (Exception e) {
System.err.println("Failed to set board from string array: " + e.getMessage()); System.err.println("Failed to set board from string array: " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
} }
// Dans tous les cas, mettre à jour l'interface
mjf.update(this.board.getTurnNumber(), this.board.isTurnWhite()); mjf.update(this.board.getTurnNumber(), this.board.isTurnWhite());
} }
/**
* Tente d'annuler le dernier coup joué.
* La possibilité d'annuler dépend de si le `Board` gère un historique des coups.
* (Nécessite que la méthode `undoLastMove` soit implémentée dans la classe Board).
*/
public void undoLastMove() { public void undoLastMove() {
// Optionnel: Ajouter une logique pour empêcher l'annulation pendant le tour de l'IA
// if (isAITurn()) {
// System.out.println("Undo ignored: AI is thinking or has just played.");
// return;
// }
System.out.println("Requesting undo last move..."); System.out.println("Requesting undo last move...");
// TODO: Implémenter Board.undoLastMove() pour que cela fonctionne. // TODO:
boolean success = board.undoLastMove(); // Supposons que undoLastMove renvoie un booléen boolean success = board.undoLastMove();
if (success) { if (success) {
System.out.println("Last move undone successfully."); System.out.println("Last move undone successfully.");
System.out.println(this.board.toString()); // Afficher le nouvel état System.out.println(this.board.toString());
} else { } else {
System.out.println("Undo failed (no history or cannot undo)."); System.out.println("Undo failed (no history or cannot undo).");
} }
// Mettre à jour l'interface quelle que soit l'issue
mjf.update(board.getTurnNumber(), board.isTurnWhite()); mjf.update(board.getTurnNumber(), board.isTurnWhite());
} }

View File

@ -17,7 +17,7 @@ public class Move {
this.toX = toX; this.toX = toX;
this.toY = toY; this.toY = toY;
if (pieceMoved == null) { if (pieceMoved == null) {
throw new IllegalArgumentException("pieceMoved cannot be null in a Move."); throw new IllegalArgumentException("pieceMoved cannot be null in a Move.");
} }
this.pieceMoved = pieceMoved; this.pieceMoved = pieceMoved;
this.pieceCaptured = pieceCaptured; this.pieceCaptured = pieceCaptured;
@ -30,7 +30,7 @@ public class Move {
public Piece getPieceMoved() { return pieceMoved; } public Piece getPieceMoved() { return pieceMoved; }
public Piece getPieceCaptured() { return pieceCaptured; } public Piece getPieceCaptured() { return pieceCaptured; }
public static Set<String> calculateValidMoves(Board board, Piece piece) { public Set<String> calculateValidMoves(Board board, Piece piece) {
Set<String> validMoves = new HashSet<>(); Set<String> validMoves = new HashSet<>();
if (piece == null || board == null) { if (piece == null || board == null) {
@ -64,19 +64,19 @@ public class Move {
return validMoves; return validMoves;
} }
private static void addMove(int x, int y, Set<String> moves) { private void addMove(int x, int y, Set<String> moves) {
moves.add(x + "," + y); moves.add(x + "," + y);
} }
static boolean isValidPosition(Board board, int x, int y) { boolean isValidPosition(Board board, int x, int y) {
return x >= 0 && x < board.getWidth() && y >= 0 && y < board.getHeight(); return x >= 0 && x < board.getWidth() && y >= 0 && y < board.getHeight();
} }
private static Piece getPieceAt(Board board, int x, int y) { private Piece getPieceAt(Board board, int x, int y) {
return board.getPieceAt(x, y); return board.getPieceAt(x, y);
} }
private static void calculateSlidingMoves(Board board, Piece piece, int x, int y, Set<String> validMoves, int[][] directions) { private void calculateSlidingMoves(Board board, Piece piece, int x, int y, Set<String> validMoves, int[][] directions) {
for (int[] dir : directions) { for (int[] dir : directions) {
int dx = dir[0]; int dx = dir[0];
int dy = dir[1]; int dy = dir[1];
@ -102,7 +102,7 @@ public class Move {
} }
} }
private static void calculatePawnMoves(Board board, Piece piece, int x, int y, Set<String> validMoves) { private void calculatePawnMoves(Board board, Piece piece, int x, int y, Set<String> validMoves) {
int forwardDirection = piece.isWhite() ? -1 : 1; int forwardDirection = piece.isWhite() ? -1 : 1;
int startRow = piece.isWhite() ? 6 : 1; int startRow = piece.isWhite() ? 6 : 1;
@ -129,27 +129,27 @@ public class Move {
} }
} }
// V<>rifier la capture en passant // Vérifier la capture en passant
int enPassantTargetX = board.getEnPassantTargetX(); int enPassantTargetX = board.getEnPassantTargetX();
int enPassantTargetY = board.getEnPassantTargetY(); int enPassantTargetY = board.getEnPassantTargetY();
if (enPassantTargetX != -1 && enPassantTargetY != -1) { // Si une cible EP existe if (enPassantTargetX != -1 && enPassantTargetY != -1) { // Si une cible EP existe
// V<>rifier si la cible est sur la case diagonale avant // Vérifier si la cible est sur la case diagonale avant
if (enPassantTargetY == oneStepY) { // La cible doit <20>tre sur la rang<6E>e devant le pion if (enPassantTargetY == oneStepY) { // La cible doit être sur la rangée devant le pion
if (Math.abs(x - enPassantTargetX) == 1) { // La cible doit <20>tre sur une colonne adjacente if (Math.abs(x - enPassantTargetX) == 1) { // La cible doit être sur une colonne adjacente
// V<>rifier qu'il y a bien un pion adverse <20> capturer <20> c<>t<EFBFBD> de nous (sur la case EP virtuelle) // rifier qu'il y a bien un pion adverse à capturer à côté de nous (sur la case EP virtuelle)
// Le pion <20> capturer est sur (enPassantTargetX, y) // Le pion à capturer est sur (enPassantTargetX, y)
Piece adjacentPawn = getPieceAt(board, enPassantTargetX, y); Piece adjacentPawn = getPieceAt(board, enPassantTargetX, y);
if (adjacentPawn != null && adjacentPawn.getType() == PieceType.Pawn && adjacentPawn.isWhite() != piece.isWhite()) { if (adjacentPawn != null && adjacentPawn.getType() == PieceType.Pawn && adjacentPawn.isWhite() != piece.isWhite()) {
addMove(enPassantTargetX, enPassantTargetY, validMoves); addMove(enPassantTargetX, enPassantTargetY, validMoves);
System.out.println("En passant move calculated for pawn at ("+x+","+y+") to ("+enPassantTargetX+","+enPassantTargetY+")"); // Debug System.out.println("En passant move calculated for pawn at ("+x+","+y+") to ("+enPassantTargetX+","+enPassantTargetY+")"); // Debug
} }
} }
} }
} }
} }
private static void calculateKnightMoves(Board board, Piece piece, int x, int y, Set<String> validMoves) { private void calculateKnightMoves(Board board, Piece piece, int x, int y, Set<String> validMoves) {
int[][] knightMoves = { int[][] knightMoves = {
{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2}, {-2, -1}, {-2, 1}, {-1, -2}, {-1, 2},
{1, -2}, {1, 2}, {2, -1}, {2, 1} {1, -2}, {1, 2}, {2, -1}, {2, 1}
@ -166,7 +166,7 @@ public class Move {
} }
} }
private static void calculateKingMoves(Board board, Piece piece, int x, int y, Set<String> validMoves) { private void calculateKingMoves(Board board, Piece piece, int x, int y, Set<String> validMoves) {
for (int dx = -1; dx <= 1; dx++) { for (int dx = -1; dx <= 1; dx++) {
for (int dy = -1; dy <= 1; dy++) { for (int dy = -1; dy <= 1; dy++) {
if (dx == 0 && dy == 0) continue; if (dx == 0 && dy == 0) continue;
@ -183,42 +183,77 @@ public class Move {
} }
} }
// Ajouter calcul du roque ici // Ajouter calcul du roque ici
calculateCastlingMoves(board, piece, x, y, validMoves); calculateCastlingMoves1(board, piece, x, y, validMoves);
} }
private static void calculateCastlingMoves(Board board, Piece piece, int x, int y, Set<String> validMoves) { private void calculateCastlingMoves1(Board board, Piece piece, int x, int y, Set<String> validMoves) {
if (piece.getType() != PieceType.King || piece.hasMoved()) { if (piece.getType() != PieceType.King || piece.hasMoved()) {
return; return;
} }
// Roque c<>t<EFBFBD> roi // Roque côté roi
if (canCastleKingside(board, piece, x, y)) { if (canCastleKingside(board, piece, x, y)) {
addMove(x + 2, y, validMoves); addMove(x + 2, y, validMoves);
} }
// Roque c<>t<EFBFBD> dame // Roque côté dame
if (canCastleQueenside(board, piece, x, y)) { if (canCastleQueenside(board, piece, x, y)) {
addMove(x - 2, y, validMoves); addMove(x - 2, y, validMoves);
} }
} }
private static boolean canCastleKingside(Board board, Piece king, int x, int y) { private void calculateCastlingMoves(Board board, Piece piece, int x, int y, Set<String> validMoves) {
// Castling is only possible for a king
if (piece.getType() != PieceType.King) {
return;
}
// The king must not have moved
if (piece.hasMoved()) {
return;
}
// Roque côté roi (kingside castling)
if (canCastleKingside(board, piece, x, y)) {
addMove(x + 2, y, validMoves);
}
// Roque côté dame (queenside castling)
if (canCastleQueenside(board, piece, x, y)) {
addMove(x - 2, y, validMoves);
}
}
private boolean canCastleKingside(Board board, Piece king, int x, int y) {
Piece rook = board.getPieceAt(x + 3, y); Piece rook = board.getPieceAt(x + 3, y);
return rook != null && rook.getType() == PieceType.Rook && !rook.hasMoved() && // The rook must exist, be a rook, and not have moved
board.getPieceAt(x + 1, y) == null && board.getPieceAt(x + 2, y) == null && // The squares between the king and rook must be empty
// The king must not be in check
return rook != null &&
rook.getType() == PieceType.Rook &&
!rook.hasMoved() &&
board.getPieceAt(x + 1, y) == null &&
board.getPieceAt(x + 2, y) == null &&
!isKingInCheck(board, king.isWhite()); !isKingInCheck(board, king.isWhite());
} }
private static boolean canCastleQueenside(Board board, Piece king, int x, int y) { private boolean canCastleQueenside(Board board, Piece king, int x, int y) {
Piece rook = board.getPieceAt(x - 4, y); Piece rook = board.getPieceAt(x - 4, y);
return rook != null && rook.getType() == PieceType.Rook && !rook.hasMoved() && // The rook must exist, be a rook, and not have moved
board.getPieceAt(x - 1, y) == null && board.getPieceAt(x - 2, y) == null && board.getPieceAt(x - 3, y) == null && // The squares between the king and rook must be empty
// The king must not be in check
return rook != null &&
rook.getType() == PieceType.Rook &&
!rook.hasMoved() &&
board.getPieceAt(x - 1, y) == null &&
board.getPieceAt(x - 2, y) == null &&
board.getPieceAt(x - 3, y) == null &&
!isKingInCheck(board, king.isWhite()); !isKingInCheck(board, king.isWhite());
} }
private static boolean isKingInCheck(Board board, boolean isWhite) { private boolean isKingInCheck(Board board, boolean isWhite) {
// Impl<70>mentez la logique pour v<>rifier si le roi est en <20>chec // Implémentez la logique pour rifier si le roi est en échec
// Cela n<>cessite de v<>rifier tous les mouvements possibles des pi<70>ces adverses // Cela nécessite de rifier tous les mouvements possibles des pièces adverses
return false; return false;
} }
@ -230,4 +265,4 @@ public class Move {
"-" + captureStr + "-" + captureStr +
"(" + toX + "," + toY + ")"; "(" + toX + "," + toY + ")";
} }
} }

View File

@ -38,12 +38,14 @@ public class Piece {
public boolean canMoveTo(int toX, int toY, Board board) { public boolean canMoveTo(int toX, int toY, Board board) {
if (board == null) return false; if (board == null) return false;
if (this.x == toX && this.y == toY) return false; if (this.x == toX && this.y == toY) return false;
if (!Move.isValidPosition(board, toX, toY)) return false; // Create a temporary Move object to call isValidPosition
Move tempMove = new Move(this.x, this.y, toX, toY, this, null);
if (!tempMove.isValidPosition(board, toX, toY)) return false;
Piece pieceAtDestination = board.getPieceAt(toX, toY); Piece pieceAtDestination = board.getPieceAt(toX, toY);
if (pieceAtDestination != null && pieceAtDestination.isWhite() == this.isWhite) { if (pieceAtDestination != null && pieceAtDestination.isWhite() == this.isWhite) {
return false; return false;
} }
int dx = Math.abs(toX - this.x); int dx = Math.abs(toX - this.x);
@ -63,7 +65,7 @@ public class Piece {
case King: case King:
return dx <= 1 && dy <= 1; return dx <= 1 && dy <= 1;
default: default:
System.err.println("Erreur: Type de pi<70>ce inconnu dans canMoveTo: " + this.type); System.err.println("Erreur: Type de pièce inconnu dans canMoveTo: " + this.type);
return false; return false;
} }
} }