i have implemented a basic AI that plays legal move

This commit is contained in:
carol 2025-05-19 18:19:41 +02:00
parent 8062a2ce28
commit 2ba7cccbf4
3 changed files with 181 additions and 16 deletions

View File

@ -1,17 +1,90 @@
package backend; package backend;
import java.util.ArrayList;
import java.util.Random;
public class AutoPlayer { public class AutoPlayer {
private final Move moveHelper = new Move();
private final Random random = new Random();
/** /**
* returns the best Move to try on provided board for active player * Returns a random legal move for the current player
* @param board * @param boardObj The board to find moves for
* @return * @return a valid Move or null if no moves available
*/ */
public Move computeBestMove(Board board) { public Move computeBestMove(Board boardObj) {
// Create a list of pieces that can move
ArrayList<Piece> candidates = new ArrayList<>();
return null;
ArrayList<Piece> allPieces = boardObj.getPieces();
int width = boardObj.getWidth();
int height = boardObj.getHeight();
boolean isWhiteTurn = boardObj.isTurnWhite();
Piece[][] boardArray = new Piece[width][height];
// Find all pieces with legal moves
for (Piece piece : allPieces) {
// Only consider pieces of the current player's color
if (piece.isWhite() == isWhiteTurn) {
clearBoard(boardArray);
for (Piece p : allPieces) {
boardArray[p.getX()][p.getY()] = p;
} }
ArrayList<int[]> moves = moveHelper.getValidMoves(
piece, boardArray, width, height, null, boardObj
);
if (!moves.isEmpty()) {
candidates.add(piece);
}
}
}
if (candidates.isEmpty()) return null;
// Select a random piece to move
Piece selected = candidates.get(random.nextInt(candidates.size()));
clearBoard(boardArray);
for (Piece p : allPieces) {
boardArray[p.getX()][p.getY()] = p;
}
ArrayList<int[]> moves = moveHelper.getValidMoves(
selected, boardArray, width, height, null, boardObj
);
// Select a random destination for the piece
int[] target = moves.get(random.nextInt(moves.size()));
Move aiMove = new Move();
aiMove.setFromX(selected.getX());
aiMove.setFromY(selected.getY());
aiMove.setToX(target[0]);
aiMove.setToY(target[1]);
return aiMove;
}
/**
* Clears the given board array by setting all elements to null
*/
private void clearBoard(Piece[][] boardArray) {
for (int x = 0; x < boardArray.length; x++) {
for (int y = 0; y < boardArray[x].length; y++) {
boardArray[x][y] = null;
}
}
}
} }

View File

@ -15,6 +15,7 @@ public class Board {
private ArrayList<int[]> highlightedSquares = new ArrayList<>(); private ArrayList<int[]> highlightedSquares = new ArrayList<>();
private int[] enPassantTarget = null; // [x,y] coordinates of en passant target square private int[] enPassantTarget = null; // [x,y] coordinates of en passant target square
private Move moveHelper = new Move(); private Move moveHelper = new Move();
private final AutoPlayer ai = new AutoPlayer();
public Board(int colNum, int lineNum) { public Board(int colNum, int lineNum) {
this.width = colNum; this.width = colNum;
@ -214,6 +215,12 @@ public class Board {
// Clear selection & highlights // Clear selection & highlights
hasSelectedPiece = false; hasSelectedPiece = false;
highlightedSquares.clear(); highlightedSquares.clear();
if (!turnWhite) {
Move aiMove = ai.computeBestMove(this);
if (aiMove != null) {
playMove(aiMove);
}
} }
// Invalid move: just unselect // Invalid move: just unselect
else { else {
@ -223,6 +230,8 @@ public class Board {
} }
} }
}
/* saving-loading feature */ /* saving-loading feature */
@ -342,6 +351,52 @@ public class Board {
} }
public void playMove(Move move) { public void playMove(Move move) {
// TODO Piece selectedPiece = board[move.getFromX()][move.getFromY()];
if (selectedPiece == null) return;
boolean isEnPassant = selectedPiece.getType() == PieceType.Pawn &&
enPassantTarget != null &&
move.getToX() == enPassantTarget[0] &&
move.getToY() == enPassantTarget[1] &&
board[move.getToX()][move.getToY()] == null;
previousBoard = cloneBoard(board);
board[move.getToX()][move.getToY()] = selectedPiece;
board[move.getFromX()][move.getFromY()] = null;
selectedPiece.setX(move.getToX());
selectedPiece.setY(move.getToY());
selectedPiece.setMoved(true);
if (isEnPassant) {
board[move.getToX()][move.getFromY()] = null;
}
if (selectedPiece.getType() == PieceType.King && Math.abs(move.getToX() - move.getFromX()) == 2) {
if (move.getToX() > move.getFromX()) {
Piece rook = board[7][move.getToY()];
board[5][move.getToY()] = rook;
board[7][move.getToY()] = null;
rook.setX(5);
rook.setMoved(true);
} else {
Piece rook = board[0][move.getToY()];
board[3][move.getToY()] = rook;
board[0][move.getToY()] = null;
rook.setX(3);
rook.setMoved(true);
} }
} }
enPassantTarget = null;
if (selectedPiece.getType() == PieceType.Pawn &&
Math.abs(move.getToY() - move.getFromY()) == 2) {
enPassantTarget = new int[]{move.getToX(), (move.getFromY() + move.getToY()) / 2};
}
turnWhite = !turnWhite;
turnNumber++;
hasSelectedPiece = false;
highlightedSquares.clear();
}
}

View File

@ -143,4 +143,41 @@ public class Move {
private boolean inBounds(int x, int y, int width, int height) { private boolean inBounds(int x, int y, int width, int height) {
return x >= 0 && x < width && y >= 0 && y < height; return x >= 0 && x < width && y >= 0 && y < height;
} }
private int fromX;
private int fromY;
private int toX;
private int toY;
public int getFromX() {
return fromX;
}
public void setFromX(int fromX) {
this.fromX = fromX;
}
public int getFromY() {
return fromY;
}
public void setFromY(int fromY) {
this.fromY = fromY;
}
public int getToX() {
return toX;
}
public void setToX(int toX) {
this.toX = toX;
}
public int getToY() {
return toY;
}
public void setToY(int toY) {
this.toY = toY;
}
} }