Compare commits
2 Commits
5d5c023f1a
...
15fc3a6851
| Author | SHA1 | Date |
|---|---|---|
|
|
15fc3a6851 | |
|
|
f854687c3e |
|
|
@ -0,0 +1,34 @@
|
|||
8,white
|
||||
8,8
|
||||
Rook,0,0,B
|
||||
Knight,1,0,B
|
||||
Bishop,2,0,B
|
||||
Queen,3,0,B
|
||||
King,4,0,B
|
||||
Bishop,5,0,B
|
||||
Knight,6,0,B
|
||||
Rook,7,0,B
|
||||
Pawn,0,1,B
|
||||
Pawn,1,1,B
|
||||
Pawn,2,1,B
|
||||
Pawn,4,1,B
|
||||
Pawn,5,1,B
|
||||
Pawn,6,2,B
|
||||
Pawn,7,2,B
|
||||
Pawn,3,3,B
|
||||
Pawn,3,4,W
|
||||
Pawn,7,5,W
|
||||
Pawn,0,6,W
|
||||
Pawn,1,6,W
|
||||
Pawn,2,6,W
|
||||
Pawn,4,6,W
|
||||
Pawn,5,6,W
|
||||
Pawn,6,6,W
|
||||
Rook,7,6,W
|
||||
Rook,0,7,W
|
||||
Knight,1,7,W
|
||||
Bishop,2,7,W
|
||||
Queen,3,7,W
|
||||
King,4,7,W
|
||||
Bishop,5,7,W
|
||||
Knight,6,7,W
|
||||
|
|
@ -11,8 +11,8 @@ public class Board {
|
|||
private boolean turnWhite=true; // True if it's White's turn, False if it's Black's turn
|
||||
private ArrayList<int[]> highlightedPositions = new ArrayList<>(); // List containing all board positions
|
||||
private ArrayList<MoveRecord> moveHistory = new ArrayList<>(); // List to store move history
|
||||
private String winnerMessage;
|
||||
private boolean suppressCheckmateCheck = false;
|
||||
private GameResult gameResult = new GameResult();
|
||||
|
||||
private boolean inBounds(int x, int y) {
|
||||
// Verify the bounds of the board
|
||||
return x >= 0 && y >= 0 && x < col && y < line;
|
||||
|
|
@ -42,7 +42,10 @@ public class Board {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public GameResult getGameResult() {
|
||||
return gameResult;
|
||||
}
|
||||
|
||||
public Board(int colNum, int lineNum) {
|
||||
this.col=colNum;
|
||||
|
|
@ -115,6 +118,11 @@ public class Board {
|
|||
}
|
||||
}
|
||||
this.turnNumber=0;
|
||||
this.turnWhite=true;
|
||||
|
||||
// Reset game result
|
||||
this.gameResult.reset();
|
||||
|
||||
System.out.println("Board cleaned. All pieces removed.");
|
||||
}
|
||||
|
||||
|
|
@ -156,6 +164,11 @@ public class Board {
|
|||
}
|
||||
|
||||
public void userTouch(int x, int y) {
|
||||
// If game is already over, prevent further moves
|
||||
if (gameResult.isGameOver()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Case 1: No position is selected
|
||||
if (selectedPosition==null) {
|
||||
Piece clickedPiece = board[y][x];
|
||||
|
|
@ -195,6 +208,9 @@ public class Board {
|
|||
// Update turn
|
||||
this.turnNumber++;
|
||||
this.turnWhite = !this.turnWhite;
|
||||
|
||||
// Check for victory after the move
|
||||
gameResult.checkForVictory(this);
|
||||
}
|
||||
|
||||
// Deselect the position after moving
|
||||
|
|
@ -428,7 +444,12 @@ public class Board {
|
|||
}
|
||||
|
||||
public void playMove(Move move) {
|
||||
//get current piece coordinate
|
||||
// If game is already over, prevent further moves
|
||||
if (gameResult.isGameOver()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//gets current piece coordinate
|
||||
int fromX = move.piece.getX();
|
||||
int fromY = move.piece.getY();
|
||||
int toX = move.toX;
|
||||
|
|
@ -437,7 +458,7 @@ public class Board {
|
|||
Piece movingPiece = move.piece;
|
||||
Piece capturedPiece = board[toY][toX]; // capture if any
|
||||
|
||||
moveHistory.add(new MoveRecord(movingPiece, capturedPiece, fromX, fromY, toX, toY,turnNumber, turnWhite));
|
||||
moveHistory.add(new MoveRecord(movingPiece, capturedPiece, fromX, fromY, toX, toY,turnNumber, turnWhite));
|
||||
//Remove the piece from the original position
|
||||
board[fromY][fromX] = null;
|
||||
//Update the internal position of the piece
|
||||
|
|
@ -450,66 +471,18 @@ public class Board {
|
|||
this.turnWhite = !this.turnWhite;
|
||||
this.turnNumber++;
|
||||
|
||||
// Check for victory after the move
|
||||
gameResult.checkForVictory(this);
|
||||
|
||||
//Clear selection/highlight
|
||||
this.selectedPosition = null;
|
||||
this.highlightedPositions.clear();
|
||||
|
||||
if (!suppressCheckmateCheck && isCheckmate(!turnWhite)) {
|
||||
winnerMessage = turnWhite ? "White is the winner" : "Black is the winner";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
public boolean isKingInCheck(boolean kingIsWhite) {
|
||||
int kingX = -1, kingY = -1;
|
||||
|
||||
//Find the king
|
||||
for (Piece p : getPieces()) {
|
||||
if (p.getType() == PieceType.King && p.isWhite() == kingIsWhite) {
|
||||
kingX = p.getX();
|
||||
kingY = p.getY();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (kingX == -1)
|
||||
return false;
|
||||
for (Piece p : getPieces()) {
|
||||
if (p.isWhite() != kingIsWhite) {
|
||||
for (int[] m : getValidMoves(p)) {
|
||||
if (m[0] == kingX && m[1] == kingY) {
|
||||
return true; //King in check
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean isCheckmate(boolean playerWhite) {
|
||||
if (!isKingInCheck(playerWhite))
|
||||
return false;
|
||||
for (Piece p : getPieces()) {
|
||||
if (p.isWhite() == playerWhite) {
|
||||
for (int[] move : getValidMoves(p)) {
|
||||
//simulate the move
|
||||
Board copy = new Board(this);
|
||||
copy.suppressCheckmateCheck = true;
|
||||
Piece simPiece = copy.board[p.getY()][p.getX()];
|
||||
Move m = new Move(simPiece, move[0], move[1]);
|
||||
copy.playMove(m);
|
||||
|
||||
if (!copy.isKingInCheck(playerWhite)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public String getWinnerMessage() {
|
||||
return winnerMessage;
|
||||
}
|
||||
public void setWinnerMessage(String message) {
|
||||
this.winnerMessage = message;
|
||||
}
|
||||
|
||||
//manually checks for victory if needed
|
||||
public boolean isCheckmate() {
|
||||
gameResult.checkForVictory(this);
|
||||
return gameResult.isGameOver();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,22 +49,7 @@ public class Game extends Thread {
|
|||
|
||||
private void aiPlayerTurn() {
|
||||
if(isAITurn()) {
|
||||
Move move = aiPlayer.computeBestMove(new Board(board));
|
||||
|
||||
if (move != null) {
|
||||
board.playMove(move);
|
||||
}
|
||||
else {
|
||||
if (board.isKingInCheck(board.isTurnWhite())) {
|
||||
System.out.println((board.isTurnWhite() ? "White" : "Black") + "is checkmated!");
|
||||
board.setWinnerMessage((!board.isTurnWhite() ? "White" : "Black") + "wins by checkmate!");
|
||||
|
||||
}
|
||||
else {
|
||||
System.out.println("It's a draw");
|
||||
board.setWinnerMessage("Draw!");
|
||||
}
|
||||
}
|
||||
board.playMove(aiPlayer.computeBestMove(new Board(board)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
package backend;
|
||||
|
||||
// Class to track the outcome of a chess game
|
||||
public class GameResult {
|
||||
private boolean gameOver = false;
|
||||
private boolean whiteWon = false;
|
||||
private boolean blackWon = false;
|
||||
private String message = "";
|
||||
|
||||
// Checks for game victory after a move is made
|
||||
public GameResult checkForVictory(Board board) {
|
||||
// If game is already over, don't check again
|
||||
if (gameOver) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// Check if White has won
|
||||
if (VictoryChecker.checkVictory(board, true)) {
|
||||
gameOver = true;
|
||||
whiteWon = true;
|
||||
message = "White wins by checkmate!";
|
||||
System.out.println(message);
|
||||
}
|
||||
// Check if Black has won
|
||||
else if (VictoryChecker.checkVictory(board, false)) {
|
||||
gameOver = true;
|
||||
blackWon = true;
|
||||
message = "Black wins by checkmate!";
|
||||
System.out.println(message);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isGameOver() {
|
||||
return gameOver;
|
||||
}
|
||||
|
||||
public boolean hasWhiteWon() {
|
||||
return whiteWon;
|
||||
}
|
||||
|
||||
public boolean hasBlackWon() {
|
||||
return blackWon;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
// Reset the game result to start a new game
|
||||
public void reset() {
|
||||
gameOver = false;
|
||||
whiteWon = false;
|
||||
blackWon = false;
|
||||
message = "";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
package backend;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class VictoryChecker {
|
||||
|
||||
// For debugging
|
||||
private static final boolean DEBUG = true;
|
||||
|
||||
// Check if a player has won the chess game via checkmate
|
||||
|
||||
public static boolean checkVictory(Board board, boolean isWhitePlayer) {
|
||||
// The opponent is the one who would be checkmated so opposite color
|
||||
boolean opponentColor = !isWhitePlayer;
|
||||
|
||||
// Debug info
|
||||
if (DEBUG) {
|
||||
System.out.println("Checking if " + (isWhitePlayer ? "White" : "Black") + " has won...");
|
||||
}
|
||||
|
||||
// Find the opponent's king
|
||||
int[] kingPosition = findKingPosition(board, opponentColor);
|
||||
if (kingPosition == null) {
|
||||
if (DEBUG) {
|
||||
System.err.println((opponentColor ? "White" : "Black") + " king not found on the board!");
|
||||
}
|
||||
// If opponent's king is not on board, the player has won
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if opponent's king is in check
|
||||
boolean kingInCheck = isKingInCheck(board, opponentColor, kingPosition);
|
||||
if (!kingInCheck) {
|
||||
if (DEBUG) {
|
||||
System.out.println((opponentColor ? "White" : "Black") + " king is not in check, no checkmate.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println((opponentColor ? "White" : "Black") + " king is in check.");
|
||||
}
|
||||
|
||||
// Check if opponent has any legal moves left
|
||||
boolean hasLegalMoves = hasLegalMoves(board, opponentColor);
|
||||
if (hasLegalMoves) {
|
||||
if (DEBUG) {
|
||||
System.out.println((opponentColor ? "White" : "Black") + " has legal moves available, no checkmate.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the king is in check and there are no legal moves, it's checkmate
|
||||
if (DEBUG) {
|
||||
System.out.println("CHECKMATE! " + (isWhitePlayer ? "White" : "Black") + " wins!");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//Determine if a player's king is in check
|
||||
|
||||
private static boolean isKingInCheck(Board board, boolean isWhite, int[] kingPosition) {
|
||||
// Get all opponent pieces
|
||||
boolean opponentColor = !isWhite;
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println("Checking if " + (isWhite ? "White" : "Black") +
|
||||
" king at [" + kingPosition[0] + "," + kingPosition[1] + "] is in check");
|
||||
}
|
||||
|
||||
for (Piece piece : board.getPieces()) {
|
||||
if (piece.isWhite() == opponentColor) {
|
||||
// Get valid moves for this opponent piece
|
||||
ArrayList<int[]> validMoves = board.getValidMoves(piece);
|
||||
|
||||
for (int[] move : validMoves) {
|
||||
// If the move targets the king's position, the king is in check
|
||||
if (move[0] == kingPosition[0] && move[1] == kingPosition[1]) {
|
||||
if (DEBUG) {
|
||||
System.out.println("King is attacked by " + piece.getType() +
|
||||
" at [" + piece.getX() + "," + piece.getY() + "]");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//Find the position of a player's king on the board
|
||||
private static int[] findKingPosition(Board board, boolean isWhite) {
|
||||
if (DEBUG) {
|
||||
System.out.println("Looking for " + (isWhite ? "White" : "Black") + " king");
|
||||
}
|
||||
|
||||
for (Piece piece : board.getPieces()) {
|
||||
if (piece.getType() == PieceType.King && piece.isWhite() == isWhite) {
|
||||
if (DEBUG) {
|
||||
System.out.println("Found king at [" + piece.getX() + "," + piece.getY() + "]");
|
||||
}
|
||||
return new int[] {piece.getX(), piece.getY()};
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
System.err.println((isWhite ? "White" : "Black") + " king not found!");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if a player has any legal moves available
|
||||
private static boolean hasLegalMoves(Board board, boolean isWhite) {
|
||||
if (DEBUG) {
|
||||
System.out.println("Checking if " + (isWhite ? "White" : "Black") + " has any legal moves");
|
||||
}
|
||||
|
||||
int legalMovesCount = 0;
|
||||
|
||||
// For each piece of the player
|
||||
for (Piece piece : board.getPieces()) {
|
||||
if (piece.isWhite() == isWhite) {
|
||||
// Get all valid moves for this piece
|
||||
ArrayList<int[]> validMoves = board.getValidMoves(piece);
|
||||
|
||||
for (int[] move : validMoves) {
|
||||
// Check if this move would still leave the king in check
|
||||
if (isLegalMoveWithoutCheck(board, piece, move[0], move[1], isWhite)) {
|
||||
legalMovesCount++;
|
||||
if (DEBUG) {
|
||||
System.out.println("Legal move found: " + piece.getType() +
|
||||
" from [" + piece.getX() + "," + piece.getY() + "] to [" +
|
||||
move[0] + "," + move[1] + "]");
|
||||
// We found at least one legal move, can return early
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println("Total legal moves found: " + legalMovesCount);
|
||||
}
|
||||
|
||||
return legalMovesCount > 0;
|
||||
}
|
||||
|
||||
// Check if a move is legal considering check rules
|
||||
private static boolean isLegalMoveWithoutCheck(Board board, Piece piece, int toX, int toY, boolean isWhite) {
|
||||
int fromX = piece.getX();
|
||||
int fromY = piece.getY();
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println("Testing move: " + piece.getType() +
|
||||
" from [" + fromX + "," + fromY + "] to [" + toX + "," + toY + "]");
|
||||
}
|
||||
|
||||
// Create a copy of the board to simulate the move
|
||||
Board simulatedBoard = new Board(board);
|
||||
|
||||
// Execute the move on the simulated board
|
||||
simulatedBoard.movePiece(fromX, fromY, toX, toY);
|
||||
|
||||
// Find the king's position after the move
|
||||
int[] kingPos = findKingPosition(simulatedBoard, isWhite);
|
||||
if (kingPos == null) {
|
||||
// This shouldn't happen unless the moved piece was the king and it was captured somehow
|
||||
if (DEBUG) {
|
||||
System.err.println("King disappeared after simulated move!");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the king is in check after the move
|
||||
boolean kingInCheck = isKingInCheck(simulatedBoard, isWhite, kingPos);
|
||||
|
||||
if (DEBUG && !kingInCheck) {
|
||||
System.out.println("Move is legal (doesn't leave king in check)");
|
||||
}
|
||||
|
||||
return !kingInCheck;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
6,white
|
||||
8,8
|
||||
Rook,0,0,B
|
||||
Knight,1,0,B
|
||||
Queen,3,0,B
|
||||
King,4,0,B
|
||||
Bishop,5,0,B
|
||||
Knight,6,0,B
|
||||
Rook,7,0,B
|
||||
Pawn,0,1,B
|
||||
Pawn,1,1,B
|
||||
Pawn,4,1,B
|
||||
Pawn,5,1,B
|
||||
Pawn,6,1,B
|
||||
Pawn,7,1,B
|
||||
Pawn,2,3,B
|
||||
Pawn,3,3,B
|
||||
Bishop,5,3,B
|
||||
Pawn,4,4,W
|
||||
Pawn,0,6,W
|
||||
Pawn,1,6,W
|
||||
Pawn,2,6,W
|
||||
Pawn,3,6,W
|
||||
Pawn,6,6,W
|
||||
Pawn,7,6,W
|
||||
Rook,0,7,W
|
||||
Knight,1,7,W
|
||||
Bishop,2,7,W
|
||||
Queen,3,7,W
|
||||
King,4,7,W
|
||||
Bishop,5,7,W
|
||||
Knight,6,7,W
|
||||
Rook,7,7,W
|
||||
Loading…
Reference in New Issue