Compare commits

..

2 Commits

Author SHA1 Message Date
Valentine GIRAL 15fc3a6851 victory checking 2025-05-16 12:20:35 +02:00
Valentine GIRAL f854687c3e display victory 2025-05-16 12:17:11 +02:00
6 changed files with 347 additions and 78 deletions

34
Test.board Normal file
View File

@ -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

View File

@ -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;
@ -43,6 +43,9 @@ 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;
@ -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();
}
}

View File

@ -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)));
}
}

View File

@ -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 = "";
}
}

View File

@ -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;
}
}

33
test2.board Normal file
View File

@ -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