Compare commits
No commits in common. "main" and "master" have entirely different histories.
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||
<attributes>
|
||||
<attribute name="module" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
|
@ -1,26 +1 @@
|
|||
# ---> Java
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
replay_pid*
|
||||
|
||||
/bin/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>OOP_1A6_Project</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.release=enabled
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
BR,BN,BB,BQ,BK,BB,BN,BR
|
||||
BP,BP,BP,BP,BP,BP,BP,BP
|
||||
, , , , , , ,
|
||||
, , , , , , ,
|
||||
, , , , , , ,
|
||||
, , , , , , ,
|
||||
WP,WP,WP,WP,WP,WP,WP,WP
|
||||
WR,WN,WB,WQ,WK,WB,WN,WR
|
||||
W
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 954 B |
|
|
@ -0,0 +1,22 @@
|
|||
import backend.Board;
|
||||
import backend.Move;
|
||||
import backend.Piece;
|
||||
import backend.PieceType;
|
||||
import windowInterface.MyInterface;
|
||||
|
||||
|
||||
public class Main {
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
// testing :
|
||||
Board testBoard = new Board(8, 8);
|
||||
testBoard.populateBoard();
|
||||
System.out.println(testBoard.toString());
|
||||
|
||||
// launches graphical interface :
|
||||
MyInterface mjf = new MyInterface();
|
||||
mjf.setVisible(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
package backend;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/*
|
||||
Task: Chess Autoplayer Implementation
|
||||
|
||||
Class name: AutoPlayer
|
||||
|
||||
Methods name:
|
||||
- computeBestMove(Board board) - Computes and returns the best move for the current player according to a simple priority heuristic; returns null if no legal move or if a king would be captured.
|
||||
- resetLastMovedPiece() - Resets the tracking of the last moved piece; to be called after a human move.
|
||||
|
||||
Methods output:
|
||||
- The best possible move for the AI player given the current board state, or null if no legal move exists.
|
||||
- Resets internal state for move tracking after a human move.
|
||||
|
||||
Methods works:
|
||||
- Analyzes all possible moves for the current player.
|
||||
- Avoids repeating the previous piece moved by the autoplayer.
|
||||
- Prevents illegal moves that would result in capturing the king.
|
||||
- Prioritizes moves that put the opposing king in check or bring pieces closer to the opposing king.
|
||||
- Randomly selects among equal-priority moves.
|
||||
- Tracks the last moved piece to avoid repetitive AI behavior.
|
||||
|
||||
Authors: Bédier Jérôme jerome.bedier@ecam.fr, Gardern Florian florian.gardner@ecam.fr, Leng Sidden sidden.leng@ecam.fr
|
||||
Date: 05/21/2025
|
||||
*/
|
||||
|
||||
public class AutoPlayer {
|
||||
private Integer lastMovedPieceHash = null; // Track the last moved piece
|
||||
|
||||
public Move computeBestMove(Board board) {
|
||||
// Count kings
|
||||
int kingCount = 0;
|
||||
for (Piece piece : board.getPieces()) {
|
||||
if (piece.getType() == PieceType.King) kingCount++;
|
||||
}
|
||||
|
||||
ArrayList<Piece> pieces = board.getPieces();
|
||||
boolean isWhite = board.isTurnWhite();
|
||||
int bestPriority = Integer.MIN_VALUE;
|
||||
List<Move> bestMoves = new ArrayList<>();
|
||||
List<Integer> movePieceHashes = new ArrayList<>();
|
||||
|
||||
for (Piece piece : pieces) {
|
||||
if (piece.isWhite() == isWhite) {
|
||||
// Skip if this piece was just moved last time
|
||||
int pieceHash = (piece.getX()*31 + piece.getY()) * (piece.isWhite() ? 1 : -1);
|
||||
if (lastMovedPieceHash != null && pieceHash == lastMovedPieceHash) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ArrayList<Move> moves = board.getLegalMoves(piece);
|
||||
for (Move move : moves) {
|
||||
// Prevent king captures: simulate move and skip if enemy king would be removed
|
||||
Board copy = new Board(board);
|
||||
copy.playMove(move);
|
||||
int kingsAfterMove = 0;
|
||||
for (Piece p : copy.getPieces()) {
|
||||
if (p.getType() == PieceType.King) kingsAfterMove++;
|
||||
}
|
||||
if (kingsAfterMove < 2) {
|
||||
// This move would remove a king, so stop AI completely
|
||||
System.out.println("Game Over! Attempted king capture. AutoPlayer will stop.");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Prevent AI from moving into check or checkmate
|
||||
if (copy.isKingInCheck(isWhite) || copy.isCheckmate(isWhite)) {
|
||||
continue; // Skip moves that leave AI in check or checkmate
|
||||
}
|
||||
|
||||
// Check if move results in checkmate for the opponent
|
||||
if (copy.isCheckmate(!isWhite)) {
|
||||
System.out.println("Checkmate! AutoPlayer has won.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Piece enemyKing = copy.findKing(!isWhite);
|
||||
int dist = Math.abs(move.getToX() - enemyKing.getX()) + Math.abs(move.getToY() - enemyKing.getY());
|
||||
int priority = -dist;
|
||||
|
||||
// Bonus if move puts king in check
|
||||
if (copy.isKingInCheck(!isWhite)) {
|
||||
priority += 1000;
|
||||
}
|
||||
|
||||
if (priority > bestPriority) {
|
||||
bestPriority = priority;
|
||||
bestMoves.clear();
|
||||
bestMoves.add(move);
|
||||
movePieceHashes.clear();
|
||||
movePieceHashes.add(pieceHash);
|
||||
} else if (priority == bestPriority) {
|
||||
bestMoves.add(move);
|
||||
movePieceHashes.add(pieceHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestMoves.isEmpty()) {
|
||||
System.out.println("Game Over! No legal moves for autoplayer.");
|
||||
return null;
|
||||
}
|
||||
// Randomly pick among best moves
|
||||
Random rand = new Random();
|
||||
int idx = rand.nextInt(bestMoves.size());
|
||||
lastMovedPieceHash = movePieceHashes.get(idx);
|
||||
return bestMoves.get(idx);
|
||||
}
|
||||
|
||||
// Call this after a player move to reset tracking
|
||||
public void resetLastMovedPiece() {
|
||||
lastMovedPieceHash = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,786 @@
|
|||
package backend;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
/*
|
||||
Task: Chess Game Board Implementation
|
||||
|
||||
Class name: Board
|
||||
|
||||
Methods name:
|
||||
- getWidth() - Returns the width of the board as an integer
|
||||
- getHeight() - Returns the height of the board as an integer
|
||||
- getTurnNumber() - Returns the current turn number as an integer
|
||||
- isTurnWhite() - Returns true if it's white's turn, false if it's black's turn
|
||||
- setPiece() - Places a piece on the board at specified coordinates, returns nothing
|
||||
- populateBoard() - Sets up the initial chess position with all pieces, returns nothing
|
||||
- cleanBoard() - Resets the board and turn counter to initial state, returns nothing
|
||||
- toString() - Creates a string representation of the board with piece positions and turn info
|
||||
- getPieces() - Returns ArrayList containing all pieces currently on the board
|
||||
- userTouch() - Handles user interaction with the board (selecting/moving pieces), returns nothing
|
||||
- isSelected() - Returns true if the specified square is currently selected, false otherwise
|
||||
- toFileRep() - Returns a String array representation of the board for saving
|
||||
- Board(String[] fileRepresentation) - Constructor that loads a board from string array, returns nothing
|
||||
- calculateValidMoves() - Calculates and highlights valid moves for selected piece, returns nothing
|
||||
- isHighlighted() - Returns true if the specified square is highlighted as a legal move
|
||||
- clearHighlights() - Clears all highlighted squares, returns nothing
|
||||
- highlightLegalMoves() - Highlights all legal moves for a given piece, returns nothing
|
||||
- getLegalMoves() - Returns ArrayList of all legal moves for a given piece
|
||||
- handlePawnMoves() - Adds all legal pawn moves to the moves list, returns nothing
|
||||
- checkPawnCapture() - Checks if a pawn can capture diagonally, returns nothing
|
||||
- handleKnightMoves() - Adds all legal knight moves to the moves list, returns nothing
|
||||
- handleSlidingMoves() - Adds all legal sliding moves (bishop/rook/queen) to the moves list, returns nothing
|
||||
- handleKingMoves() - Adds all legal king moves to the moves list, returns nothing
|
||||
- isValidPosition() - Returns true if the coordinates are within the board boundaries
|
||||
- isEmpty() - Returns true if the specified square is empty
|
||||
- isEnemy() - Returns true if the specified square contains an enemy piece
|
||||
- isAlly() - Returns true if the specified square contains a friendly piece
|
||||
- undoLastMove() - Reverts to the previous board state, returns nothing
|
||||
- Board(Board board) - Copy constructor that creates a duplicate board, returns nothing
|
||||
- playMove() - Executes a chess move and updates the board state, returns nothing
|
||||
- findKing() - Returns the Piece object of the king of specified color
|
||||
- isKingInCheck() - Returns true if the king of specified color is in check
|
||||
- promotePawn() - Returns a new Queen piece to replace a pawn at the end rank
|
||||
- highlightKingInCheck() - Highlights kings that are in check, returns nothing
|
||||
- canSelectPieceWhenInCheck() - Returns true if the piece can be selected when king is in check
|
||||
- isSquareAttacked() - Returns true if the specified square is under attack by specified color
|
||||
- filterMovesForCheck() - Removes moves that would leave king in check, returns nothing
|
||||
|
||||
Methods output:
|
||||
- Board dimensions (width, height)
|
||||
- Current turn number and active player
|
||||
- String representation of the chess board
|
||||
- Collection of all pieces on the board
|
||||
- Selected piece status
|
||||
- Highlighted squares showing legal moves
|
||||
- File representation for saving/loading
|
||||
- Move validation results
|
||||
- King check status
|
||||
- Game state information
|
||||
|
||||
Methods works:
|
||||
- Board initialization and management
|
||||
- Chess piece movement and validation
|
||||
- Game state tracking (turns, check conditions)
|
||||
- Special chess rules (promotion, en passant)
|
||||
- Check and checkmate detection
|
||||
- Move history and undo functionality
|
||||
- Board state saving and loading
|
||||
- Legal move calculation for all piece types
|
||||
- User interaction handling
|
||||
- Visual board representation
|
||||
|
||||
Authors: Bédier Jérôme jerome.bedier@ecam.fr, Gardern Florian florian.gardner@ecam.fr, Leng Sidden sidden.leng@ecam.fr
|
||||
Date: 05/21/2025
|
||||
*/
|
||||
|
||||
public class Board {
|
||||
private Piece[][] board;
|
||||
private int width;
|
||||
private int height;
|
||||
private int turn;
|
||||
private int selectedX = -1;
|
||||
private int selectedY = -1;
|
||||
private boolean[][] highlightedSquares;
|
||||
private Stack<String[]> undoStack = new Stack<>();
|
||||
private int enPassantCol = -1;
|
||||
private int enPassantRow = -1;
|
||||
|
||||
public Board(int colNum, int lineNum) {
|
||||
this.width = colNum; // col move x
|
||||
this.height = lineNum; // line mov in y
|
||||
this.board = new Piece[width][height]; // 8x8 chess board
|
||||
this.highlightedSquares = new boolean[width][height];
|
||||
}
|
||||
|
||||
|
||||
public int getWidth() {
|
||||
//width = 8; // setting the width at 8 for the moment can be changed
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
//height = 8; // setting the height at 8 for the moment can be changed
|
||||
return height;
|
||||
}
|
||||
|
||||
public int getTurnNumber() {
|
||||
return turn;
|
||||
}
|
||||
|
||||
public boolean isTurnWhite() {
|
||||
return turn % 2 == 0; // White starts on turn 0 and only even turns
|
||||
}
|
||||
|
||||
public void setPiece(boolean isWhite, PieceType type, int x, int y) {
|
||||
/* Ensure coordinates are inside the board boundaries
|
||||
if (x < 0 || x >= width || y < 0 || y >= height) {
|
||||
System.out.println("Invalid coordinates: (" + x + ", " + y + ")");
|
||||
return;
|
||||
}*/
|
||||
|
||||
// Create and place the new piece
|
||||
board[x][y] = new Piece(isWhite, type, x, y);
|
||||
System.out.println(toString()); // Work but not sure ?
|
||||
}
|
||||
|
||||
|
||||
public void populateBoard() {
|
||||
// Place Rooks
|
||||
board[0][0] = new Piece(false, PieceType.Rook, 0, 0); //color, piece , x -> , y |
|
||||
board[0][7] = new Piece(true, PieceType.Rook, 0, 7);
|
||||
board[7][0] = new Piece(false, PieceType.Rook, 7, 0);
|
||||
board[7][7] = new Piece(true, PieceType.Rook, 7, 7);
|
||||
// Place Knights
|
||||
board[1][0] = new Piece(false, PieceType.Knight, 1, 0);
|
||||
board[1][7] = new Piece(true, PieceType.Knight, 1, 7);
|
||||
board[6][0] = new Piece(false, PieceType.Knight, 6, 0);
|
||||
board[6][7] = new Piece(true, PieceType.Knight, 6, 7);
|
||||
// Place Bishops
|
||||
board[2][0] = new Piece(false, PieceType.Bishop, 2, 0);
|
||||
board[2][7] = new Piece(true, PieceType.Bishop, 2, 7);
|
||||
board[5][0] = new Piece(false, PieceType.Bishop, 5, 0);
|
||||
board[5][7] = new Piece(true, PieceType.Bishop, 5, 7);
|
||||
// Place Queens
|
||||
board[4][0] = new Piece(false, PieceType.Queen, 4, 0);
|
||||
board[4][7] = new Piece(true, PieceType.Queen, 4, 7);
|
||||
// Place Kings
|
||||
board[3][0] = new Piece(false, PieceType.King, 3, 0);
|
||||
board[3][7] = new Piece(true, PieceType.King, 3, 7);
|
||||
// Place Pawns
|
||||
for (int i = 0; i < 8; i++) {
|
||||
board[i][1] = new Piece(false, PieceType.Pawn, i, 1); //color, piece , x -> , y |
|
||||
board[i][6] = new Piece(true, PieceType.Pawn, i, 6); //color, piece , x -> , y |
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanBoard() {
|
||||
turn = 0;
|
||||
this.board = new Piece[width][height]; // should work ?
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
Piece piece = board[x][y];
|
||||
if (piece == null) {
|
||||
sb.append(" ");
|
||||
} else {
|
||||
// Using Teacher method no breaks
|
||||
sb.append(piece.isWhite() ? "W" : "B")
|
||||
.append(piece.getType().getSummary());
|
||||
}
|
||||
if (x < width - 1) sb.append(",");
|
||||
}
|
||||
sb.append("\n");
|
||||
}
|
||||
sb.append("Turn: ").append(isTurnWhite() ? "White" : "Black").append("\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public ArrayList<Piece> getPieces() {
|
||||
ArrayList<Piece> pieces = new ArrayList<>();
|
||||
for (int i = 0; i < width; i++) {
|
||||
for (int j = 0; j < height; j++) {
|
||||
if (board[i][j] != null) {
|
||||
pieces.add(board[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pieces;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void userTouch(int x, int y) {
|
||||
if (x < 0 || x >= width || y < 0 || y >= height) return;
|
||||
|
||||
Piece clickedPiece = board[x][y];
|
||||
|
||||
// No piece selected yet
|
||||
if (selectedX == -1 && selectedY == -1) {
|
||||
if (clickedPiece != null && clickedPiece.isWhite() == isTurnWhite() && canSelectPieceWhenInCheck(x, y)){
|
||||
selectedX = x;
|
||||
selectedY = y;
|
||||
calculateValidMoves(clickedPiece);
|
||||
filterMovesForCheck();
|
||||
}
|
||||
} else {
|
||||
// Clicked the same piece again : unselect
|
||||
if (x == selectedX && y == selectedY) {
|
||||
selectedX = -1;
|
||||
selectedY = -1;
|
||||
clearHighlights();
|
||||
|
||||
} else if (highlightedSquares[x][y]) {
|
||||
// Move the piece
|
||||
Move move = new Move(selectedX, selectedY, x, y);
|
||||
playMove(move); // This handles moving the piece AND saving the undo state.
|
||||
selectedX = -1;
|
||||
selectedY = -1; // Unselect
|
||||
|
||||
clearHighlights();
|
||||
highlightKingInCheck();
|
||||
System.out.println(toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSelected(int x, int y) {
|
||||
return x == selectedX && y == selectedY;
|
||||
}
|
||||
|
||||
/* saving-loading feature :*/
|
||||
|
||||
public String[] toFileRep() {
|
||||
String[] lines = new String[height + 1]; // one line per row + 1 for turn
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int x = 0; x < width; x++) {
|
||||
Piece piece = board[x][y];
|
||||
if (piece == null) {
|
||||
sb.append("--");
|
||||
} else {
|
||||
sb.append(piece.isWhite() ? "W" : "B");
|
||||
sb.append(piece.getType().getSummary());
|
||||
}
|
||||
if (x < width - 1) sb.append(",");
|
||||
}
|
||||
lines[y] = sb.toString();
|
||||
}
|
||||
|
||||
// Last line stores the turn number
|
||||
lines[height] = Integer.toString(turn);
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
|
||||
public Board(String[] fileRepresentation) {
|
||||
this.height = fileRepresentation.length - 1;
|
||||
this.width = fileRepresentation[0].split(",").length;
|
||||
this.board = new Piece[width][height];
|
||||
this.highlightedSquares = new boolean[width][height];
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
String[] tokens = fileRepresentation[y].split(",");
|
||||
for (int x = 0; x < width; x++) {
|
||||
String token = tokens[x];
|
||||
if (!token.equals("--")) {
|
||||
boolean isWhite = token.charAt(0) == 'W';
|
||||
char pieceChar = token.charAt(1);
|
||||
PieceType type = PieceType.fromSummary(pieceChar);
|
||||
board[x][y] = new Piece(isWhite, type, x, y);
|
||||
} else {
|
||||
board[x][y] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.turn = Integer.parseInt(fileRepresentation[height]);
|
||||
}
|
||||
|
||||
|
||||
private void calculateValidMoves(Piece piece) {
|
||||
clearHighlights();
|
||||
if (piece == null) return;
|
||||
ArrayList<Move> legalMoves = getLegalMoves(piece); // Make sure getLegalMoves is implemented
|
||||
for (Move move : legalMoves) {
|
||||
highlightedSquares[move.getToX()][move.getToY()] = true;
|
||||
}
|
||||
}
|
||||
/* The following methods require more work ! */
|
||||
|
||||
public boolean isHighlighted(int x, int y) {
|
||||
return highlightedSquares[x][y];
|
||||
}
|
||||
|
||||
private void clearHighlights() {
|
||||
highlightedSquares = new boolean[width][height];
|
||||
}
|
||||
|
||||
private void highlightLegalMoves(Piece piece) {
|
||||
// Clear previous highlights
|
||||
for (int i = 0; i < width; i++)
|
||||
for (int j = 0; j < height; j++)
|
||||
highlightedSquares[i][j] = false;
|
||||
|
||||
if (piece == null) return;
|
||||
|
||||
ArrayList<Move> legalMoves = getLegalMoves(piece); // your existing method
|
||||
for (int i = 0; i < legalMoves.size(); i++) {
|
||||
Move move = legalMoves.get(i);
|
||||
highlightedSquares[move.getToX()][move.getToY()] = true; // assuming Move has toX and toY fields
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<Move> getLegalMoves(Piece piece) {
|
||||
ArrayList<Move> moves = new ArrayList<>();
|
||||
int x = piece.getX();
|
||||
int y = piece.getY();
|
||||
boolean isWhite = piece.isWhite();
|
||||
|
||||
switch(piece.getType()) {
|
||||
case Pawn:
|
||||
handlePawnMoves(moves, piece, x, y);
|
||||
break;
|
||||
case Knight:
|
||||
handleKnightMoves(moves, piece, x, y);
|
||||
break;
|
||||
case Bishop:
|
||||
handleSlidingMoves(moves, piece, x, y, new int[][]{{1,1}, {1,-1}, {-1,1}, {-1,-1}});
|
||||
break;
|
||||
case Rook:
|
||||
handleSlidingMoves(moves, piece, x, y, new int[][]{{1,0}, {-1,0}, {0,1}, {0,-1}});
|
||||
break;
|
||||
case Queen:
|
||||
handleSlidingMoves(moves, piece, x, y, new int[][]{{1,0}, {-1,0}, {0,1}, {0,-1}, {1,1}, {1,-1}, {-1,1}, {-1,-1}});
|
||||
break;
|
||||
case King:
|
||||
handleKingMoves(moves, piece, x, y);
|
||||
break;
|
||||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
// Helper methods for movement calculations
|
||||
private void handlePawnMoves(ArrayList<Move> moves, Piece pawn, int x, int y) {
|
||||
int direction = pawn.isWhite() ? -1 : 1;
|
||||
int startRow = pawn.isWhite() ? 6 : 1;
|
||||
|
||||
// Forward moves
|
||||
if (isEmpty(x, y + direction)) {
|
||||
moves.add(new Move(x, y, x, y + direction));
|
||||
if (y == startRow && isEmpty(x, y + 2*direction)) {
|
||||
moves.add(new Move(x, y, x, y + 2*direction));
|
||||
}
|
||||
}
|
||||
|
||||
// Captures
|
||||
checkPawnCapture(moves, pawn, x, y, direction, -1);
|
||||
checkPawnCapture(moves, pawn, x, y, direction, 1);
|
||||
|
||||
// En passant captures
|
||||
if ((pawn.isWhite() && y == 3) || (!pawn.isWhite() && y == 4)) {
|
||||
// Check both sides
|
||||
for (int dx : new int[]{-1, 1}) {
|
||||
int captureX = x + dx;
|
||||
// If there's a valid en passant opportunity
|
||||
if (captureX == enPassantCol && y + direction == enPassantRow) {
|
||||
Move enPassantMove = new Move(x, y, captureX, y + direction);
|
||||
// Set the captured piece (the pawn that just moved)
|
||||
enPassantMove.setCapturedPiece(board[captureX][y]);
|
||||
moves.add(enPassantMove);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkPawnCapture(ArrayList<Move> moves, Piece pawn, int x, int y, int dir, int dx) {
|
||||
int nx = x + dx;
|
||||
int ny = y + dir;
|
||||
if (isEnemy(nx, ny, pawn.isWhite())) {
|
||||
Move move = new Move(x, y, nx, ny);
|
||||
move.setCapturedPiece(board[nx][ny]);
|
||||
moves.add(move);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleKnightMoves(ArrayList<Move> moves, Piece knight, int x, int y) {
|
||||
int[][] offsets = {{2,1}, {2,-1}, {-2,1}, {-2,-1},
|
||||
{1,2}, {1,-2}, {-1,2}, {-1,-2}};
|
||||
for (int[] offset : offsets) {
|
||||
int nx = x + offset[0];
|
||||
int ny = y + offset[1];
|
||||
if (isValidPosition(nx, ny) && !isAlly(nx, ny, knight.isWhite())) {
|
||||
Move move = new Move(x, y, nx, ny);
|
||||
if (isEnemy(nx, ny, knight.isWhite())) {
|
||||
move.setCapturedPiece(board[nx][ny]);
|
||||
}
|
||||
moves.add(move);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSlidingMoves(ArrayList<Move> moves, Piece piece, int x, int y, int[][] directions) {
|
||||
for (int[] dir : directions) {
|
||||
int nx = x;
|
||||
int ny = y;
|
||||
while (true) {
|
||||
nx += dir[0];
|
||||
ny += dir[1];
|
||||
if (!isValidPosition(nx, ny)) break;
|
||||
if (isAlly(nx, ny, piece.isWhite())) break;
|
||||
|
||||
Move move = new Move(x, y, nx, ny);
|
||||
if (isEnemy(nx, ny, piece.isWhite())) {
|
||||
move.setCapturedPiece(board[nx][ny]);
|
||||
moves.add(move);
|
||||
break;
|
||||
}
|
||||
moves.add(move);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleKingMoves(ArrayList<Move> moves, Piece king, int x, int y) {
|
||||
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 (isValidPosition(nx, ny) && !isAlly(nx, ny, king.isWhite())) {
|
||||
Move move = new Move(x, y, nx, ny);
|
||||
if (isEnemy(nx, ny, king.isWhite())) {
|
||||
move.setCapturedPiece(board[nx][ny]);
|
||||
}
|
||||
moves.add(move);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Utility methods
|
||||
private boolean isValidPosition(int x, int y) {
|
||||
return x >= 0 && x < width && y >= 0 && y < height;
|
||||
}
|
||||
|
||||
public boolean isEmpty(int x, int y) {
|
||||
return isValidPosition(x, y) && board[x][y] == null;
|
||||
}
|
||||
|
||||
private boolean isEnemy(int x, int y, boolean isWhite) {
|
||||
return isValidPosition(x, y) && board[x][y] != null && board[x][y].isWhite() != isWhite;
|
||||
}
|
||||
|
||||
private boolean isAlly(int x, int y, boolean isWhite) {
|
||||
return isValidPosition(x, y) && board[x][y] != null && board[x][y].isWhite() == isWhite;
|
||||
}
|
||||
|
||||
public Piece getPieceAt(int x, int y) {
|
||||
if (!isValidPosition(x, y)) return null;
|
||||
return board[x][y];
|
||||
}
|
||||
|
||||
public void removePieceAt(int x, int y) {
|
||||
if (isValidPosition(x, y)) board[x][y] = null;
|
||||
}
|
||||
|
||||
public void setEnPassantCol(int col) {
|
||||
this.enPassantCol = col;
|
||||
}
|
||||
|
||||
public void setEnPassantRow(int row) {
|
||||
this.enPassantRow = row;
|
||||
}
|
||||
|
||||
public int getEnPassantCol() {
|
||||
return this.enPassantCol;
|
||||
}
|
||||
|
||||
public int getEnPassantRow() {
|
||||
return this.enPassantRow;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void undoLastMove() {
|
||||
if (!undoStack.isEmpty()) {
|
||||
String[] lastState = undoStack.pop();
|
||||
|
||||
// Load the board from the saved state
|
||||
Board previousBoard = new Board(lastState);
|
||||
|
||||
// Copy the previousBoard's fields into current board instance
|
||||
this.board = previousBoard.board;
|
||||
this.turn = previousBoard.turn;
|
||||
this.width = previousBoard.width;
|
||||
this.height = previousBoard.height;
|
||||
this.highlightedSquares = previousBoard.highlightedSquares;
|
||||
|
||||
// Clear selection and highlights as well (optional)
|
||||
this.selectedX = -1;
|
||||
this.selectedY = -1;
|
||||
clearHighlights();
|
||||
|
||||
System.out.println("Undo performed.");
|
||||
System.out.println(this.toString());
|
||||
} else {
|
||||
System.out.println("No moves to undo.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Board(Board original) {
|
||||
this.width = original.width;
|
||||
this.height = original.height;
|
||||
this.turn = original.turn;
|
||||
this.selectedX = original.selectedX;
|
||||
this.selectedY = original.selectedY;
|
||||
this.enPassantCol = original.enPassantCol;
|
||||
this.enPassantRow = original.enPassantRow;
|
||||
|
||||
// Deep copy the board array and pieces
|
||||
this.board = new Piece[width][height];
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
Piece p = original.board[x][y];
|
||||
if (p != null) {
|
||||
this.board[x][y] = new Piece(p.isWhite(), p.getType(), x, y);
|
||||
} else {
|
||||
this.board[x][y] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Deep copy highlightedSquares
|
||||
this.highlightedSquares = new boolean[width][height];
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
this.highlightedSquares[x][y] = original.highlightedSquares[x][y];
|
||||
}
|
||||
}
|
||||
|
||||
// Undo stack is not copied (empty)
|
||||
this.undoStack = new Stack<>();
|
||||
}//test
|
||||
|
||||
|
||||
public void playMove(Move move) {
|
||||
// Save current state before move for undo
|
||||
undoStack.push(toFileRep());
|
||||
|
||||
Piece piece = board[move.getFromX()][move.getFromY()];
|
||||
SpecialMoves specialMoves = new SpecialMoves();
|
||||
|
||||
// Handle en passant capture
|
||||
if (specialMoves.isEnPassant(this, move)) {
|
||||
Piece capturedPawn = board[move.getToX()][move.getFromY()];
|
||||
move.setCapturedPiece(capturedPawn);
|
||||
specialMoves.handleEnPassant(this, move);
|
||||
}
|
||||
|
||||
// Move the piece
|
||||
board[move.getToX()][move.getToY()] = piece;
|
||||
board[move.getFromX()][move.getFromY()] = null;
|
||||
piece.x = move.getToX();
|
||||
piece.y = move.getToY();
|
||||
|
||||
// Update en passant tracking
|
||||
specialMoves.updateEnPassantTracking(this, move, piece);
|
||||
|
||||
// Handle pawn promotion
|
||||
if (piece.getType() == PieceType.Pawn &&
|
||||
(piece.getY() == 0 || piece.getY() == height - 1)) {
|
||||
board[piece.getX()][piece.getY()] = specialMoves.promotePawn(piece.isWhite(), piece.getX(), piece.getY());
|
||||
}
|
||||
|
||||
turn++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Finds the position of the king of a given color.
|
||||
public Piece findKing(boolean isWhite) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
Piece piece = board[x][y];
|
||||
if (piece != null && piece.getType() == PieceType.King && piece.isWhite() == isWhite) {
|
||||
return piece;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null; // King not found (should not happen in normal chess)
|
||||
}
|
||||
|
||||
// check king check based on a given color
|
||||
public boolean isKingInCheck(boolean isWhite) {
|
||||
// First, find the king's position
|
||||
Piece king = findKing(isWhite);
|
||||
soudEffect soundPlayer = new soudEffect();
|
||||
|
||||
if (king == null) {
|
||||
// If king not found (shouldn't happen in a valid chess game)
|
||||
return false;
|
||||
}
|
||||
|
||||
int kingX = king.getX();
|
||||
int kingY = king.getY();
|
||||
|
||||
// Check if any enemy piece can attack the king
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
Piece piece = board[x][y];
|
||||
|
||||
// Skip empty squares and pieces of the same color as the king
|
||||
if (piece == null || piece.isWhite() == isWhite) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get all legal moves for this enemy piece
|
||||
ArrayList<Move> moves = getLegalMoves(piece);
|
||||
|
||||
// Check if any move can capture the king
|
||||
for (Move move : moves) {
|
||||
if (move.getToX() == kingX && move.getToY() == kingY) {
|
||||
soundPlayer.playCheckSound();
|
||||
return true; // King is in check
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false; // King is not in check
|
||||
}
|
||||
|
||||
public Piece promotePawn(boolean isWhite, int x, int y) {
|
||||
return new Piece(isWhite, PieceType.Queen, x, y);
|
||||
}
|
||||
|
||||
private void highlightKingInCheck() {
|
||||
int highlightedCount = 0;
|
||||
// Check if white king is in check
|
||||
Piece whiteKing = findKing(true);
|
||||
if (whiteKing != null && isKingInCheck(true)) {
|
||||
highlightedSquares[whiteKing.getX()][whiteKing.getY()] = true;
|
||||
}
|
||||
|
||||
//check if white king checkmate
|
||||
|
||||
|
||||
// Check if black king is in check
|
||||
Piece blackKing = findKing(false);
|
||||
if (blackKing != null && isKingInCheck(false)) {
|
||||
highlightedSquares[blackKing.getX()][blackKing.getY()] = true;
|
||||
}
|
||||
|
||||
} // check
|
||||
|
||||
public boolean canSelectPieceWhenInCheck(int x, int y) {
|
||||
Piece piece = board[x][y];
|
||||
|
||||
// If no piece at this position or wrong color, can't select
|
||||
if (piece == null || piece.isWhite() != isTurnWhite()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If king is not in check, any piece can be selected
|
||||
if (!isKingInCheck(isTurnWhite())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// When king is in check, check if this piece can make any legal move
|
||||
// that would get the king out of check
|
||||
ArrayList<Move> legalMoves = getLegalMoves(piece);
|
||||
for (Move move : legalMoves) {
|
||||
// Temporarily make the move
|
||||
Piece capturedPiece = board[move.getToX()][move.getToY()];
|
||||
board[move.getToX()][move.getToY()] = piece;
|
||||
board[move.getFromX()][move.getFromY()] = null;
|
||||
|
||||
// Check if king is still in check after this move
|
||||
boolean stillInCheck = isKingInCheck(isTurnWhite());
|
||||
|
||||
// Undo the move
|
||||
board[move.getFromX()][move.getFromY()] = piece;
|
||||
board[move.getToX()][move.getToY()] = capturedPiece;
|
||||
|
||||
// If this move gets king out of check, piece can be selected
|
||||
if (!stillInCheck) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// No legal moves that get king out of check
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSquareAttacked(int x, int y, boolean byWhite) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
for (int j = 0; j < height; j++) {
|
||||
Piece attacker = board[i][j];
|
||||
if (attacker != null && attacker.isWhite() == byWhite) {
|
||||
ArrayList<Move> moves = getLegalMoves(attacker);
|
||||
for (Move move : moves) {
|
||||
if (move.getToX() == x && move.getToY() == y) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void filterMovesForCheck() {
|
||||
Piece selectedPiece = board[selectedX][selectedY];
|
||||
boolean[][] newHighlights = new boolean[width][height];
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
if (highlightedSquares[x][y]) {
|
||||
// Temporarily make the move
|
||||
Piece capturedPiece = board[x][y];
|
||||
board[x][y] = selectedPiece;
|
||||
board[selectedX][selectedY] = null;
|
||||
|
||||
// Check if king is in check after the move
|
||||
boolean leavesKingInCheck;
|
||||
|
||||
// If moving the king, check if the destination square is attacked
|
||||
if (selectedPiece.getType() == PieceType.King) {
|
||||
leavesKingInCheck = isSquareAttacked(x, y, !selectedPiece.isWhite());
|
||||
System.out.println("Game Over"); // only work if king selected
|
||||
}
|
||||
|
||||
else {
|
||||
leavesKingInCheck = isKingInCheck(isTurnWhite());
|
||||
}
|
||||
// Undo the move
|
||||
board[selectedX][selectedY] = selectedPiece;
|
||||
board[x][y] = capturedPiece;
|
||||
|
||||
// Keep only safe moves
|
||||
if (!leavesKingInCheck) {
|
||||
newHighlights[x][y] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replace highlights with filtered version
|
||||
highlightedSquares = newHighlights;
|
||||
}
|
||||
|
||||
public boolean isCheckmate(boolean isWhite) {
|
||||
if (!isKingInCheck(isWhite)) {
|
||||
return false; // Not in check, so not checkmate
|
||||
}
|
||||
|
||||
// Check if ANY legal move can get the king out of check
|
||||
for (Piece piece : getPieces()) {
|
||||
if (piece.isWhite() == isWhite) {
|
||||
ArrayList<Move> legalMoves = getLegalMoves(piece);
|
||||
|
||||
for (Move move : legalMoves) {
|
||||
// Simulate move
|
||||
Board simulatedBoard = new Board(this.toFileRep());
|
||||
simulatedBoard.playMove(move);
|
||||
|
||||
// If king is not in check after this move, it's not checkmate
|
||||
if (!simulatedBoard.isKingInCheck(isWhite)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true; // No legal move prevents check => checkmate
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
package backend;
|
||||
|
||||
import windowInterface.MyInterface;
|
||||
|
||||
public class Game extends Thread {
|
||||
|
||||
private AutoPlayer aiPlayer;
|
||||
private Board board;
|
||||
|
||||
private MyInterface mjf;
|
||||
private int COL_NUM = 8;
|
||||
private int LINE_NUM = 8;
|
||||
private int loopDelay = 250;
|
||||
boolean[] activationAIFlags;
|
||||
|
||||
public Game(MyInterface mjfParam) {
|
||||
mjf = mjfParam;
|
||||
board = new Board(COL_NUM, LINE_NUM);
|
||||
loopDelay = 250;
|
||||
LINE_NUM = 8;
|
||||
COL_NUM = 8;
|
||||
activationAIFlags = new boolean[2];
|
||||
aiPlayer = new AutoPlayer();
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return board.getWidth();
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return board.getHeight();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while(true) {
|
||||
aiPlayerTurn();
|
||||
mjf.update(board.getTurnNumber(), board.isTurnWhite());
|
||||
try {
|
||||
Thread.sleep(loopDelay);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAITurn() {
|
||||
return activationAIFlags[board.isTurnWhite()?1:0];
|
||||
}
|
||||
|
||||
private void aiPlayerTurn() {
|
||||
if(isAITurn()) {
|
||||
board.playMove(aiPlayer.computeBestMove(new Board(board)));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setPiece(boolean isWhite, PieceType type, int x, int y) {
|
||||
board.setPiece(isWhite, type, x, y);
|
||||
}
|
||||
|
||||
public String[] getFileRepresentation() {
|
||||
return board.toFileRep();
|
||||
}
|
||||
|
||||
public void setLoopDelay(int delay) {
|
||||
this.loopDelay = delay;
|
||||
}
|
||||
|
||||
public void setDefaultSetup() {
|
||||
board.cleanBoard();
|
||||
board.populateBoard();
|
||||
}
|
||||
|
||||
public void setBoard(String[] array) {
|
||||
board = new Board(array);
|
||||
}
|
||||
|
||||
public Iterable<Piece> getPieces() {
|
||||
return board.getPieces();
|
||||
}
|
||||
|
||||
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() {
|
||||
board.undoLastMove();
|
||||
}
|
||||
|
||||
public void toggleAI(boolean isWhite) {
|
||||
this.activationAIFlags[isWhite?1:0] = !this.activationAIFlags[isWhite?1:0];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package backend;
|
||||
|
||||
public class Move {
|
||||
private final int fromX;
|
||||
private final int fromY;
|
||||
private final int toX;
|
||||
private final int toY;
|
||||
private Piece capturedPiece;
|
||||
|
||||
public Move(int fromX, int fromY, int toX, int toY) {
|
||||
this.fromX = fromX;
|
||||
this.fromY = fromY;
|
||||
this.toX = toX;
|
||||
this.toY = toY;
|
||||
}
|
||||
|
||||
// Getters
|
||||
public int getFromX() { return fromX; }
|
||||
public int getFromY() { return fromY; }
|
||||
public int getToX() { return toX; }
|
||||
public int getToY() { return toY; }
|
||||
public Piece getCapturedPiece() { return capturedPiece; }
|
||||
|
||||
// Setter for captured piece
|
||||
public void setCapturedPiece(Piece piece) {
|
||||
this.capturedPiece = piece;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("Move from (%d,%d) to (%d,%d)", fromX, fromY, toX, toY);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package backend;
|
||||
|
||||
/*Task: Chess Game Piece Representation
|
||||
|
||||
Class name: Piece.java
|
||||
|
||||
Methods name:
|
||||
|
||||
Piece(boolean whitePiece, PieceType type, int x, int y) - Constructor that initializes a chess piece with color, type, and position
|
||||
getX() - Returns the current x-coordinate of the piece on the board
|
||||
getY() - Returns the current y-coordinate of the piece on the board
|
||||
getType() - Returns the type of the piece (Pawn, Knight, Bishop, etc.)
|
||||
isWhite() - Returns true if the piece is white, false if black
|
||||
|
||||
Methods output:
|
||||
|
||||
Piece position coordinates (x, y)
|
||||
Piece type information
|
||||
Piece color information
|
||||
Methods works:
|
||||
|
||||
Chess piece representation
|
||||
Piece attribute storage
|
||||
Position tracking
|
||||
Type and color identification
|
||||
|
||||
Authors: Bédier Jérôme jerome.bedier@ecam.fr Gardern Florian florian.gardner@ecam.fr Leng Sidden sidden.leng@ecam.fr
|
||||
Date: 05/14/2025
|
||||
*/
|
||||
|
||||
public class Piece {
|
||||
boolean whitePiece;
|
||||
int x;
|
||||
int y;
|
||||
private PieceType type;
|
||||
|
||||
public Piece(boolean whitePiece, PieceType type, int x, int y) {
|
||||
this.whitePiece = whitePiece;
|
||||
this.type = type;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public PieceType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public boolean isWhite() {
|
||||
return whitePiece;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package backend;
|
||||
|
||||
/*Task: Chess Game Piece Type Enumeration
|
||||
|
||||
Class name: PieceType.java
|
||||
|
||||
Methods name:
|
||||
- getSummary() - Returns a single character representation of the piece type (P, R, N, B, Q, K)
|
||||
- fromSummary(char c) - Static method that converts a character to the corresponding PieceType
|
||||
|
||||
Methods output:
|
||||
- Single character representation of piece types
|
||||
- PieceType enum value from character input
|
||||
|
||||
Methods works:
|
||||
- Chess piece type enumeration
|
||||
- Conversion between piece types and their character representations
|
||||
- Support for standard chess piece notation
|
||||
- Mapping between characters and piece types
|
||||
|
||||
Authors: Bédier Jérôme jerome.bedier@ecam.fr Gardern Florian florian.gardner@ecam.fr Leng Sidden sidden.leng@ecam.fr
|
||||
Date: 05/14/2025
|
||||
*/
|
||||
|
||||
public enum PieceType {
|
||||
Pawn, Rook, Knight, Bishop, Queen, King;
|
||||
|
||||
public String getSummary() {
|
||||
if(this == PieceType.Knight) {
|
||||
return "N";
|
||||
}
|
||||
return this.name().substring(0, 1);
|
||||
}
|
||||
|
||||
public static PieceType fromSummary(char c) {
|
||||
if(c=='P') {
|
||||
return PieceType.Pawn;
|
||||
}else if(c=='N') {
|
||||
return PieceType.Knight;
|
||||
}else if(c=='B') {
|
||||
return PieceType.Bishop;
|
||||
}else if(c=='R') {
|
||||
return PieceType.Rook;
|
||||
}else if(c=='K') {
|
||||
return PieceType.King;
|
||||
}
|
||||
return PieceType.Queen;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package backend;
|
||||
|
||||
/*
|
||||
Task: Chess Special Moves Implementation
|
||||
|
||||
Class name: SpecialMoves
|
||||
|
||||
Methods name:
|
||||
- promotePawn(boolean isWhite, int x, int y) - Returns a new Queen piece to replace a pawn upon reaching the promotion rank.
|
||||
- isEnPassant(Board board, Move move) - Returns true if the specified move is an en passant capture.
|
||||
- handleEnPassant(Board board, Move move) - Handles the en passant capture by removing the captured pawn from the board.
|
||||
- updateEnPassantTracking(Board board, Move move, Piece piece) - Updates en passant square tracking after a pawn's double move.
|
||||
- canCastle(Board board, Piece king, boolean isKingside) - Returns true if castling is possible (placeholder, always false).
|
||||
- handleCastling(Board board, Move move, boolean isKingside) - Handles king and rook movement for castling (placeholder, no implementation).
|
||||
|
||||
Methods output:
|
||||
- Promoted queen piece on pawn promotion.
|
||||
- Boolean status for en passant and castling move possibilities.
|
||||
- Updates to board state for en passant and castling.
|
||||
- En passant tracking updates after pawn double moves.
|
||||
|
||||
Methods works:
|
||||
- Pawn promotion to queen on reaching the opponent's back rank.
|
||||
- Detection and execution of en passant captures.
|
||||
- Tracking and resetting en passant target squares.
|
||||
- (Placeholder) Castling logic including detection and execution.
|
||||
|
||||
Authors: Bédier Jérôme jerome.bedier@ecam.fr, Gardern Florian florian.gardner@ecam.fr, Leng Sidden sidden.leng@ecam.fr
|
||||
Date: 05/21/2025
|
||||
*/
|
||||
|
||||
public class SpecialMoves {
|
||||
|
||||
// Pawn promotion: always promotes to Queen for simplicity
|
||||
public Piece promotePawn(boolean isWhite, int x, int y) {
|
||||
return new Piece(isWhite, PieceType.Queen, x, y);
|
||||
}
|
||||
|
||||
// Checks if a move is an en passant capture
|
||||
public boolean isEnPassant(Board board, Move move) {
|
||||
Piece piece = board.getPieceAt(move.getFromX(), move.getFromY());
|
||||
if (piece == null || piece.getType() != PieceType.Pawn) return false;
|
||||
if (move.getToX() == move.getFromX()) return false;
|
||||
return board.isEmpty(move.getToX(), move.getToY());
|
||||
}
|
||||
|
||||
// Handles the en passant capture
|
||||
public void handleEnPassant(Board board, Move move) {
|
||||
board.removePieceAt(move.getToX(), move.getFromY());
|
||||
}
|
||||
|
||||
// Updates en passant tracking after a pawn's double move
|
||||
public void updateEnPassantTracking(Board board, Move move, Piece piece) {
|
||||
board.setEnPassantCol(-1);
|
||||
board.setEnPassantRow(-1);
|
||||
if (piece.getType() == PieceType.Pawn &&
|
||||
Math.abs(move.getFromY() - move.getToY()) == 2) {
|
||||
board.setEnPassantCol(move.getToX());
|
||||
board.setEnPassantRow((move.getFromY() + move.getToY()) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
// (Optional) Placeholder for castling logic
|
||||
public boolean canCastle(Board board, Piece king, boolean isKingside) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void handleCastling(Board board, Move move, boolean isKingside) {
|
||||
// Implement castling logic if needed
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package backend;
|
||||
|
||||
import javax.sound.sampled.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/*
|
||||
Task: Chess Sound Effect Handling
|
||||
|
||||
Class name: soudEffect
|
||||
|
||||
Methods name:
|
||||
- playCheckSound() - Plays a sound effect when the king is in check. Uses a WAV file and Java's audio system.
|
||||
|
||||
Methods output:
|
||||
- Plays a check sound effect.
|
||||
|
||||
Methods works:
|
||||
- Loads and plays a WAV audio file to provide audio feedback (e.g., when the king is in check).
|
||||
- Handles exceptions for unsupported file formats, unavailable lines, and IO errors.
|
||||
|
||||
Authors: Bédier Jérôme jerome.bedier@ecam.fr, Gardern Florian florian.gardner@ecam.fr, Leng Sidden sidden.leng@ecam.fr
|
||||
Date: 05/21/2025
|
||||
*/
|
||||
|
||||
public class soudEffect {
|
||||
public void playCheckSound() {
|
||||
try {
|
||||
// Replace "check.wav" with the path to your check sound file
|
||||
File soundFile = new File("exterminate.wav");
|
||||
AudioInputStream audioStream = AudioSystem.getAudioInputStream(soundFile);
|
||||
Clip clip = AudioSystem.getClip();
|
||||
clip.open(audioStream);
|
||||
clip.start();
|
||||
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
package windowInterface;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import backend.Game;
|
||||
import backend.Piece;
|
||||
import backend.PieceType;
|
||||
|
||||
public class JPanelChessBoard extends JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Game myGame;
|
||||
private MyInterface interfaceGlobal;
|
||||
private BufferedImage spriteSheet;
|
||||
private int PIECE_WIDTH = 16; //in spritesheet
|
||||
private int PIECE_HEIGHT = 16; //in spritesheet
|
||||
private int MARGIN = 6;
|
||||
|
||||
private boolean pieceSelectorMode;
|
||||
private boolean selectedPieceIsWhite;
|
||||
private PieceType selectedPieceType;
|
||||
private boolean pieceAdderMode;
|
||||
|
||||
public JPanelChessBoard(MyInterface itf) {
|
||||
super();
|
||||
myGame = null;
|
||||
interfaceGlobal = itf;
|
||||
selectedPieceIsWhite = true;
|
||||
selectedPieceType = PieceType.Pawn;
|
||||
pieceSelectorMode = false;
|
||||
try {
|
||||
spriteSheet = ImageIO.read(new File("pieces.png"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
pieceSelectorMode = false;
|
||||
pieceAdderMode = false;
|
||||
addMouseListener(new MouseAdapter() {
|
||||
public void mousePressed(MouseEvent me) {
|
||||
// System.out.println(me);
|
||||
if(pieceSelectorMode) {
|
||||
int x = Math.round(me.getX()/cellWidth());
|
||||
selectedPieceType = PieceType.values()[5-x];
|
||||
selectedPieceIsWhite = (me.getY() > cellHeight());
|
||||
pieceSelectorMode = false;
|
||||
} else {
|
||||
if(myGame == null) {
|
||||
interfaceGlobal.instantiateSimu();
|
||||
}
|
||||
int x = (me.getX()*myGame.getWidth())/getWidth();
|
||||
int y = (me.getY()*myGame.getHeight())/getHeight();
|
||||
if(pieceAdderMode) {
|
||||
//TODO
|
||||
myGame.setPiece(selectedPieceIsWhite,selectedPieceType, x, y);
|
||||
pieceAdderMode = false;
|
||||
} else {
|
||||
myGame.clickCoords(x,y);
|
||||
}
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void setGame(Game simu) {
|
||||
myGame = simu;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
this.setBackground(Color.darkGray);
|
||||
if(pieceSelectorMode) {
|
||||
g.drawImage(
|
||||
spriteSheet,
|
||||
0,
|
||||
0,
|
||||
Math.round(5*cellWidth()),
|
||||
Math.round(2*cellHeight()),
|
||||
null
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (myGame != null) {
|
||||
// Draw Interface from state of simulator
|
||||
float cellWidth = cellWidth();
|
||||
float cellHeight = cellHeight();
|
||||
|
||||
g.setColor(Color.pink);
|
||||
for(int x=0; x<myGame.getWidth();x++) {
|
||||
for (int y=0; y<myGame.getHeight(); y++) {
|
||||
boolean isSelect = myGame.isSelected(x,y);
|
||||
boolean isHighlight = myGame.isHighlighted(x,y);
|
||||
if(isSelect) {
|
||||
g.setColor(Color.red);
|
||||
}
|
||||
if(isHighlight) {
|
||||
g.setColor(Color.blue);
|
||||
}
|
||||
if((x+y)%2==1 || isSelect || isHighlight) {
|
||||
g.fillRect(
|
||||
Math.round(x*cellWidth),
|
||||
Math.round(y*cellHeight),
|
||||
Math.round(cellWidth),
|
||||
Math.round(cellHeight)
|
||||
);
|
||||
}
|
||||
if(isHighlight || isSelect) {
|
||||
g.setColor(Color.pink);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
g.setColor(Color.gray);
|
||||
for(int x=0; x<myGame.getWidth();x++) {
|
||||
int graphX = Math.round(x*cellWidth);
|
||||
g.drawLine(graphX, 0, graphX, this.getHeight());
|
||||
}
|
||||
for (int y=0; y<myGame.getHeight(); y++) {
|
||||
int graphY = Math.round(y*cellHeight);
|
||||
g.drawLine(0, graphY, this.getWidth(), graphY);
|
||||
}
|
||||
|
||||
for (Piece piece : myGame.getPieces()) {
|
||||
drawPiece(g,piece);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawPiece(Graphics g, Piece piece) {
|
||||
g.drawImage(
|
||||
getChessPieceImageFromType(piece.getType(), piece.isWhite()),
|
||||
MARGIN+(xCoordFromGame(piece.getX())),
|
||||
MARGIN+(yCoordFromGame(piece.getY())),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private Image getChessPieceImageFromType(PieceType type, boolean isWhite) {
|
||||
int x = spriteSheetPositionOfPieceType(type)*PIECE_WIDTH;
|
||||
int y = PIECE_HEIGHT * (isWhite?1:0);
|
||||
Image subImage = spriteSheet.getSubimage(x, y, PIECE_WIDTH, PIECE_HEIGHT);
|
||||
return subImage.getScaledInstance(
|
||||
Math.round(cellWidth())-2*MARGIN,
|
||||
Math.round(cellHeight())-2*MARGIN, 0
|
||||
);
|
||||
}
|
||||
|
||||
private int spriteSheetPositionOfPieceType(PieceType type) {
|
||||
return 5-type.ordinal();
|
||||
}
|
||||
|
||||
private float cellWidth() {
|
||||
return (float) this.getWidth()/ (float)myGame.getWidth();
|
||||
}
|
||||
private float cellHeight() {
|
||||
return (float)this.getHeight()/ (float)myGame.getHeight();
|
||||
}
|
||||
private int xCoordFromGame(int x) {
|
||||
return Math.round(x*cellWidth());
|
||||
}
|
||||
private int yCoordFromGame(int y) {
|
||||
return Math.round(y*cellHeight());
|
||||
}
|
||||
|
||||
public void togglePieceSelector() {
|
||||
pieceSelectorMode = ! pieceSelectorMode;
|
||||
}
|
||||
|
||||
public void toggleAdderMode() {
|
||||
pieceAdderMode = ! pieceAdderMode;
|
||||
}
|
||||
|
||||
public boolean isPieceSelectorMode() {
|
||||
return pieceSelectorMode;
|
||||
}
|
||||
|
||||
|
||||
public boolean isPieceAdderMode() {
|
||||
return pieceAdderMode;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,269 @@
|
|||
package windowInterface;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridLayout;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import backend.Game;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.AbstractListModel;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.JRadioButton;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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));
|
||||
|
||||
|
||||
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);
|
||||
|
||||
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 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 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();
|
||||
}
|
||||
|
||||
});
|
||||
panelTop.add(btnUndo);
|
||||
|
||||
chckbxWhiteAI = new JCheckBox("WhiteAI");
|
||||
chckbxWhiteAI.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clicAIToggle(true);
|
||||
}
|
||||
|
||||
});
|
||||
panelTop.add(chckbxWhiteAI);
|
||||
|
||||
chckbxBlackAI = new JCheckBox("BlackAI");
|
||||
chckbxBlackAI.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
clicAIToggle(false);
|
||||
}
|
||||
|
||||
});
|
||||
panelTop.add(chckbxBlackAI);
|
||||
|
||||
panelDraw = new JPanelChessBoard(this);
|
||||
contentPane.add(panelDraw, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
public void setStepBanner(String s) {
|
||||
turnLabel.setText(s);
|
||||
}
|
||||
|
||||
public void setBorderBanner(String s) {
|
||||
borderLabel.setText(s);
|
||||
}
|
||||
|
||||
public JPanelChessBoard getPanelDessin() {
|
||||
return panelDraw;
|
||||
}
|
||||
|
||||
public void instantiateSimu() {
|
||||
if(game==null) {
|
||||
game = new Game(this);
|
||||
panelDraw.setGame(game);
|
||||
game.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void clicButtonStart() {
|
||||
this.instantiateSimu();
|
||||
game.setDefaultSetup();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
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 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 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();
|
||||
}
|
||||
|
||||
public void eraseLabels() {
|
||||
this.setStepBanner("Turn : X");
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue