Merge branch 'master' of https://gitarero.ecam.fr/yohan.montagne/OOP_2B1_Project.git
This commit is contained in:
commit
73e0bc0106
|
|
@ -1,25 +1,21 @@
|
|||
package backend;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class AutoPlayer {
|
||||
|
||||
|
||||
/**
|
||||
* returns the best Move to try on provided board for active player
|
||||
* @param board
|
||||
* @return
|
||||
*/
|
||||
|
||||
public Move computeBestMove(Board board) {
|
||||
List<Move> moves = board.getAllLegalMoves(board.isTurnWhite());
|
||||
boolean aiIsWhite = board.isTurnWhite(); // Important!
|
||||
List<Move> moves = board.getAllLegalMoves(aiIsWhite);
|
||||
|
||||
Move bestMove = null;
|
||||
int bestScore = Integer.MIN_VALUE;
|
||||
|
||||
for (Move move : moves) {
|
||||
Board simulated = board.clone(); // Clone the board
|
||||
Board simulated = board.clone();
|
||||
simulated.playMove(move);
|
||||
|
||||
int score = evaluate(simulated, board.isTurnWhite());
|
||||
|
||||
int score = evaluate(simulated, aiIsWhite); // Pass correct side
|
||||
if (score > bestScore) {
|
||||
bestScore = score;
|
||||
bestMove = move;
|
||||
|
|
@ -28,26 +24,25 @@ public class AutoPlayer {
|
|||
|
||||
return bestMove;
|
||||
}
|
||||
|
||||
private int evaluate(Board board, boolean forWhite) {
|
||||
|
||||
private int evaluate(Board board, boolean forWhite) {
|
||||
int score = 0;
|
||||
for (Piece piece : board.getAllPieces()) {
|
||||
for (Piece piece : board.getPieces()) {
|
||||
int value = getPieceValue(piece);
|
||||
score += (piece.isWhite() == forWhite) ? value : -value;
|
||||
score += piece.isWhite() == forWhite ? value : -value;
|
||||
}
|
||||
return score;
|
||||
}
|
||||
private int getPieceValue(Piece piece) {
|
||||
switch (piece.getType()) {
|
||||
case Pawn: return 1;
|
||||
case Knight: case Bishop: return 3;
|
||||
case Rook: return 5;
|
||||
case Queen: return 9;
|
||||
case King: return 100;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private int getPieceValue(Piece piece) {
|
||||
switch (piece.getType()) {
|
||||
case Pawn: return 1;
|
||||
case Knight:
|
||||
case Bishop: return 3;
|
||||
case Rook: return 5;
|
||||
case Queen: return 9;
|
||||
case King: return 100;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,22 +3,15 @@ package backend;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Bishop extends Piece {
|
||||
class Bishop extends Piece {
|
||||
public Bishop(boolean isWhite, int x, int y) {
|
||||
super(isWhite, PieceType.Bishop, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PieceType getType() {
|
||||
return PieceType.Bishop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Move> getLegalMoves(Board board, int row, int col) {
|
||||
List<Move> moves = new ArrayList<>();
|
||||
int[][] directions = {
|
||||
{-1, -1}, {-1, 1}, {1, -1}, {1, 1}
|
||||
};
|
||||
int[][] directions = {{-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
|
||||
|
||||
for (int[] dir : directions) {
|
||||
int r = row + dir[0];
|
||||
|
|
@ -28,20 +21,19 @@ public class Bishop extends Piece {
|
|||
if (target == null) {
|
||||
moves.add(new Move(this, row, col, r, c));
|
||||
} else {
|
||||
if (target.isWhite() != this.isWhite)
|
||||
moves.add(new Move(this, row, col, r, c));
|
||||
if (target.isWhite() != isWhite)
|
||||
moves.add(new Move(this, row, col, r, c, target));
|
||||
break;
|
||||
}
|
||||
r += dir[0];
|
||||
c += dir[1];
|
||||
}
|
||||
}
|
||||
|
||||
return moves;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Piece clone() {
|
||||
return new Bishop(this.isWhite, this.x, this.y);
|
||||
return new Bishop(isWhite, x, y);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
package backend;
|
||||
import javax.print.attribute.standard.MediaSize.Other;
|
||||
|
||||
import javax.sound.sampled.AudioInputStream;
|
||||
import javax.sound.sampled.AudioSystem;
|
||||
import javax.sound.sampled.Clip;
|
||||
|
|
@ -147,53 +147,45 @@ public class Board implements Cloneable {
|
|||
public void userTouch(int x, int y) {
|
||||
if (selectedX == null && selectedY == null) {
|
||||
Piece pieceAtPos = getPieceAt(x, y);
|
||||
if (pieceAtPos != null) {
|
||||
|
||||
if (pieceAtPos != null && pieceAtPos.isWhite() == turnIsWhite) {
|
||||
selectedX = x;
|
||||
selectedY = y;
|
||||
|
||||
// Calculate and highlight valid moves for the selected piece
|
||||
highlightedPositions.clear();
|
||||
List<Move> legalMoves = pieceAtPos.getLegalMoves(this, x, y);
|
||||
|
||||
List<Move> legalMoves = pieceAtPos.getLegalMoves(this, y, x);
|
||||
for (Move move : legalMoves) {
|
||||
highlightedPositions.add(new int[]{move.getToCol(), move.getToRow()});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (selectedX == x && selectedY == y) {
|
||||
// Unselect the piece and clear highlighted positions
|
||||
selectedX = null;
|
||||
selectedY = null;
|
||||
highlightedPositions.clear();
|
||||
} else {
|
||||
Piece pieceToMove = getPieceAt(selectedX, selectedY);
|
||||
if (pieceToMove != null) {
|
||||
Piece pieceAtDestination = getPieceAt(x, y);
|
||||
if (pieceAtDestination == null || pieceAtDestination.isWhite() != pieceToMove.isWhite()) {
|
||||
saveStateToHistory();
|
||||
if (pieceAtDestination != null) {
|
||||
pieces.remove(pieceAtDestination);
|
||||
|
||||
if (pieceToMove != null && pieceToMove.isWhite() == turnIsWhite) {
|
||||
List<Move> legalMoves = pieceToMove.getLegalMoves(this, selectedY, selectedX);
|
||||
|
||||
for (Move move : legalMoves) {
|
||||
if (move.getToCol() == x && move.getToRow() == y) {
|
||||
saveStateToHistory();
|
||||
playMove(move);
|
||||
break;
|
||||
}
|
||||
pieces.remove(pieceToMove);
|
||||
|
||||
// Create a new instance of the specific piece type
|
||||
Piece newPiece = makeNewPiece(pieceToMove.getType(), pieceToMove.isWhite(), x, y);
|
||||
pieces.add(newPiece);
|
||||
|
||||
playMoveSound();
|
||||
|
||||
turnNumber++;
|
||||
turnIsWhite = !turnIsWhite;
|
||||
|
||||
// Clear highlighted positions after moving the piece
|
||||
highlightedPositions.clear();
|
||||
}
|
||||
}
|
||||
|
||||
selectedX = null;
|
||||
selectedY = null;
|
||||
highlightedPositions.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Piece makeNewPiece(PieceType type, boolean isWhite, int x, int y) {
|
||||
Piece newPiece;
|
||||
switch (type) {
|
||||
|
|
@ -238,12 +230,12 @@ public class Board implements Cloneable {
|
|||
|
||||
|
||||
public Piece getPieceAt(int x, int y) {
|
||||
for (Piece piece : pieces) {
|
||||
if (piece.getX() == x && piece.getY() == y) {
|
||||
return piece;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
for (Piece piece : pieces) {
|
||||
if (piece.getX() == x && piece.getY() == y) {
|
||||
return piece;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -302,8 +294,9 @@ public class Board implements Cloneable {
|
|||
/* The following methods require more work ! */
|
||||
|
||||
public boolean isHighlighted(int x, int y) {
|
||||
for (int[] position : highlightedPositions) {
|
||||
if (position[0] == x && position[1] == y) {
|
||||
// Ensure coordinates are correct
|
||||
for (int[] pos : highlightedPositions) {
|
||||
if (pos[0] == x && pos[1] == y) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -315,6 +308,12 @@ public class Board implements Cloneable {
|
|||
pieces = boardHistory.getLast();
|
||||
boardHistory.removeLast();
|
||||
turnNumber--;
|
||||
if (!turnIsWhite) {
|
||||
turnIsWhite=true;
|
||||
}
|
||||
else {
|
||||
turnIsWhite=false;
|
||||
}
|
||||
}
|
||||
|
||||
public Board(Board board) {
|
||||
|
|
@ -331,45 +330,38 @@ public class Board implements Cloneable {
|
|||
}
|
||||
|
||||
public void playMove(Move move) {
|
||||
Piece pieceToMove = getPieceAt(move.getFromCol(), move.getFromRow());
|
||||
if (pieceToMove != null) {
|
||||
Piece pieceAtDestination = getPieceAt(move.getToCol(), move.getToRow());
|
||||
if (pieceAtDestination != null) {
|
||||
pieces.remove(pieceAtDestination);
|
||||
}
|
||||
pieces.remove(pieceToMove);
|
||||
// Note: getPieceAt(x, y), x = col, y = row
|
||||
Piece pieceToMove = getPieceAt(move.getFromCol(), move.getFromRow());
|
||||
|
||||
// Create a new instance of the specific piece type
|
||||
Piece newPiece;
|
||||
switch (pieceToMove.getType()) {
|
||||
case Pawn:
|
||||
newPiece = new Pawn(pieceToMove.isWhite(), move.getToCol(), move.getToRow());
|
||||
break;
|
||||
case King:
|
||||
newPiece = new King(pieceToMove.isWhite(), move.getToCol(), move.getToRow());
|
||||
break;
|
||||
case Queen:
|
||||
newPiece = new Queen(pieceToMove.isWhite(), move.getToCol(), move.getToRow());
|
||||
break;
|
||||
case Rook:
|
||||
newPiece = new Rook(pieceToMove.isWhite(), move.getToCol(), move.getToRow());
|
||||
break;
|
||||
case Bishop:
|
||||
newPiece = new Bishop(pieceToMove.isWhite(), move.getToCol(), move.getToRow());
|
||||
break;
|
||||
case Knight:
|
||||
newPiece = new Knight(pieceToMove.isWhite(), move.getToCol(), move.getToRow());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown piece type");
|
||||
}
|
||||
pieces.add(newPiece);
|
||||
if (pieceToMove == null) {
|
||||
System.err.println("Invalid move: no piece at source");
|
||||
return;
|
||||
}
|
||||
|
||||
turnNumber++;
|
||||
turnIsWhite = !turnIsWhite;
|
||||
}
|
||||
}
|
||||
if (pieceToMove.isWhite() != turnIsWhite) {
|
||||
System.err.println("Invalid move: wrong turn");
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove captured piece, if any
|
||||
Piece capturedPiece = getPieceAt(move.getToCol(), move.getToRow());
|
||||
if (capturedPiece != null) {
|
||||
pieces.remove(capturedPiece);
|
||||
}
|
||||
|
||||
pieces.remove(pieceToMove);
|
||||
|
||||
// Add moved piece at the new position
|
||||
Piece movedPiece = makeNewPiece(pieceToMove.getType(), pieceToMove.isWhite(), move.getToCol(), move.getToRow());
|
||||
pieces.add(movedPiece);
|
||||
|
||||
// Update turn info
|
||||
turnIsWhite = !turnIsWhite;
|
||||
turnNumber++;
|
||||
|
||||
// Play move sound if enabled
|
||||
playMoveSound();
|
||||
}
|
||||
|
||||
public ArrayList<Move> getAllLegalMoves(boolean isWhite) {
|
||||
ArrayList<Move> moves = new ArrayList<>();
|
||||
|
|
@ -399,11 +391,10 @@ public class Board implements Cloneable {
|
|||
|
||||
return pieces;
|
||||
}
|
||||
public boolean isInBounds(int row, int col) {
|
||||
return row >= 0 && row < 8 && col >= 0 && col < 8;
|
||||
public boolean isInBounds(int x, int y) {
|
||||
return x >= 0 && x < Width && y >= 0 && y < Height;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Board clone() {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -3,39 +3,35 @@ package backend;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class King extends Piece {
|
||||
class King extends Piece {
|
||||
public King(boolean isWhite, int x, int y) {
|
||||
super(isWhite, PieceType.King, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PieceType getType() {
|
||||
return PieceType.King;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Move> getLegalMoves(Board board, int row, int col) {
|
||||
List<Move> moves = new ArrayList<>();
|
||||
int[] d = {-1, 0, 1};
|
||||
|
||||
for (int dr : d) {
|
||||
for (int dc : d) {
|
||||
for (int dr = -1; dr <= 1; dr++) {
|
||||
for (int dc = -1; dc <= 1; dc++) {
|
||||
if (dr == 0 && dc == 0) continue;
|
||||
int r = row + dr;
|
||||
int c = col + dc;
|
||||
if (board.isInBounds(r, c)) {
|
||||
Piece p = board.getPieceAt(r, c);
|
||||
if (p == null || p.isWhite() != this.isWhite)
|
||||
moves.add(new Move(this, row, col, r, c));
|
||||
Piece target = board.getPieceAt(r, c);
|
||||
if (target == null || target.isWhite() != isWhite) {
|
||||
if (target != null)
|
||||
moves.add(new Move(this, row, col, r, c, target));
|
||||
else
|
||||
moves.add(new Move(this, row, col, r, c));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return moves;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Piece clone() {
|
||||
return new King(this.isWhite, this.x, this.y);
|
||||
return new King(isWhite, x, y);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,16 +3,11 @@ package backend;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Knight extends Piece {
|
||||
class Knight extends Piece {
|
||||
public Knight(boolean isWhite, int x, int y) {
|
||||
super(isWhite, PieceType.Knight, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PieceType getType() {
|
||||
return PieceType.Knight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Move> getLegalMoves(Board board, int row, int col) {
|
||||
List<Move> moves = new ArrayList<>();
|
||||
|
|
@ -25,17 +20,20 @@ public class Knight extends Piece {
|
|||
int r = row + offset[0];
|
||||
int c = col + offset[1];
|
||||
if (board.isInBounds(r, c)) {
|
||||
Piece p = board.getPieceAt(r, c);
|
||||
if (p == null || p.isWhite() != this.isWhite)
|
||||
moves.add(new Move(this, row, col, r, c));
|
||||
Piece target = board.getPieceAt(r, c);
|
||||
if (target == null || target.isWhite() != isWhite) {
|
||||
if (target != null)
|
||||
moves.add(new Move(this, row, col, r, c, target));
|
||||
else
|
||||
moves.add(new Move(this, row, col, r, c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return moves;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Piece clone() {
|
||||
return new Knight(this.isWhite, this.x, this.y);
|
||||
return new Knight(isWhite, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,41 +3,37 @@ package backend;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class Pawn extends Piece {
|
||||
public Pawn(boolean isWhite, int x, int y) {
|
||||
super(isWhite, PieceType.Pawn, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PieceType getType() {
|
||||
return PieceType.Pawn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Move> getLegalMoves(Board board, int row, int col) {
|
||||
List<Move> moves = new ArrayList<>();
|
||||
int direction = isWhite ? -1 : 1;
|
||||
int direction = isWhite ? -1 : 1; // White moves up, black down
|
||||
int startRow = isWhite ? 6 : 1;
|
||||
|
||||
// Forward 1 square
|
||||
int forwardRow = row + direction;
|
||||
if (board.isInBounds(forwardRow, col) && board.getPieceAt(forwardRow, col) == null) {
|
||||
moves.add(new Move(this, row, col, forwardRow, col));
|
||||
|
||||
// Forward 2 squares from starting position
|
||||
int doubleForwardRow = row + 2 * direction;
|
||||
if (row == startRow && board.getPieceAt(doubleForwardRow, col) == null) {
|
||||
moves.add(new Move(this, row, col, doubleForwardRow, col));
|
||||
// Move forward
|
||||
int oneStep = row + direction;
|
||||
if (board.isInBounds(col, oneStep) && board.getPieceAt(col, oneStep) == null) {
|
||||
moves.add(new Move(this, row, col, oneStep, col));
|
||||
int twoStep = row + 2 * direction;
|
||||
if (row == startRow && board.isInBounds(col, twoStep) && board.getPieceAt(col, twoStep) == null) {
|
||||
moves.add(new Move(this, row, col, twoStep, col));
|
||||
}
|
||||
}
|
||||
|
||||
// Diagonal captures
|
||||
for (int dc = -1; dc <= 1; dc += 2) {
|
||||
int c = col + dc;
|
||||
if (board.isInBounds(forwardRow, c)) {
|
||||
Piece target = board.getPieceAt(forwardRow, c);
|
||||
if (target != null && target.isWhite() != this.isWhite)
|
||||
moves.add(new Move(this, row, col, forwardRow, c));
|
||||
// Captures
|
||||
int[] dx = {-1, 1};
|
||||
for (int d : dx) {
|
||||
int targetCol = col + d;
|
||||
if (board.isInBounds(targetCol, oneStep)) {
|
||||
Piece enemy = board.getPieceAt(targetCol, oneStep);
|
||||
if (enemy != null && enemy.isWhite() != this.isWhite) {
|
||||
moves.add(new Move(this, row, col, oneStep, targetCol, enemy));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -46,6 +42,6 @@ public class Pawn extends Piece {
|
|||
|
||||
@Override
|
||||
public Piece clone() {
|
||||
return new Pawn(this.isWhite, this.x, this.y);
|
||||
return new Pawn(isWhite, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,22 +3,17 @@ package backend;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Queen extends Piece {
|
||||
class Queen extends Piece {
|
||||
public Queen(boolean isWhite, int x, int y) {
|
||||
super(isWhite, PieceType.Queen, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PieceType getType() {
|
||||
return PieceType.Queen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Move> getLegalMoves(Board board, int row, int col) {
|
||||
List<Move> moves = new ArrayList<>();
|
||||
int[][] directions = {
|
||||
{-1, 0}, {1, 0}, {0, -1}, {0, 1}, // Rook-like
|
||||
{-1, -1}, {-1, 1}, {1, -1}, {1, 1} // Bishop-like
|
||||
{-1, 0}, {1, 0}, {0, -1}, {0, 1},
|
||||
{-1, -1}, {-1, 1}, {1, -1}, {1, 1}
|
||||
};
|
||||
|
||||
for (int[] dir : directions) {
|
||||
|
|
@ -29,21 +24,19 @@ public class Queen extends Piece {
|
|||
if (target == null) {
|
||||
moves.add(new Move(this, row, col, r, c));
|
||||
} else {
|
||||
if (target.isWhite() != this.isWhite) {
|
||||
moves.add(new Move(this, row, col, r, c));
|
||||
}
|
||||
if (target.isWhite() != isWhite)
|
||||
moves.add(new Move(this, row, col, r, c, target));
|
||||
break;
|
||||
}
|
||||
r += dir[0];
|
||||
c += dir[1];
|
||||
}
|
||||
}
|
||||
|
||||
return moves;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Piece clone() {
|
||||
return new Queen(this.isWhite, this.x, this.y);
|
||||
return new Queen(isWhite, x, y);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,42 +3,37 @@ package backend;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Rook extends Piece {
|
||||
class Rook extends Piece {
|
||||
public Rook(boolean isWhite, int x, int y) {
|
||||
super(isWhite, PieceType.Rook, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PieceType getType() {
|
||||
return PieceType.Rook;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Move> getLegalMoves(Board board, int row, int col) {
|
||||
List<Move> moves = new ArrayList<>();
|
||||
int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
|
||||
|
||||
for (int[] dir : directions) {
|
||||
int r = row + dir[0], c = col + dir[1];
|
||||
int r = row + dir[0];
|
||||
int c = col + dir[1];
|
||||
while (board.isInBounds(r, c)) {
|
||||
Piece target = board.getPieceAt(r, c);
|
||||
if (target == null) {
|
||||
moves.add(new Move(this, row, col, r, c));
|
||||
} else {
|
||||
if (target.isWhite() != this.isWhite)
|
||||
moves.add(new Move(this, row, col, r, c));
|
||||
if (target.isWhite() != isWhite)
|
||||
moves.add(new Move(this, row, col, r, c, target));
|
||||
break;
|
||||
}
|
||||
r += dir[0];
|
||||
c += dir[1];
|
||||
}
|
||||
}
|
||||
|
||||
return moves;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Piece clone() {
|
||||
return new Rook(this.isWhite, this.x, this.y);
|
||||
return new Rook(isWhite, x, y);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue