En passant

This commit is contained in:
clement 2025-05-19 18:01:03 +02:00
parent d1b1bdcd19
commit cdbba67bc5
2 changed files with 119 additions and 30 deletions

View File

@ -18,15 +18,18 @@ public class Board {
private Stack<Move> moveHistory = new Stack<>(); private Stack<Move> moveHistory = new Stack<>();
// EN PASSANT
private Integer enPassantX = null;
private Integer enPassantY = null;
public Board(int colNum, int lineNum) { public Board(int colNum, int lineNum) {
this.width = colNum; this.width = colNum;
this.height = lineNum; this.height = lineNum;
this.pieces = new ArrayList<>(); this.pieces = new ArrayList<>();
this.enPassantX = null;
this.enPassantY = null;
} }
/**
* Constructeur de copie : clone l'état du plateau
*/
public Board(Board other) { public Board(Board other) {
this.width = other.width; this.width = other.width;
this.height = other.height; this.height = other.height;
@ -42,6 +45,8 @@ public class Board {
this.highlightedPositions = new ArrayList<>(other.highlightedPositions); this.highlightedPositions = new ArrayList<>(other.highlightedPositions);
this.moveHistory = new Stack<>(); this.moveHistory = new Stack<>();
this.moveHistory.addAll(other.moveHistory); this.moveHistory.addAll(other.moveHistory);
this.enPassantX = other.enPassantX;
this.enPassantY = other.enPassantY;
} }
public Board(String[] array) { public Board(String[] array) {
@ -59,6 +64,8 @@ public class Board {
} }
} }
turnIsWhite = array[8].equalsIgnoreCase("W"); turnIsWhite = array[8].equalsIgnoreCase("W");
this.enPassantX = null;
this.enPassantY = null;
} }
public int getWidth() { return width; } public int getWidth() { return width; }
@ -66,6 +73,8 @@ public class Board {
public int getTurnNumber() { return turnNumber; } public int getTurnNumber() { return turnNumber; }
public boolean isTurnWhite() { return turnIsWhite; } public boolean isTurnWhite() { return turnIsWhite; }
public boolean isGameOver() { return gameOver; } 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) { public void setPiece(boolean isWhite, PieceType type, int x, int y) {
pieces.removeIf(p -> p.getX() == x && p.getY() == 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.Knight, 6, 0);
setPiece(false, PieceType.Rook, 7, 0); setPiece(false, PieceType.Rook, 7, 0);
for (int x = 0; x < 8; x++) setPiece(false, PieceType.Pawn, x, 1); for (int x = 0; x < 8; x++) setPiece(false, PieceType.Pawn, x, 1);
this.enPassantX = null;
this.enPassantY = null;
} }
public void cleanBoard() { public void cleanBoard() {
@ -102,6 +113,8 @@ public class Board {
highlightedPositions.clear(); highlightedPositions.clear();
moveHistory.clear(); moveHistory.clear();
gameOver = false; gameOver = false;
enPassantX = null;
enPassantY = null;
} }
public ArrayList<Piece> getPieces() { return pieces; } public ArrayList<Piece> 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() == selectedX && p.getY() == selectedY);
simulation.pieces.removeIf(p -> p.getX() == x && p.getY() == y); simulation.pieces.removeIf(p -> p.getX() == x && p.getY() == y);
simulation.pieces.add(new Piece( simulation.pieces.add(new Piece(
selectedPiece.isWhite(), selectedPiece.isWhite(),
selectedPiece.getType(), selectedPiece.getType(),
x, y x, y
)); ));
if (!simulation.isKingInCheck(turnIsWhite)) { if (!simulation.isKingInCheck(turnIsWhite)) {
Piece target = getPieceAt(x, y); 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 // Si on cible le roi adverse, c'est un cas de mat -> terminer la partie
if (target != null && target.getType() == PieceType.King) { if (target != null && target.getType() == PieceType.King) {
gameOver = true; gameOver = true;
// On ne modifie pas le plateau (le roi n'est pas capturé)
return; return;
} }
// Sinon capturer la pièce normale // Capture normale
if (target != null) { if (!enPassantMove && target != null) {
pieces.removeIf(p -> p.getX() == x && p.getY() == y); pieces.removeIf(p -> p.getX() == x && p.getY() == y);
} }
// Déplacer la pièce sélectionnée // Déplacer la pièce sélectionnée
pieces.removeIf(p -> p.getX() == selectedX && p.getY() == selectedY); pieces.removeIf(p -> p.getX() == selectedX && p.getY() == selectedY);
pieces.add(new Piece( pieces.add(new Piece(
selectedPiece.isWhite(), selectedPiece.isWhite(),
selectedPiece.getType(), selectedPiece.getType(),
x, y x, y
)); ));
// Historique // EN PASSANT : Maj de la case en passant
Move move = new Move(selectedPiece, selectedX, selectedY, x, y, target); 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); moveHistory.push(move);
// Changer de tour // Changer de tour
@ -183,9 +221,9 @@ public class Board {
Move lastMove = moveHistory.pop(); Move lastMove = moveHistory.pop();
pieces.removeIf(p -> p.getX() == lastMove.getToX() && p.getY() == lastMove.getToY()); pieces.removeIf(p -> p.getX() == lastMove.getToX() && p.getY() == lastMove.getToY());
pieces.add(new Piece( pieces.add(new Piece(
lastMove.getMovedPiece().isWhite(), lastMove.getMovedPiece().isWhite(),
lastMove.getMovedPiece().getType(), lastMove.getMovedPiece().getType(),
lastMove.getFromX(), lastMove.getFromY() lastMove.getFromX(), lastMove.getFromY()
)); ));
if (lastMove.getCapturedPiece() != null) { if (lastMove.getCapturedPiece() != null) {
pieces.add(lastMove.getCapturedPiece()); pieces.add(lastMove.getCapturedPiece());
@ -196,13 +234,11 @@ public class Board {
selectedY = null; selectedY = null;
highlightedPositions.clear(); highlightedPositions.clear();
gameOver = false; 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) { public boolean isCheckmate(boolean forWhite) {
if (!isKingInCheck(forWhite)) return false; if (!isKingInCheck(forWhite)) return false;
for (Piece piece : pieces) { for (Piece piece : pieces) {
@ -223,14 +259,12 @@ public class Board {
return true; return true;
} }
/**
* Vérifie si le roi de couleur isWhite est en échec.
*/
public boolean isKingInCheck(boolean isWhite) { public boolean isKingInCheck(boolean isWhite) {
Piece king = null; Piece king = null;
for (Piece p : pieces) { for (Piece p : pieces) {
if (p.getType() == PieceType.King && p.isWhite() == isWhite) { 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 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}); moves.add(new int[]{x, twoStepY});
} }
} }
// Capture à gauche
if (inBounds(x - 1, oneStepY)) { if (inBounds(x - 1, oneStepY)) {
Piece left = getPieceAt(x - 1, oneStepY); Piece left = getPieceAt(x - 1, oneStepY);
if (left != null && left.isWhite() != isWhite) if (left != null && left.isWhite() != isWhite)
moves.add(new int[]{x - 1, oneStepY}); 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)) { if (inBounds(x + 1, oneStepY)) {
Piece right = getPieceAt(x + 1, oneStepY); Piece right = getPieceAt(x + 1, oneStepY);
if (right != null && right.isWhite() != isWhite) if (right != null && right.isWhite() != isWhite)
moves.add(new int[]{x + 1, oneStepY}); 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; break;
case Rook: case Rook:
@ -407,22 +459,38 @@ public class Board {
public void playMove(Move move) { public void playMove(Move move) {
if (move == null || gameOver) return; if (move == null || gameOver) return;
Piece captured = getPieceAt(move.getToX(), move.getToY()); 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 // Si tentative de capturer le roi, fin de partie
if (captured != null && captured.getType() == PieceType.King) { if (captured != null && captured.getType() == PieceType.King) {
gameOver = true; gameOver = true;
return; return;
} }
// Capture normale // 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()); pieces.removeIf(p -> p.getX() == move.getToX() && p.getY() == move.getToY());
} }
// Déplacement // Déplacement
pieces.removeIf(p -> p.getX() == move.getFromX() && p.getY() == move.getFromY()); pieces.removeIf(p -> p.getX() == move.getFromX() && p.getY() == move.getFromY());
pieces.add(new Piece( pieces.add(new Piece(
move.getMovedPiece().isWhite(), move.getMovedPiece().isWhite(),
move.getMovedPiece().getType(), move.getMovedPiece().getType(),
move.getToX(), move.getToY() 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); moveHistory.push(move);
turnNumber++; turnNumber++;
turnIsWhite = !turnIsWhite; turnIsWhite = !turnIsWhite;
@ -430,7 +498,6 @@ public class Board {
selectedY = null; selectedY = null;
highlightedPositions.clear(); highlightedPositions.clear();
// Vérifier échec et mat
if (isCheckmate(turnIsWhite)) { if (isCheckmate(turnIsWhite)) {
gameOver = true; gameOver = true;
} }

View File

@ -6,6 +6,9 @@ public class Move {
private int toX, toY; private int toX, toY;
private Piece capturedPiece; private Piece capturedPiece;
private boolean isEnPassant = false;
public Move(Piece movedPiece, int fromX, int fromY, int toX, int toY, Piece capturedPiece) { public Move(Piece movedPiece, int fromX, int fromY, int toX, int toY, Piece capturedPiece) {
this.movedPiece = movedPiece; this.movedPiece = movedPiece;
this.fromX = fromX; this.fromX = fromX;
@ -15,6 +18,16 @@ public class Move {
this.capturedPiece = capturedPiece; 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() { public Piece getMovedPiece() {
return movedPiece; return movedPiece;
} }
@ -38,4 +51,13 @@ public class Move {
public Piece getCapturedPiece() { public Piece getCapturedPiece() {
return capturedPiece; return capturedPiece;
} }
public boolean isEnPassant() {
return isEnPassant;
}
public void setEnPassant(boolean enPassant) {
this.isEnPassant = enPassant;
}
} }