From cdbba67bc56242322eb342ad77b222aaccf17670 Mon Sep 17 00:00:00 2001 From: clement Date: Mon, 19 May 2025 18:01:03 +0200 Subject: [PATCH] En passant --- OOP_2B6_PROJECT/src/backend/Board.java | 127 +++++++++++++++++++------ OOP_2B6_PROJECT/src/backend/Move.java | 22 +++++ 2 files changed, 119 insertions(+), 30 deletions(-) diff --git a/OOP_2B6_PROJECT/src/backend/Board.java b/OOP_2B6_PROJECT/src/backend/Board.java index b821f86..a05e8f2 100644 --- a/OOP_2B6_PROJECT/src/backend/Board.java +++ b/OOP_2B6_PROJECT/src/backend/Board.java @@ -18,15 +18,18 @@ public class Board { private Stack moveHistory = new Stack<>(); + // EN PASSANT + private Integer enPassantX = null; + private Integer enPassantY = null; + public Board(int colNum, int lineNum) { this.width = colNum; this.height = lineNum; this.pieces = new ArrayList<>(); + this.enPassantX = null; + this.enPassantY = null; } - /** - * Constructeur de copie : clone l'état du plateau - */ public Board(Board other) { this.width = other.width; this.height = other.height; @@ -42,6 +45,8 @@ public class Board { this.highlightedPositions = new ArrayList<>(other.highlightedPositions); this.moveHistory = new Stack<>(); this.moveHistory.addAll(other.moveHistory); + this.enPassantX = other.enPassantX; + this.enPassantY = other.enPassantY; } public Board(String[] array) { @@ -59,6 +64,8 @@ public class Board { } } turnIsWhite = array[8].equalsIgnoreCase("W"); + this.enPassantX = null; + this.enPassantY = null; } public int getWidth() { return width; } @@ -66,6 +73,8 @@ public class Board { public int getTurnNumber() { return turnNumber; } public boolean isTurnWhite() { return turnIsWhite; } public boolean isGameOver() { return gameOver; } + public Integer getEnPassantX() { return enPassantX; } + public Integer getEnPassantY() { return enPassantY; } public void setPiece(boolean isWhite, PieceType type, int x, int y) { pieces.removeIf(p -> p.getX() == x && p.getY() == y); @@ -93,6 +102,8 @@ public class Board { setPiece(false, PieceType.Knight, 6, 0); setPiece(false, PieceType.Rook, 7, 0); for (int x = 0; x < 8; x++) setPiece(false, PieceType.Pawn, x, 1); + this.enPassantX = null; + this.enPassantY = null; } public void cleanBoard() { @@ -102,6 +113,8 @@ public class Board { highlightedPositions.clear(); moveHistory.clear(); gameOver = false; + enPassantX = null; + enPassantY = null; } public ArrayList getPieces() { return pieces; } @@ -130,34 +143,59 @@ public class Board { simulation.pieces.removeIf(p -> p.getX() == selectedX && p.getY() == selectedY); simulation.pieces.removeIf(p -> p.getX() == x && p.getY() == y); simulation.pieces.add(new Piece( - selectedPiece.isWhite(), - selectedPiece.getType(), - x, y + selectedPiece.isWhite(), + selectedPiece.getType(), + x, y )); if (!simulation.isKingInCheck(turnIsWhite)) { Piece target = getPieceAt(x, y); + + // EN PASSANT (avant la capture normale) + boolean enPassantMove = false; + if (selectedPiece.getType() == PieceType.Pawn + && getEnPassantX() != null && getEnPassantY() != null + && x == getEnPassantX() && y == getEnPassantY() + && target == null + && selectedX != x) { + // On va prendre en passant + enPassantMove = true; + int capturedY = turnIsWhite ? y + 1 : y - 1; + pieces.removeIf(p -> p.getX() == x && p.getY() == capturedY); + target = getPieceAt(x, capturedY); // Pour le move history + } + // Si on cible le roi adverse, c'est un cas de mat -> terminer la partie if (target != null && target.getType() == PieceType.King) { gameOver = true; - // On ne modifie pas le plateau (le roi n'est pas capturé) return; } - // Sinon capturer la pièce normale - if (target != null) { + // Capture normale + if (!enPassantMove && target != null) { pieces.removeIf(p -> p.getX() == x && p.getY() == y); } + // Déplacer la pièce sélectionnée pieces.removeIf(p -> p.getX() == selectedX && p.getY() == selectedY); pieces.add(new Piece( - selectedPiece.isWhite(), - selectedPiece.getType(), - x, y + selectedPiece.isWhite(), + selectedPiece.getType(), + x, y )); - // Historique - Move move = new Move(selectedPiece, selectedX, selectedY, x, y, target); + // EN PASSANT : Maj de la case en passant + if (selectedPiece.getType() == PieceType.Pawn && Math.abs(y - selectedY) == 2) { + enPassantX = x; + enPassantY = (y + selectedY) / 2; // Case traversée + } else { + enPassantX = null; + enPassantY = null; + } + + // Move history (on précise enPassant ou non) + Move move = new Move(selectedPiece, selectedX, selectedY, x, y, target, + enPassantMove); moveHistory.push(move); // Changer de tour @@ -183,9 +221,9 @@ public class Board { Move lastMove = moveHistory.pop(); pieces.removeIf(p -> p.getX() == lastMove.getToX() && p.getY() == lastMove.getToY()); pieces.add(new Piece( - lastMove.getMovedPiece().isWhite(), - lastMove.getMovedPiece().getType(), - lastMove.getFromX(), lastMove.getFromY() + lastMove.getMovedPiece().isWhite(), + lastMove.getMovedPiece().getType(), + lastMove.getFromX(), lastMove.getFromY() )); if (lastMove.getCapturedPiece() != null) { pieces.add(lastMove.getCapturedPiece()); @@ -196,13 +234,11 @@ public class Board { selectedY = null; highlightedPositions.clear(); gameOver = false; + enPassantX = null; + enPassantY = null; } } - /** - * Détermine si le joueur forWhite est en échec et mat. - * @param forWhite couleur du joueur - */ public boolean isCheckmate(boolean forWhite) { if (!isKingInCheck(forWhite)) return false; for (Piece piece : pieces) { @@ -223,14 +259,12 @@ public class Board { return true; } - /** - * Vérifie si le roi de couleur isWhite est en échec. - */ public boolean isKingInCheck(boolean isWhite) { Piece king = null; for (Piece p : pieces) { if (p.getType() == PieceType.King && p.isWhite() == isWhite) { - king = p; break; + king = p; + break; } } if (king == null) return true; // pas de roi => considérer comme échec @@ -280,15 +314,33 @@ public class Board { moves.add(new int[]{x, twoStepY}); } } + // Capture à gauche if (inBounds(x - 1, oneStepY)) { Piece left = getPieceAt(x - 1, oneStepY); if (left != null && left.isWhite() != isWhite) moves.add(new int[]{x - 1, oneStepY}); + // EN PASSANT GAUCHE + if (getEnPassantX() != null && getEnPassantY() != null && + x - 1 == getEnPassantX() && oneStepY == getEnPassantY() && + getPieceAt(x - 1, y) != null && + getPieceAt(x - 1, y).getType() == PieceType.Pawn && + getPieceAt(x - 1, y).isWhite() != isWhite) { + moves.add(new int[]{x - 1, oneStepY}); + } } + // Capture à droite if (inBounds(x + 1, oneStepY)) { Piece right = getPieceAt(x + 1, oneStepY); if (right != null && right.isWhite() != isWhite) moves.add(new int[]{x + 1, oneStepY}); + // EN PASSANT DROITE + if (getEnPassantX() != null && getEnPassantY() != null && + x + 1 == getEnPassantX() && oneStepY == getEnPassantY() && + getPieceAt(x + 1, y) != null && + getPieceAt(x + 1, y).getType() == PieceType.Pawn && + getPieceAt(x + 1, y).isWhite() != isWhite) { + moves.add(new int[]{x + 1, oneStepY}); + } } break; case Rook: @@ -407,22 +459,38 @@ public class Board { public void playMove(Move move) { if (move == null || gameOver) return; Piece captured = getPieceAt(move.getToX(), move.getToY()); + // EN PASSANT (avant la capture normale) + if (move.getMovedPiece().getType() == PieceType.Pawn + && move.isEnPassant()) { + int capturedY = move.getMovedPiece().isWhite() ? move.getToY() + 1 : move.getToY() - 1; + pieces.removeIf(p -> p.getX() == move.getToX() && p.getY() == capturedY); + } // Si tentative de capturer le roi, fin de partie if (captured != null && captured.getType() == PieceType.King) { gameOver = true; return; } // Capture normale - if (captured != null) { + if (!(move.getMovedPiece().getType() == PieceType.Pawn && move.isEnPassant()) && captured != null) { pieces.removeIf(p -> p.getX() == move.getToX() && p.getY() == move.getToY()); } // Déplacement pieces.removeIf(p -> p.getX() == move.getFromX() && p.getY() == move.getFromY()); pieces.add(new Piece( - move.getMovedPiece().isWhite(), - move.getMovedPiece().getType(), - move.getToX(), move.getToY() + move.getMovedPiece().isWhite(), + move.getMovedPiece().getType(), + move.getToX(), move.getToY() )); + + // EN PASSANT : Maj de la case en passant + if (move.getMovedPiece().getType() == PieceType.Pawn && Math.abs(move.getToY() - move.getFromY()) == 2) { + enPassantX = move.getToX(); + enPassantY = (move.getToY() + move.getFromY()) / 2; + } else { + enPassantX = null; + enPassantY = null; + } + moveHistory.push(move); turnNumber++; turnIsWhite = !turnIsWhite; @@ -430,7 +498,6 @@ public class Board { selectedY = null; highlightedPositions.clear(); - // Vérifier échec et mat if (isCheckmate(turnIsWhite)) { gameOver = true; } diff --git a/OOP_2B6_PROJECT/src/backend/Move.java b/OOP_2B6_PROJECT/src/backend/Move.java index ce0e266..bf5f87c 100644 --- a/OOP_2B6_PROJECT/src/backend/Move.java +++ b/OOP_2B6_PROJECT/src/backend/Move.java @@ -6,6 +6,9 @@ public class Move { private int toX, toY; private Piece capturedPiece; + + private boolean isEnPassant = false; + public Move(Piece movedPiece, int fromX, int fromY, int toX, int toY, Piece capturedPiece) { this.movedPiece = movedPiece; this.fromX = fromX; @@ -15,6 +18,16 @@ public class Move { this.capturedPiece = capturedPiece; } + public Move(Piece movedPiece, int fromX, int fromY, int toX, int toY, Piece capturedPiece, boolean isEnPassant) { + this.movedPiece = movedPiece; + this.fromX = fromX; + this.fromY = fromY; + this.toX = toX; + this.toY = toY; + this.capturedPiece = capturedPiece; + this.isEnPassant = isEnPassant; + } + public Piece getMovedPiece() { return movedPiece; } @@ -38,4 +51,13 @@ public class Move { public Piece getCapturedPiece() { return capturedPiece; } + + + public boolean isEnPassant() { + return isEnPassant; + } + + public void setEnPassant(boolean enPassant) { + this.isEnPassant = enPassant; + } }