i have implemented a basic AI that plays legal move
This commit is contained in:
parent
8062a2ce28
commit
2ba7cccbf4
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue