check and checkmate
This commit is contained in:
parent
56806bed50
commit
065b410ef3
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package backend;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -14,9 +13,22 @@ public class Board {
|
|||
private ArrayList<int[]> highlightedSquares = new ArrayList<>();
|
||||
private Stack<Move> moveHistory = new Stack<>();
|
||||
|
||||
public Board(int colNum, int lineNum) {
|
||||
this.width = colNum;
|
||||
this.height = lineNum;
|
||||
// Game message attribute
|
||||
private String gameMessage = "";
|
||||
|
||||
// Advanced movement attributes
|
||||
private int enPassantColumn = -1;
|
||||
private int enPassantRow = -1;
|
||||
private boolean whiteKingMoved = false;
|
||||
private boolean blackKingMoved = false;
|
||||
private boolean whiteRookKingSideMoved = false;
|
||||
private boolean whiteRookQueenSideMoved = false;
|
||||
private boolean blackRookKingSideMoved = false;
|
||||
private boolean blackRookQueenSideMoved = false;
|
||||
|
||||
public Board(int width, int height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.turnNumber = 0;
|
||||
this.isWhiteTurn = true;
|
||||
this.pieces = new ArrayList<>();
|
||||
|
|
@ -24,6 +36,46 @@ public class Board {
|
|||
this.selectedY = null;
|
||||
}
|
||||
|
||||
public Board(Board board) {
|
||||
this.width = board.width;
|
||||
this.height = board.height;
|
||||
this.turnNumber = board.turnNumber;
|
||||
this.isWhiteTurn = board.isWhiteTurn;
|
||||
this.selectedX = board.selectedX;
|
||||
this.selectedY = board.selectedY;
|
||||
this.gameMessage = board.gameMessage;
|
||||
|
||||
// Deep copy of pieces
|
||||
this.pieces = new ArrayList<>();
|
||||
for (Piece p : board.pieces) {
|
||||
this.pieces.add(new Piece(p.getX(), p.getY(), p.isWhite(), p.getType()));
|
||||
}
|
||||
|
||||
// Copy highlighted squares
|
||||
this.highlightedSquares = new ArrayList<>();
|
||||
for (int[] square : board.highlightedSquares) {
|
||||
this.highlightedSquares.add(new int[]{square[0], square[1]});
|
||||
}
|
||||
|
||||
// Copy castling and en-passant state
|
||||
this.whiteKingMoved = board.whiteKingMoved;
|
||||
this.blackKingMoved = board.blackKingMoved;
|
||||
this.whiteRookKingSideMoved = board.whiteRookKingSideMoved;
|
||||
this.whiteRookQueenSideMoved = board.whiteRookQueenSideMoved;
|
||||
this.blackRookKingSideMoved = board.blackRookKingSideMoved;
|
||||
this.blackRookQueenSideMoved = board.blackRookQueenSideMoved;
|
||||
this.enPassantColumn = board.enPassantColumn;
|
||||
this.enPassantRow = board.enPassantRow;
|
||||
|
||||
// We don't copy the move history as it's not needed for evaluation
|
||||
this.moveHistory = new Stack<>();
|
||||
}
|
||||
|
||||
public Board(String[] array) {
|
||||
// TODO: Part 3 - Load
|
||||
this(8, 8); // Default initialization
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
|
@ -40,6 +92,11 @@ public class Board {
|
|||
return isWhiteTurn;
|
||||
}
|
||||
|
||||
// Getter for game message
|
||||
public String getGameMessage() {
|
||||
return gameMessage;
|
||||
}
|
||||
|
||||
public void setPiece(boolean isWhite, PieceType type, int x, int y) {
|
||||
removePieceAt(x, y);
|
||||
pieces.add(new Piece(x, y, isWhite, type));
|
||||
|
|
@ -60,6 +117,17 @@ public class Board {
|
|||
pieces.add(new Piece(x, 0, false, backRow[x])); // Black back row
|
||||
pieces.add(new Piece(x, 7, true, backRow[x])); // White back row
|
||||
}
|
||||
|
||||
// Reset movement tracking
|
||||
whiteKingMoved = false;
|
||||
blackKingMoved = false;
|
||||
whiteRookKingSideMoved = false;
|
||||
whiteRookQueenSideMoved = false;
|
||||
blackRookKingSideMoved = false;
|
||||
blackRookQueenSideMoved = false;
|
||||
enPassantColumn = -1;
|
||||
enPassantRow = -1;
|
||||
gameMessage = "";
|
||||
}
|
||||
|
||||
public void cleanBoard() {
|
||||
|
|
@ -70,8 +138,19 @@ public class Board {
|
|||
selectedY = null;
|
||||
highlightedSquares.clear();
|
||||
moveHistory.clear();
|
||||
|
||||
// Reset movement tracking
|
||||
whiteKingMoved = false;
|
||||
blackKingMoved = false;
|
||||
whiteRookKingSideMoved = false;
|
||||
whiteRookQueenSideMoved = false;
|
||||
blackRookKingSideMoved = false;
|
||||
blackRookQueenSideMoved = false;
|
||||
enPassantColumn = -1;
|
||||
enPassantRow = -1;
|
||||
gameMessage = "";
|
||||
}
|
||||
//create the board
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int y = 0; y < height; y++) {
|
||||
|
|
@ -121,6 +200,16 @@ public class Board {
|
|||
Piece selectedPiece = getPieceAt(selectedX, selectedY);
|
||||
Piece captured = getPieceAt(x, y);
|
||||
|
||||
// Check for en-passant capture
|
||||
if (selectedPiece.getType() == PieceType.Pawn &&
|
||||
x == enPassantColumn &&
|
||||
((selectedPiece.isWhite() && y == enPassantRow - 1) ||
|
||||
(!selectedPiece.isWhite() && y == enPassantRow + 1))) {
|
||||
// Remove the pawn that was captured en-passant
|
||||
captured = getPieceAt(enPassantColumn, enPassantRow);
|
||||
removePieceAt(enPassantColumn, enPassantRow);
|
||||
}
|
||||
|
||||
// Store move for undo
|
||||
Move m = new Move(
|
||||
selectedX, selectedY, x, y,
|
||||
|
|
@ -128,12 +217,76 @@ public class Board {
|
|||
);
|
||||
moveHistory.push(m);
|
||||
|
||||
removePieceAt(x, y); // capture
|
||||
// Track king and rook movements for castling
|
||||
if (selectedPiece.getType() == PieceType.King) {
|
||||
if (selectedPiece.isWhite()) {
|
||||
whiteKingMoved = true;
|
||||
|
||||
// Check for castling
|
||||
if (selectedX == 4 && selectedY == 7) {
|
||||
if (x == 6 && y == 7) { // King-side castling
|
||||
// Move the rook too
|
||||
removePieceAt(7, 7);
|
||||
pieces.add(new Piece(5, 7, true, PieceType.Rook));
|
||||
} else if (x == 2 && y == 7) { // Queen-side castling
|
||||
// Move the rook too
|
||||
removePieceAt(0, 7);
|
||||
pieces.add(new Piece(3, 7, true, PieceType.Rook));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
blackKingMoved = true;
|
||||
|
||||
// Check for castling
|
||||
if (selectedX == 4 && selectedY == 0) {
|
||||
if (x == 6 && y == 0) { // King-side castling
|
||||
// Move the rook too
|
||||
removePieceAt(7, 0);
|
||||
pieces.add(new Piece(5, 0, false, PieceType.Rook));
|
||||
} else if (x == 2 && y == 0) { // Queen-side castling
|
||||
// Move the rook too
|
||||
removePieceAt(0, 0);
|
||||
pieces.add(new Piece(3, 0, false, PieceType.Rook));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (selectedPiece.getType() == PieceType.Rook) {
|
||||
if (selectedPiece.isWhite()) {
|
||||
if (selectedX == 0 && selectedY == 7) {
|
||||
whiteRookQueenSideMoved = true;
|
||||
} else if (selectedX == 7 && selectedY == 7) {
|
||||
whiteRookKingSideMoved = true;
|
||||
}
|
||||
} else {
|
||||
if (selectedX == 0 && selectedY == 0) {
|
||||
blackRookQueenSideMoved = true;
|
||||
} else if (selectedX == 7 && selectedY == 0) {
|
||||
blackRookKingSideMoved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset en-passant
|
||||
enPassantColumn = -1;
|
||||
enPassantRow = -1;
|
||||
|
||||
// Check if this is a double pawn move for en-passant
|
||||
if (selectedPiece.getType() == PieceType.Pawn &&
|
||||
Math.abs(y - selectedY) == 2) {
|
||||
enPassantColumn = x;
|
||||
enPassantRow = y;
|
||||
}
|
||||
|
||||
// Move the piece
|
||||
removePieceAt(x, y); // capture if any
|
||||
removePieceAt(selectedX, selectedY);
|
||||
pieces.add(new Piece(x, y, selectedPiece.isWhite(), selectedPiece.getType()));
|
||||
|
||||
turnNumber++;
|
||||
isWhiteTurn = !isWhiteTurn;
|
||||
|
||||
// Check for check or checkmate after move
|
||||
updateCheckStatus();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -152,10 +305,6 @@ public class Board {
|
|||
return null;
|
||||
}
|
||||
|
||||
public Board(String[] array) {
|
||||
// TODO: Part 3 - Load
|
||||
}
|
||||
|
||||
public boolean isHighlighted(int x, int y) {
|
||||
for (int[] move : highlightedSquares) {
|
||||
if (move[0] == x && move[1] == y) return true;
|
||||
|
|
@ -185,32 +334,65 @@ public class Board {
|
|||
pieces.add(new Piece(p.getX(), p.getY(), p.isWhite(), p.getType()));
|
||||
}
|
||||
|
||||
// Undo castling if it was a king move
|
||||
if (lastMove.getType() == PieceType.King) {
|
||||
if (lastMove.isWhite()) {
|
||||
// Undo white king-side castling
|
||||
if (lastMove.getFromX() == 4 && lastMove.getFromY() == 7 &&
|
||||
lastMove.getToX() == 6 && lastMove.getToY() == 7) {
|
||||
removePieceAt(5, 7); // Remove rook from new position
|
||||
pieces.add(new Piece(7, 7, true, PieceType.Rook)); // Restore rook
|
||||
}
|
||||
// Undo white queen-side castling
|
||||
else if (lastMove.getFromX() == 4 && lastMove.getFromY() == 7 &&
|
||||
lastMove.getToX() == 2 && lastMove.getToY() == 7) {
|
||||
removePieceAt(3, 7); // Remove rook from new position
|
||||
pieces.add(new Piece(0, 7, true, PieceType.Rook)); // Restore rook
|
||||
}
|
||||
whiteKingMoved = false;
|
||||
} else {
|
||||
// Undo black king-side castling
|
||||
if (lastMove.getFromX() == 4 && lastMove.getFromY() == 0 &&
|
||||
lastMove.getToX() == 6 && lastMove.getToY() == 0) {
|
||||
removePieceAt(5, 0); // Remove rook from new position
|
||||
pieces.add(new Piece(7, 0, false, PieceType.Rook)); // Restore rook
|
||||
}
|
||||
// Undo black queen-side castling
|
||||
else if (lastMove.getFromX() == 4 && lastMove.getFromY() == 0 &&
|
||||
lastMove.getToX() == 2 && lastMove.getToY() == 0) {
|
||||
removePieceAt(3, 0); // Remove rook from new position
|
||||
pieces.add(new Piece(0, 0, false, PieceType.Rook)); // Restore rook
|
||||
}
|
||||
blackKingMoved = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Undo rook movement tracking
|
||||
if (lastMove.getType() == PieceType.Rook) {
|
||||
if (lastMove.isWhite()) {
|
||||
if (lastMove.getFromX() == 0 && lastMove.getFromY() == 7) {
|
||||
whiteRookQueenSideMoved = false;
|
||||
} else if (lastMove.getFromX() == 7 && lastMove.getFromY() == 7) {
|
||||
whiteRookKingSideMoved = false;
|
||||
}
|
||||
} else {
|
||||
if (lastMove.getFromX() == 0 && lastMove.getFromY() == 0) {
|
||||
blackRookQueenSideMoved = false;
|
||||
} else if (lastMove.getFromX() == 7 && lastMove.getFromY() == 0) {
|
||||
blackRookKingSideMoved = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset en-passant for simplicity (could be more accurate with more state tracking)
|
||||
enPassantColumn = -1;
|
||||
enPassantRow = -1;
|
||||
|
||||
turnNumber--;
|
||||
isWhiteTurn = !isWhiteTurn;
|
||||
}
|
||||
|
||||
public Board(Board board) {
|
||||
this.width = board.width;
|
||||
this.height = board.height;
|
||||
this.turnNumber = board.turnNumber;
|
||||
this.isWhiteTurn = board.isWhiteTurn;
|
||||
this.selectedX = board.selectedX;
|
||||
this.selectedY = board.selectedY;
|
||||
|
||||
// Deep copy of pieces
|
||||
this.pieces = new ArrayList<>();
|
||||
for (Piece p : board.pieces) {
|
||||
this.pieces.add(new Piece(p.getX(), p.getY(), p.isWhite(), p.getType()));
|
||||
}
|
||||
|
||||
// Copy highlighted squares
|
||||
this.highlightedSquares = new ArrayList<>();
|
||||
for (int[] square : board.highlightedSquares) {
|
||||
this.highlightedSquares.add(new int[]{square[0], square[1]});
|
||||
}
|
||||
|
||||
// We don't copy the move history as it's not needed for evaluation
|
||||
this.moveHistory = new Stack<>();
|
||||
// Update check status after undoing move
|
||||
updateCheckStatus();
|
||||
}
|
||||
|
||||
public void playMove(Move move) {
|
||||
|
|
@ -219,11 +401,80 @@ public class Board {
|
|||
// Store move for undo
|
||||
moveHistory.push(move);
|
||||
|
||||
// Remove captured piece if any
|
||||
if (move.getCapturedPiece() != null) {
|
||||
removePieceAt(move.getToX(), move.getToY());
|
||||
Piece movingPiece = getPieceAt(move.getFromX(), move.getFromY());
|
||||
|
||||
// Check for en-passant capture
|
||||
if (movingPiece != null && movingPiece.getType() == PieceType.Pawn &&
|
||||
move.getToX() == enPassantColumn &&
|
||||
((movingPiece.isWhite() && move.getToY() == enPassantRow - 1) ||
|
||||
(!movingPiece.isWhite() && move.getToY() == enPassantRow + 1))) {
|
||||
// Remove the pawn that was captured en-passant
|
||||
removePieceAt(enPassantColumn, enPassantRow);
|
||||
}
|
||||
|
||||
// Track king and rook movements for castling
|
||||
if (movingPiece != null && movingPiece.getType() == PieceType.King) {
|
||||
if (movingPiece.isWhite()) {
|
||||
whiteKingMoved = true;
|
||||
|
||||
// Check for castling
|
||||
if (move.getFromX() == 4 && move.getFromY() == 7) {
|
||||
if (move.getToX() == 6 && move.getToY() == 7) { // King-side castling
|
||||
// Move the rook too
|
||||
removePieceAt(7, 7);
|
||||
pieces.add(new Piece(5, 7, true, PieceType.Rook));
|
||||
} else if (move.getToX() == 2 && move.getToY() == 7) { // Queen-side castling
|
||||
// Move the rook too
|
||||
removePieceAt(0, 7);
|
||||
pieces.add(new Piece(3, 7, true, PieceType.Rook));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
blackKingMoved = true;
|
||||
|
||||
// Check for castling
|
||||
if (move.getFromX() == 4 && move.getFromY() == 0) {
|
||||
if (move.getToX() == 6 && move.getToY() == 0) { // King-side castling
|
||||
// Move the rook too
|
||||
removePieceAt(7, 0);
|
||||
pieces.add(new Piece(5, 0, false, PieceType.Rook));
|
||||
} else if (move.getToX() == 2 && move.getToY() == 0) { // Queen-side castling
|
||||
// Move the rook too
|
||||
removePieceAt(0, 0);
|
||||
pieces.add(new Piece(3, 0, false, PieceType.Rook));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (movingPiece != null && movingPiece.getType() == PieceType.Rook) {
|
||||
if (movingPiece.isWhite()) {
|
||||
if (move.getFromX() == 0 && move.getFromY() == 7) {
|
||||
whiteRookQueenSideMoved = true;
|
||||
} else if (move.getFromX() == 7 && move.getFromY() == 7) {
|
||||
whiteRookKingSideMoved = true;
|
||||
}
|
||||
} else {
|
||||
if (move.getFromX() == 0 && move.getFromY() == 0) {
|
||||
blackRookQueenSideMoved = true;
|
||||
} else if (move.getFromX() == 7 && move.getFromY() == 0) {
|
||||
blackRookKingSideMoved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset en-passant
|
||||
enPassantColumn = -1;
|
||||
enPassantRow = -1;
|
||||
|
||||
// Check if this is a double pawn move for en-passant
|
||||
if (movingPiece != null && movingPiece.getType() == PieceType.Pawn &&
|
||||
Math.abs(move.getToY() - move.getFromY()) == 2) {
|
||||
enPassantColumn = move.getToX();
|
||||
enPassantRow = move.getToY();
|
||||
}
|
||||
|
||||
// Remove captured piece if any
|
||||
removePieceAt(move.getToX(), move.getToY());
|
||||
|
||||
// Remove piece from original position
|
||||
removePieceAt(move.getFromX(), move.getFromY());
|
||||
|
||||
|
|
@ -234,14 +485,53 @@ public class Board {
|
|||
turnNumber++;
|
||||
isWhiteTurn = !isWhiteTurn;
|
||||
|
||||
// Check for check or checkmate after move
|
||||
updateCheckStatus();
|
||||
}
|
||||
|
||||
// ========== Helper Methods ==========
|
||||
// Method to check if the current player is in check or checkmate
|
||||
private void updateCheckStatus() {
|
||||
gameMessage = ""; // Reset message
|
||||
|
||||
private void removePieceAt(int x, int y) {
|
||||
pieces.removeIf(p -> p.getX() == x && p.getY() == y);
|
||||
// Find the king of the current player
|
||||
Piece king = findKing(isWhiteTurn);
|
||||
if (king == null) return; // Should never happen in a valid game
|
||||
|
||||
// Check if the king is under attack
|
||||
boolean inCheck = isSquareAttacked(king.getX(), king.getY(), !isWhiteTurn);
|
||||
|
||||
if (inCheck) {
|
||||
// Check if there are any legal moves for the current player
|
||||
boolean hasLegalMoves = false;
|
||||
|
||||
// Check king's moves
|
||||
ArrayList<int[]> kingMoves = computeLegalMoves(king);
|
||||
if (!kingMoves.isEmpty()) {
|
||||
hasLegalMoves = true;
|
||||
}
|
||||
|
||||
// Check other pieces' moves
|
||||
if (!hasLegalMoves) {
|
||||
for (Piece piece : pieces) {
|
||||
if (piece.isWhite() == isWhiteTurn && piece.getType() != PieceType.King) {
|
||||
ArrayList<int[]> moves = computeLegalMoves(piece);
|
||||
if (!moves.isEmpty()) {
|
||||
hasLegalMoves = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasLegalMoves) {
|
||||
gameMessage = "Check!";
|
||||
} else {
|
||||
gameMessage = "Checkmate!";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
private Piece getPieceAt(int x, int y) {
|
||||
for (Piece p : pieces) {
|
||||
if (p.getX() == x && p.getY() == y) return p;
|
||||
|
|
@ -249,106 +539,312 @@ public class Board {
|
|||
return null;
|
||||
}
|
||||
|
||||
private void removePieceAt(int x, int y) {
|
||||
pieces.removeIf(p -> p.getX() == x && p.getY() == y);
|
||||
}
|
||||
|
||||
private ArrayList<int[]> computeLegalMoves(Piece piece) {
|
||||
ArrayList<int[]> moves = new ArrayList<>();
|
||||
int x = piece.getX();
|
||||
int y = piece.getY();
|
||||
boolean isWhite = piece.isWhite();
|
||||
ArrayList<int[]> candidateMoves = new ArrayList<>();
|
||||
int x = piece.getX();
|
||||
int y = piece.getY();
|
||||
boolean isWhite = piece.isWhite();
|
||||
|
||||
switch (piece.getType()) {
|
||||
case Pawn:
|
||||
int dir = isWhite ? -1 : 1;
|
||||
int startRow = isWhite ? 6 : 1;
|
||||
switch (piece.getType()) {
|
||||
case Pawn:
|
||||
int dir = isWhite ? -1 : 1;
|
||||
int startRow = isWhite ? 6 : 1;
|
||||
|
||||
if (getPieceAt(x, y + dir) == null) {
|
||||
moves.add(new int[]{x, y + dir});
|
||||
if (y == startRow && getPieceAt(x, y + 2 * dir) == null) {
|
||||
moves.add(new int[]{x, y + 2 * dir});
|
||||
}
|
||||
}
|
||||
for (int dx = -1; dx <= 1; dx += 2) {
|
||||
int nx = x + dx;
|
||||
int ny = y + dir;
|
||||
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
||||
Piece target = getPieceAt(nx, ny);
|
||||
if (target != null && target.isWhite() != isWhite) {
|
||||
moves.add(new int[]{nx, ny});
|
||||
// Forward move
|
||||
if (getPieceAt(x, y + dir) == null) {
|
||||
candidateMoves.add(new int[]{x, y + dir});
|
||||
// Double move from starting position
|
||||
if (y == startRow && getPieceAt(x, y + 2 * dir) == null) {
|
||||
candidateMoves.add(new int[]{x, y + 2 * dir});
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Rook:
|
||||
addSlidingMoves(moves, x, y, isWhite, new int[][]{{1,0},{-1,0},{0,1},{0,-1}});
|
||||
break;
|
||||
|
||||
case Bishop:
|
||||
addSlidingMoves(moves, x, y, isWhite, new int[][]{{1,1},{1,-1},{-1,1},{-1,-1}});
|
||||
break;
|
||||
|
||||
case Queen:
|
||||
addSlidingMoves(moves, x, y, isWhite, new int[][]{
|
||||
{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}
|
||||
});
|
||||
break;
|
||||
|
||||
case Knight:
|
||||
int[][] knightMoves = {
|
||||
{x+1, y+2}, {x+1, y-2}, {x-1, y+2}, {x-1, y-2},
|
||||
{x+2, y+1}, {x+2, y-1}, {x-2, y+1}, {x-2, y-1}
|
||||
};
|
||||
for (int[] move : knightMoves) {
|
||||
int nx = move[0];
|
||||
int ny = move[1];
|
||||
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
||||
Piece target = getPieceAt(nx, ny);
|
||||
if (target == null || target.isWhite() != isWhite) {
|
||||
moves.add(new int[]{nx, ny});
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case King:
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dy = -1; dy <= 1; dy++) {
|
||||
if (dx == 0 && dy == 0) continue;
|
||||
// Regular captures
|
||||
for (int dx = -1; dx <= 1; dx += 2) {
|
||||
int nx = x + dx;
|
||||
int ny = y + dy;
|
||||
int ny = y + dir;
|
||||
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
||||
Piece target = getPieceAt(nx, ny);
|
||||
if (target != null && target.isWhite() != isWhite) {
|
||||
candidateMoves.add(new int[]{nx, ny});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// En-passant capture
|
||||
if (enPassantColumn != -1 &&
|
||||
Math.abs(x - enPassantColumn) == 1 &&
|
||||
y == enPassantRow) {
|
||||
candidateMoves.add(new int[]{enPassantColumn, enPassantRow + (isWhite ? -1 : 1)});
|
||||
}
|
||||
break;
|
||||
|
||||
case Rook:
|
||||
addSlidingMoves(candidateMoves, x, y, isWhite, new int[][]{{1,0},{-1,0},{0,1},{0,-1}}, false);
|
||||
break;
|
||||
|
||||
case Bishop:
|
||||
addSlidingMoves(candidateMoves, x, y, isWhite, new int[][]{{1,1},{1,-1},{-1,1},{-1,-1}}, false);
|
||||
break;
|
||||
|
||||
case Queen:
|
||||
addSlidingMoves(candidateMoves, x, y, isWhite, new int[][]{
|
||||
{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}
|
||||
}, false);
|
||||
break;
|
||||
|
||||
case Knight:
|
||||
int[][] knightMoves = {
|
||||
{1,2}, {1,-2}, {-1,2}, {-1,-2},
|
||||
{2,1}, {2,-1}, {-2,1}, {-2,-1}
|
||||
};
|
||||
for (int[] move : knightMoves) {
|
||||
int nx = x + move[0];
|
||||
int ny = y + move[1];
|
||||
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
||||
Piece target = getPieceAt(nx, ny);
|
||||
if (target == null || target.isWhite() != isWhite) {
|
||||
candidateMoves.add(new int[]{nx, ny});
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case King:
|
||||
// Normal king moves
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dy = -1; dy <= 1; dy++) {
|
||||
if (dx == 0 && dy == 0) continue;
|
||||
int nx = x + dx;
|
||||
int ny = y + dy;
|
||||
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
||||
Piece target = getPieceAt(nx, ny);
|
||||
if (target == null || target.isWhite() != isWhite) {
|
||||
candidateMoves.add(new int[]{nx, ny});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Castling
|
||||
if (isWhite && !whiteKingMoved && x == 4 && y == 7) {
|
||||
// King-side castling
|
||||
if (!whiteRookKingSideMoved &&
|
||||
getPieceAt(5, 7) == null &&
|
||||
getPieceAt(6, 7) == null &&
|
||||
getPieceAt(7, 7) != null &&
|
||||
getPieceAt(7, 7).getType() == PieceType.Rook) {
|
||||
|
||||
// Check if king would pass through check
|
||||
if (!isSquareAttacked(4, 7, false) &&
|
||||
!isSquareAttacked(5, 7, false) &&
|
||||
!isSquareAttacked(6, 7, false)) {
|
||||
candidateMoves.add(new int[]{6, 7});
|
||||
}
|
||||
}
|
||||
|
||||
// Queen-side castling
|
||||
if (!whiteRookQueenSideMoved &&
|
||||
getPieceAt(1, 7) == null &&
|
||||
getPieceAt(2, 7) == null &&
|
||||
getPieceAt(3, 7) == null &&
|
||||
getPieceAt(0, 7) != null &&
|
||||
getPieceAt(0, 7).getType() == PieceType.Rook) {
|
||||
|
||||
// Check if king would pass through check
|
||||
if (!isSquareAttacked(4, 7, false) &&
|
||||
!isSquareAttacked(3, 7, false) &&
|
||||
!isSquareAttacked(2, 7, false)) {
|
||||
candidateMoves.add(new int[]{2, 7});
|
||||
}
|
||||
}
|
||||
} else if (!isWhite && !blackKingMoved && x == 4 && y == 0) {
|
||||
// King-side castling
|
||||
if (!blackRookKingSideMoved &&
|
||||
getPieceAt(5, 0) == null &&
|
||||
getPieceAt(6, 0) == null &&
|
||||
getPieceAt(7, 0) != null &&
|
||||
getPieceAt(7, 0).getType() == PieceType.Rook) {
|
||||
|
||||
// Check if king would pass through check
|
||||
if (!isSquareAttacked(4, 0, true) &&
|
||||
!isSquareAttacked(5, 0, true) &&
|
||||
!isSquareAttacked(6, 0, true)) {
|
||||
candidateMoves.add(new int[]{6, 0});
|
||||
}
|
||||
}
|
||||
|
||||
// Queen-side castling
|
||||
if (!blackRookQueenSideMoved &&
|
||||
getPieceAt(1, 0) == null &&
|
||||
getPieceAt(2, 0) == null &&
|
||||
getPieceAt(3, 0) == null &&
|
||||
getPieceAt(0, 0) != null &&
|
||||
getPieceAt(0, 0).getType() == PieceType.Rook) {
|
||||
|
||||
// Check if king would pass through check
|
||||
if (!isSquareAttacked(4, 0, true) &&
|
||||
!isSquareAttacked(3, 0, true) &&
|
||||
!isSquareAttacked(2, 0, true)) {
|
||||
candidateMoves.add(new int[]{2, 0});
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Filter out moves that would leave the king in check
|
||||
ArrayList<int[]> legalMoves = new ArrayList<>();
|
||||
for (int[] move : candidateMoves) {
|
||||
if (!moveWouldLeaveInCheck(piece, move[0], move[1])) {
|
||||
legalMoves.add(move);
|
||||
}
|
||||
}
|
||||
|
||||
return legalMoves;
|
||||
}
|
||||
|
||||
private void addSlidingMoves(ArrayList<int[]> moves, int x, int y, boolean isWhite, int[][] directions, boolean forAttack) {
|
||||
for (int[] dir : directions) {
|
||||
for (int i = 1; i < 8; i++) {
|
||||
int nx = x + dir[0] * i;
|
||||
int ny = y + dir[1] * i;
|
||||
if (nx < 0 || nx >= width || ny < 0 || ny >= height) break;
|
||||
|
||||
Piece target = getPieceAt(nx, ny);
|
||||
if (target == null) {
|
||||
moves.add(new int[]{nx, ny});
|
||||
} else {
|
||||
if (target.isWhite() != isWhite) {
|
||||
moves.add(new int[]{nx, ny});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSquareAttacked(int x, int y, boolean byWhite) {
|
||||
for (Piece piece : pieces) {
|
||||
if (piece.isWhite() == byWhite) {
|
||||
ArrayList<int[]> attackMoves = getAttackMoves(piece);
|
||||
for (int[] move : attackMoves) {
|
||||
if (move[0] == x && move[1] == y) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private ArrayList<int[]> getAttackMoves(Piece piece) {
|
||||
ArrayList<int[]> moves = new ArrayList<>();
|
||||
int x = piece.getX();
|
||||
int y = piece.getY();
|
||||
boolean isWhite = piece.isWhite();
|
||||
|
||||
switch (piece.getType()) {
|
||||
case Pawn:
|
||||
int dir = isWhite ? -1 : 1;
|
||||
// Pawns attack diagonally
|
||||
for (int dx = -1; dx <= 1; dx += 2) {
|
||||
int nx = x + dx;
|
||||
int ny = y + dir;
|
||||
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
||||
moves.add(new int[]{nx, ny});
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Other pieces attack the same way they move
|
||||
case Rook:
|
||||
addSlidingMoves(moves, x, y, isWhite, new int[][]{{1,0},{-1,0},{0,1},{0,-1}}, true);
|
||||
break;
|
||||
|
||||
case Bishop:
|
||||
addSlidingMoves(moves, x, y, isWhite, new int[][]{{1,1},{1,-1},{-1,1},{-1,-1}}, true);
|
||||
break;
|
||||
|
||||
case Queen:
|
||||
addSlidingMoves(moves, x, y, isWhite, new int[][]{
|
||||
{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}
|
||||
}, true);
|
||||
break;
|
||||
|
||||
case Knight:
|
||||
int[][] knightMoves = {
|
||||
{1,2}, {1,-2}, {-1,2}, {-1,-2},
|
||||
{2,1}, {2,-1}, {-2,1}, {-2,-1}
|
||||
};
|
||||
for (int[] move : knightMoves) {
|
||||
int nx = x + move[0];
|
||||
int ny = y + move[1];
|
||||
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
||||
moves.add(new int[]{nx, ny});
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case King:
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dy = -1; dy <= 1; dy++) {
|
||||
if (dx == 0 && dy == 0) continue;
|
||||
int nx = x + dx;
|
||||
int ny = y + dy;
|
||||
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
||||
moves.add(new int[]{nx, ny});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
private void addSlidingMoves(ArrayList<int[]> moves, int x, int y, boolean isWhite, int[][] directions) {
|
||||
for (int[] dir : directions) {
|
||||
for (int i = 1; i < 8; i++) {
|
||||
int nx = x + dir[0] * i;
|
||||
int ny = y + dir[1] * i;
|
||||
if (nx < 0 || nx >= width || ny < 0 || ny >= height) break;
|
||||
Piece target = getPieceAt(nx, ny);
|
||||
if (target == null) {
|
||||
moves.add(new int[]{nx, ny});
|
||||
} else {
|
||||
if (target.isWhite() != isWhite) {
|
||||
moves.add(new int[]{nx, ny});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return moves;
|
||||
}
|
||||
|
||||
private Piece findKing(boolean isWhite) {
|
||||
for (Piece piece : pieces) {
|
||||
if (piece.getType() == PieceType.King && piece.isWhite() == isWhite) {
|
||||
return piece;
|
||||
}
|
||||
}
|
||||
return null; // Should never happen in a valid chess game
|
||||
}
|
||||
}
|
||||
|
||||
private boolean moveWouldLeaveInCheck(Piece piece, int toX, int toY) {
|
||||
boolean isWhite = piece.isWhite();
|
||||
int fromX = piece.getX();
|
||||
int fromY = piece.getY();
|
||||
|
||||
// Create a temporary board to test the move
|
||||
Board tempBoard = new Board(width, height);
|
||||
|
||||
// Copy all pieces except the one being moved
|
||||
for (Piece p : pieces) {
|
||||
if (p.getX() == fromX && p.getY() == fromY) continue;
|
||||
if (p.getX() == toX && p.getY() == toY) continue; // Skip captured piece
|
||||
tempBoard.pieces.add(new Piece(p.getX(), p.getY(), p.isWhite(), p.getType()));
|
||||
}
|
||||
|
||||
// Add the moved piece
|
||||
tempBoard.pieces.add(new Piece(toX, toY, isWhite, piece.getType()));
|
||||
|
||||
// Find the king on the temporary board
|
||||
Piece king;
|
||||
if (piece.getType() == PieceType.King) {
|
||||
king = tempBoard.getPieceAt(toX, toY);
|
||||
} else {
|
||||
king = tempBoard.findKing(isWhite);
|
||||
}
|
||||
|
||||
if (king == null) return true; // Shouldn't happen, but prevent the move if it does
|
||||
|
||||
// Check if the king is in check
|
||||
return tempBoard.isSquareAttacked(king.getX(), king.getY(), !isWhite);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,106 +4,125 @@ import windowInterface.MyInterface;
|
|||
|
||||
public class Game extends Thread {
|
||||
|
||||
private AutoPlayer aiPlayer;
|
||||
private Board board;
|
||||
private AutoPlayer aiPlayer;
|
||||
private Board board;
|
||||
|
||||
private MyInterface mjf; //Reference to GUI interface
|
||||
private int COL_NUM = 8; // number of columns of a chess board
|
||||
private int LINE_NUM = 8; // number of rows of a chess board
|
||||
private int loopDelay = 250; // Delay in milisec between turns (AI speed)
|
||||
boolean[] activationAIFlags; //Flags to enable or disable AI for white or black
|
||||
private MyInterface mjf; //Reference to GUI interface
|
||||
private int COL_NUM = 8; // number of columns of a chess board
|
||||
private int LINE_NUM = 8; // number of rows of a chess board
|
||||
private int loopDelay = 250; // Delay in milisec between turns (AI speed)
|
||||
boolean[] activationAIFlags; //Flags to enable or disable AI for white or black
|
||||
|
||||
//Constructor to initialize the game with a GUI interface
|
||||
public Game(MyInterface mjfParam) {
|
||||
mjf = mjfParam;
|
||||
board = new Board(COL_NUM, LINE_NUM); // create a new chess board
|
||||
loopDelay = 250;
|
||||
activationAIFlags = new boolean[2]; // initialize AI flags: false by default
|
||||
aiPlayer = new AutoPlayer(); // create the AI player
|
||||
}
|
||||
// getter for the board width
|
||||
public int getWidth() {
|
||||
return board.getWidth();
|
||||
}
|
||||
//getter for the board height
|
||||
public int getHeight() {
|
||||
return board.getHeight();
|
||||
}
|
||||
// Main loop for the game thread (run continuously)
|
||||
public void run() {
|
||||
while(true) {
|
||||
aiPlayerTurn();
|
||||
mjf.update(board.getTurnNumber(), board.isTurnWhite());
|
||||
try {
|
||||
Thread.sleep(loopDelay);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
//Constructor to initialize the game with a GUI interface
|
||||
public Game(MyInterface mjfParam) {
|
||||
mjf = mjfParam;
|
||||
board = new Board(COL_NUM, LINE_NUM); // create a new chess board
|
||||
loopDelay = 250;
|
||||
activationAIFlags = new boolean[2]; // initialize AI flags: false by default
|
||||
aiPlayer = new AutoPlayer(); // create the AI player
|
||||
}
|
||||
|
||||
private boolean isAITurn() {
|
||||
return activationAIFlags[board.isTurnWhite()?1:0];
|
||||
}
|
||||
// getter for the board width
|
||||
public int getWidth() {
|
||||
return board.getWidth();
|
||||
}
|
||||
|
||||
private void aiPlayerTurn() {
|
||||
if(isAITurn()) {
|
||||
board.playMove(aiPlayer.computeBestMove(new Board(board)));
|
||||
}
|
||||
}
|
||||
//getter for the board height
|
||||
public int getHeight() {
|
||||
return board.getHeight();
|
||||
}
|
||||
|
||||
public void clickCoords(int x, int y) {
|
||||
int width = this.getWidth();
|
||||
int height = this.getHeight();
|
||||
if(0>x || 0>y || x>width || y>height) {
|
||||
System.out.println("Click out of bounds");
|
||||
return;
|
||||
}
|
||||
if(!isAITurn()) {
|
||||
board.userTouch(x, y);
|
||||
}
|
||||
// Main loop for the game thread (run continuously)
|
||||
public void run() {
|
||||
while(true) {
|
||||
aiPlayerTurn();
|
||||
// Pass the game message to the interface
|
||||
mjf.update(board.getTurnNumber(), board.isTurnWhite(), board.getGameMessage());
|
||||
try {
|
||||
Thread.sleep(loopDelay);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Get the game message (check/checkmate) from the board
|
||||
public String getGameMessage() {
|
||||
return board.getGameMessage();
|
||||
}
|
||||
|
||||
public void setPiece(boolean isWhite, PieceType type, int x, int y) {
|
||||
board.setPiece(isWhite, type, x, y);
|
||||
}
|
||||
private boolean isAITurn() {
|
||||
return activationAIFlags[board.isTurnWhite()?1:0];
|
||||
}
|
||||
|
||||
public String[] getFileRepresentation() {
|
||||
return board.toFileRep();
|
||||
}
|
||||
private void aiPlayerTurn() {
|
||||
if(isAITurn()) {
|
||||
board.playMove(aiPlayer.computeBestMove(new Board(board)));
|
||||
}
|
||||
}
|
||||
|
||||
public void setLoopDelay(int delay) {
|
||||
this.loopDelay = delay;
|
||||
}
|
||||
public void clickCoords(int x, int y) {
|
||||
int width = this.getWidth();
|
||||
int height = this.getHeight();
|
||||
if(0>x || 0>y || x>width || y>height) {
|
||||
System.out.println("Click out of bounds");
|
||||
return;
|
||||
}
|
||||
if(!isAITurn()) {
|
||||
board.userTouch(x, y);
|
||||
// After a move, update the interface with any game message
|
||||
mjf.update(board.getTurnNumber(), board.isTurnWhite(), board.getGameMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void setDefaultSetup() {
|
||||
board.cleanBoard();
|
||||
board.populateBoard();
|
||||
}
|
||||
public void setPiece(boolean isWhite, PieceType type, int x, int y) {
|
||||
board.setPiece(isWhite, type, x, y);
|
||||
}
|
||||
|
||||
public void setBoard(String[] array) {
|
||||
board = new Board(array);
|
||||
}
|
||||
public String[] getFileRepresentation() {
|
||||
return board.toFileRep();
|
||||
}
|
||||
|
||||
public Iterable<Piece> getPieces() {
|
||||
return board.getPieces();
|
||||
}
|
||||
public void setLoopDelay(int delay) {
|
||||
this.loopDelay = delay;
|
||||
}
|
||||
|
||||
public boolean isSelected(int x, int y) {
|
||||
return board.isSelected(x, y);
|
||||
}
|
||||
public void setDefaultSetup() {
|
||||
board.cleanBoard();
|
||||
board.populateBoard();
|
||||
// Reset any game messages when starting a new game
|
||||
mjf.update(board.getTurnNumber(), board.isTurnWhite(), "");
|
||||
}
|
||||
|
||||
public boolean isHighlighted(int x, int y) {
|
||||
return board.isHighlighted(x, y);
|
||||
}
|
||||
public void setBoard(String[] array) {
|
||||
board = new Board(array);
|
||||
// Check for check/checkmate when loading a board
|
||||
mjf.update(board.getTurnNumber(), board.isTurnWhite(), board.getGameMessage());
|
||||
}
|
||||
|
||||
public void undoLastMove() {
|
||||
board.undoLastMove();
|
||||
}
|
||||
public Iterable<Piece> getPieces() {
|
||||
return board.getPieces();
|
||||
}
|
||||
|
||||
public void toggleAI(boolean isWhite) {
|
||||
this.activationAIFlags[isWhite?1:0] = !this.activationAIFlags[isWhite?1:0];
|
||||
}
|
||||
public boolean isSelected(int x, int y) {
|
||||
return board.isSelected(x, y);
|
||||
}
|
||||
|
||||
public boolean isHighlighted(int x, int y) {
|
||||
return board.isHighlighted(x, y);
|
||||
}
|
||||
|
||||
public void undoLastMove() {
|
||||
if(board == null) {
|
||||
System.out.println("error: can't undo while no game present");
|
||||
} else {
|
||||
board.undoLastMove();
|
||||
// After undoing a move, update the interface with any game message
|
||||
mjf.update(board.getTurnNumber(), board.isTurnWhite(), board.getGameMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void toggleAI(boolean isWhite) {
|
||||
this.activationAIFlags[isWhite?1:0] = !this.activationAIFlags[isWhite?1:0];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,238 +32,260 @@ import javax.swing.JCheckBox;
|
|||
|
||||
public class MyInterface extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = -6840815447618468846L;
|
||||
private JPanel contentPane;
|
||||
private JLabel turnLabel;
|
||||
private JLabel borderLabel;
|
||||
private JLabel speedLabel;
|
||||
private JPanelChessBoard panelDraw;
|
||||
private Game game;
|
||||
private JLabel actionLabel;
|
||||
private JCheckBox chckbxBlackAI;
|
||||
private JCheckBox chckbxWhiteAI;
|
||||
private static final long serialVersionUID = -6840815447618468846L;
|
||||
private JPanel contentPane;
|
||||
private JLabel turnLabel;
|
||||
private JLabel borderLabel;
|
||||
private JLabel speedLabel;
|
||||
private JPanelChessBoard panelDraw;
|
||||
private Game game;
|
||||
private JLabel actionLabel;
|
||||
private JCheckBox chckbxBlackAI;
|
||||
private JCheckBox chckbxWhiteAI;
|
||||
|
||||
/**
|
||||
* Create the frame.
|
||||
*/
|
||||
public MyInterface() {
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setBounds(10, 10, 650, 650);
|
||||
contentPane = new JPanel();
|
||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
contentPane.setLayout(new BorderLayout(0, 0));
|
||||
setContentPane(contentPane);
|
||||
/**
|
||||
* Create the frame.
|
||||
*/
|
||||
public MyInterface() {
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setBounds(10, 10, 650, 650);
|
||||
contentPane = new JPanel();
|
||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
contentPane.setLayout(new BorderLayout(0, 0));
|
||||
setContentPane(contentPane);
|
||||
|
||||
JPanel panelTop = new JPanel();
|
||||
contentPane.add(panelTop, BorderLayout.NORTH);
|
||||
JPanel panelRight = new JPanel();
|
||||
contentPane.add(panelRight, BorderLayout.EAST);
|
||||
panelRight.setLayout(new GridLayout(4,1));
|
||||
JPanel panelTop = new JPanel();
|
||||
contentPane.add(panelTop, BorderLayout.NORTH);
|
||||
JPanel panelRight = new JPanel();
|
||||
contentPane.add(panelRight, BorderLayout.EAST);
|
||||
panelRight.setLayout(new GridLayout(4,1));
|
||||
|
||||
|
||||
actionLabel = new JLabel("Waiting For Start");
|
||||
panelTop.add(actionLabel);
|
||||
actionLabel = new JLabel("Waiting For Start");
|
||||
panelTop.add(actionLabel);
|
||||
|
||||
JButton btnGo = new JButton("Start/Restart");
|
||||
btnGo.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clicButtonStart();
|
||||
}
|
||||
});
|
||||
panelTop.add(btnGo);
|
||||
JButton btnGo = new JButton("Start/Restart");
|
||||
btnGo.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clicButtonStart();
|
||||
}
|
||||
});
|
||||
panelTop.add(btnGo);
|
||||
|
||||
turnLabel = new JLabel("Turn : X");
|
||||
panelTop.add(turnLabel);
|
||||
turnLabel = new JLabel("Turn : X");
|
||||
panelTop.add(turnLabel);
|
||||
|
||||
JButton btnLoad = new JButton("Load File");
|
||||
btnLoad.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clicLoadFileButton();
|
||||
}
|
||||
});
|
||||
panelRight.add(btnLoad);
|
||||
JButton btnLoad = new JButton("Load File");
|
||||
btnLoad.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clicLoadFileButton();
|
||||
}
|
||||
});
|
||||
panelRight.add(btnLoad);
|
||||
|
||||
JButton btnSave = new JButton("Save To File");
|
||||
btnSave.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clicSaveToFileButton();
|
||||
}
|
||||
});
|
||||
panelRight.add(btnSave);
|
||||
JButton btnSave = new JButton("Save To File");
|
||||
btnSave.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clicSaveToFileButton();
|
||||
}
|
||||
});
|
||||
panelRight.add(btnSave);
|
||||
|
||||
JButton btnAdder = new JButton("Add Piece");
|
||||
btnAdder.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clickButtonAdder();
|
||||
}
|
||||
});
|
||||
panelRight.add(btnAdder);
|
||||
JButton btnAdder = new JButton("Add Piece");
|
||||
btnAdder.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clickButtonAdder();
|
||||
}
|
||||
});
|
||||
panelRight.add(btnAdder);
|
||||
|
||||
JButton btnPieceSelector = new JButton("Piece Select");
|
||||
btnPieceSelector.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clickButtonSelector();
|
||||
}
|
||||
});
|
||||
panelRight.add(btnPieceSelector);
|
||||
JButton btnPieceSelector = new JButton("Piece Select");
|
||||
btnPieceSelector.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clickButtonSelector();
|
||||
}
|
||||
});
|
||||
panelRight.add(btnPieceSelector);
|
||||
|
||||
JButton btnUndo = new JButton("Undo");
|
||||
btnUndo.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clicUndoButton();
|
||||
}
|
||||
JButton btnUndo = new JButton("Undo");
|
||||
btnUndo.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clicUndoButton();
|
||||
}
|
||||
|
||||
});
|
||||
panelTop.add(btnUndo);
|
||||
});
|
||||
panelTop.add(btnUndo);
|
||||
|
||||
chckbxWhiteAI = new JCheckBox("WhiteAI");
|
||||
chckbxWhiteAI.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clicAIToggle(true);
|
||||
}
|
||||
chckbxWhiteAI = new JCheckBox("WhiteAI");
|
||||
chckbxWhiteAI.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clicAIToggle(true);
|
||||
}
|
||||
|
||||
});
|
||||
panelTop.add(chckbxWhiteAI);
|
||||
});
|
||||
panelTop.add(chckbxWhiteAI);
|
||||
|
||||
chckbxBlackAI = new JCheckBox("BlackAI");
|
||||
chckbxBlackAI.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clicAIToggle(false);
|
||||
}
|
||||
chckbxBlackAI = new JCheckBox("BlackAI");
|
||||
chckbxBlackAI.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clicAIToggle(false);
|
||||
}
|
||||
|
||||
});
|
||||
panelTop.add(chckbxBlackAI);
|
||||
});
|
||||
panelTop.add(chckbxBlackAI);
|
||||
|
||||
panelDraw = new JPanelChessBoard(this);
|
||||
contentPane.add(panelDraw, BorderLayout.CENTER);
|
||||
}
|
||||
panelDraw = new JPanelChessBoard(this);
|
||||
contentPane.add(panelDraw, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
public void setStepBanner(String s) {
|
||||
turnLabel.setText(s);
|
||||
}
|
||||
public void setStepBanner(String s) {
|
||||
turnLabel.setText(s);
|
||||
}
|
||||
|
||||
public void setBorderBanner(String s) {
|
||||
borderLabel.setText(s);
|
||||
}
|
||||
public void setBorderBanner(String s) {
|
||||
borderLabel.setText(s);
|
||||
}
|
||||
|
||||
public JPanelChessBoard getPanelDessin() {
|
||||
return panelDraw;
|
||||
}
|
||||
public JPanelChessBoard getPanelDessin() {
|
||||
return panelDraw;
|
||||
}
|
||||
|
||||
public void instantiateSimu() {
|
||||
if(game==null) {
|
||||
game = new Game(this);
|
||||
panelDraw.setGame(game);
|
||||
game.start();
|
||||
}
|
||||
}
|
||||
public void instantiateSimu() {
|
||||
if(game==null) {
|
||||
game = new Game(this);
|
||||
panelDraw.setGame(game);
|
||||
game.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void clicButtonStart() {
|
||||
this.instantiateSimu();
|
||||
game.setDefaultSetup();
|
||||
}
|
||||
public void clicButtonStart() {
|
||||
this.instantiateSimu();
|
||||
game.setDefaultSetup();
|
||||
}
|
||||
|
||||
public void clickButtonAdder() {
|
||||
panelDraw.toggleAdderMode();
|
||||
}
|
||||
public void clickButtonSelector() {
|
||||
panelDraw.togglePieceSelector();
|
||||
}
|
||||
public void clickButtonAdder() {
|
||||
panelDraw.toggleAdderMode();
|
||||
}
|
||||
public void clickButtonSelector() {
|
||||
panelDraw.togglePieceSelector();
|
||||
}
|
||||
|
||||
private void clicUndoButton() {
|
||||
if(game == null) {
|
||||
System.out.println("error : can't undo while no game present");
|
||||
} else {
|
||||
game.undoLastMove();
|
||||
}
|
||||
private void clicUndoButton() {
|
||||
if(game == null) {
|
||||
System.out.println("error : can't undo while no game present");
|
||||
} else {
|
||||
game.undoLastMove();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public void clicAIToggle(boolean isWhite) {
|
||||
if(game == null) {
|
||||
System.out.println("error : can't activate AI while no game present");
|
||||
if(isWhite) {
|
||||
chckbxWhiteAI.setSelected(false);
|
||||
}else {
|
||||
chckbxBlackAI.setSelected(false);
|
||||
}
|
||||
} else {
|
||||
game.toggleAI(isWhite);
|
||||
}
|
||||
}
|
||||
public void clicAIToggle(boolean isWhite) {
|
||||
if(game == null) {
|
||||
System.out.println("error : can't activate AI while no game present");
|
||||
if(isWhite) {
|
||||
chckbxWhiteAI.setSelected(false);
|
||||
}else {
|
||||
chckbxBlackAI.setSelected(false);
|
||||
}
|
||||
} else {
|
||||
game.toggleAI(isWhite);
|
||||
}
|
||||
}
|
||||
|
||||
public void clicLoadFileButton() {
|
||||
Game loadedSim = new Game(this);
|
||||
String fileName=SelectFile();
|
||||
LinkedList<String> lines = new LinkedList<String>();
|
||||
if (fileName.length()>0) {
|
||||
try {
|
||||
BufferedReader fileContent = new BufferedReader(new FileReader(fileName));
|
||||
String line = fileContent.readLine();
|
||||
int colorID = 0;
|
||||
while (line != null) {
|
||||
lines.add(line);
|
||||
line = fileContent.readLine();
|
||||
}
|
||||
loadedSim.setBoard(Arrays.stream(lines.toArray()).map(Object::toString).toArray(String[]::new));
|
||||
fileContent.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
game = loadedSim;
|
||||
panelDraw.setGame(game);
|
||||
this.repaint();
|
||||
}
|
||||
}
|
||||
public void clicLoadFileButton() {
|
||||
Game loadedSim = new Game(this);
|
||||
String fileName=SelectFile();
|
||||
LinkedList<String> lines = new LinkedList<String>();
|
||||
if (fileName.length()>0) {
|
||||
try {
|
||||
BufferedReader fileContent = new BufferedReader(new FileReader(fileName));
|
||||
String line = fileContent.readLine();
|
||||
int colorID = 0;
|
||||
while (line != null) {
|
||||
lines.add(line);
|
||||
line = fileContent.readLine();
|
||||
}
|
||||
loadedSim.setBoard(Arrays.stream(lines.toArray()).map(Object::toString).toArray(String[]::new));
|
||||
fileContent.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
game = loadedSim;
|
||||
panelDraw.setGame(game);
|
||||
this.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
public void clicSaveToFileButton() {
|
||||
String fileName=SelectFile();
|
||||
if (fileName.length()>0) {
|
||||
String[] content = game.getFileRepresentation();
|
||||
writeFile(fileName, content);
|
||||
}
|
||||
}
|
||||
public void clicSaveToFileButton() {
|
||||
String fileName=SelectFile();
|
||||
if (fileName.length()>0) {
|
||||
String[] content = game.getFileRepresentation();
|
||||
writeFile(fileName, content);
|
||||
}
|
||||
}
|
||||
|
||||
public String SelectFile() {
|
||||
String s;
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
chooser.setCurrentDirectory(new java.io.File("."));
|
||||
chooser.setDialogTitle("Choose a file");
|
||||
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
|
||||
chooser.setAcceptAllFileFilterUsed(true);
|
||||
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
|
||||
s=chooser.getSelectedFile().toString();
|
||||
} else {
|
||||
System.out.println("No Selection ");
|
||||
s="";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
public String SelectFile() {
|
||||
String s;
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
chooser.setCurrentDirectory(new java.io.File("."));
|
||||
chooser.setDialogTitle("Choose a file");
|
||||
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
|
||||
chooser.setAcceptAllFileFilterUsed(true);
|
||||
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
|
||||
s=chooser.getSelectedFile().toString();
|
||||
} else {
|
||||
System.out.println("No Selection ");
|
||||
s="";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public void writeFile(String fileName, String[] content) {
|
||||
FileWriter csvWriter;
|
||||
try {
|
||||
csvWriter = new FileWriter(fileName);
|
||||
for (String row : content) {
|
||||
csvWriter.append(row);
|
||||
csvWriter.append("\n");
|
||||
}
|
||||
csvWriter.flush();
|
||||
csvWriter.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public void writeFile(String fileName, String[] content) {
|
||||
FileWriter csvWriter;
|
||||
try {
|
||||
csvWriter = new FileWriter(fileName);
|
||||
for (String row : content) {
|
||||
csvWriter.append(row);
|
||||
csvWriter.append("\n");
|
||||
}
|
||||
csvWriter.flush();
|
||||
csvWriter.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void update(int turnCount, boolean turnIsWhite) {
|
||||
turnLabel.setText("Turn : "+turnCount+", "+ (turnIsWhite?"White":"Black"));
|
||||
actionLabel.setText(panelDraw.isPieceAdderMode()?"Adding Piece":
|
||||
(panelDraw.isPieceSelectorMode()?"Selecting Piece to Add":
|
||||
"Playing"));
|
||||
this.repaint();
|
||||
}
|
||||
/**
|
||||
* Updates the interface with the game's current state and displays any game message
|
||||
* @param turnCount The current turn number
|
||||
* @param turnIsWhite True if it's white's turn, false if it's black's
|
||||
* @param gameMessage Game status message (check/checkmate)
|
||||
*/
|
||||
public void update(int turnCount, boolean turnIsWhite, String gameMessage) {
|
||||
turnLabel.setText("Turn : " + turnCount + ", " + (turnIsWhite ? "White" : "Black"));
|
||||
|
||||
public void eraseLabels() {
|
||||
this.setStepBanner("Turn : X");
|
||||
}
|
||||
// If we have a game message (check/checkmate), display it
|
||||
if (gameMessage != null && !gameMessage.isEmpty()) {
|
||||
actionLabel.setText(gameMessage);
|
||||
} else {
|
||||
// Otherwise display the normal interface state
|
||||
actionLabel.setText(panelDraw.isPieceAdderMode() ? "Adding Piece" :
|
||||
(panelDraw.isPieceSelectorMode() ? "Selecting Piece to Add" : "Playing"));
|
||||
}
|
||||
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy update method for compatibility
|
||||
* @param turnCount The current turn number
|
||||
* @param turnIsWhite True if it's white's turn, false if it's black's
|
||||
*/
|
||||
public void update(int turnCount, boolean turnIsWhite) {
|
||||
// Call the new update method with an empty game message
|
||||
update(turnCount, turnIsWhite, "");
|
||||
}
|
||||
|
||||
public void eraseLabels() {
|
||||
this.setStepBanner("Turn : X");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue