Save Load Undo En Passant Working
This commit is contained in:
parent
c032e3023c
commit
b20a1a1c9c
|
|
@ -18,4 +18,5 @@ public class Main {
|
||||||
MyInterface mjf = new MyInterface();
|
MyInterface mjf = new MyInterface();
|
||||||
mjf.setVisible(true);
|
mjf.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,17 +1,35 @@
|
||||||
|
|
||||||
package backend;
|
package backend;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
|
||||||
public class AutoPlayer {
|
public class AutoPlayer {
|
||||||
|
private Random rand = new Random();
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns the best Move to try on provided board for active player
|
|
||||||
* @param board
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Move computeBestMove(Board board) {
|
public Move computeBestMove(Board board) {
|
||||||
|
ArrayList<Move> allMoves = new ArrayList<>();
|
||||||
|
for (Piece p : board.getPieces()) {
|
||||||
|
if (p.isWhite() == board.isTurnWhite()) {
|
||||||
|
int fromX = p.getX();
|
||||||
|
int fromY = p.getY();
|
||||||
|
|
||||||
return null;
|
for (int x = 0; x < board.getWidth(); x++) {
|
||||||
|
for (int y = 0; y < board.getHeight(); y++) {
|
||||||
|
Board temp = new Board(board);
|
||||||
|
temp.selectPiece(fromX, fromY); // simulate userTouch
|
||||||
|
if (temp.isHighlighted(x, y)) {
|
||||||
|
Piece captured = board.getPieceAt(x, y);
|
||||||
|
allMoves.add(new Move(p, x, y, captured));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allMoves.isEmpty()) return null;
|
||||||
|
return allMoves.get(rand.nextInt(allMoves.size()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,303 +1,543 @@
|
||||||
package backend;
|
package backend;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
public class Board {
|
public class Board {
|
||||||
|
private Piece lastDoubleStepPawn = null;
|
||||||
private int width;
|
private int width;
|
||||||
private int height;
|
private int height;
|
||||||
private ArrayList<Piece> pieces;
|
private ArrayList<Piece> Pieces;
|
||||||
private int turnNumber;
|
private Stack<Move> moveHistory = new Stack<>();
|
||||||
private boolean isTurnWhite;
|
|
||||||
private int selectedX, selectedY;
|
|
||||||
private ArrayList<int[]> highlightedSquares;
|
|
||||||
|
|
||||||
public Board(int colNum, int lineNum) {
|
// ── NEW FIELDS FOR userTouch ───────────────────────────────────────
|
||||||
this.width = colNum;
|
private boolean hasSelection = false; // did we already click to pick up a piece?
|
||||||
this.height = lineNum;
|
private int selectedX, selectedY; // if so, which square is “in hand”?
|
||||||
this.pieces = new ArrayList<>();
|
private int turnNumber = 0; // how many half-moves have been played?
|
||||||
|
private boolean turnWhite = true; // true = White to play, false = Black
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
public String[] toFileRep() {
|
||||||
|
String[] lines = new String[height + 1];
|
||||||
|
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
Piece p = getPieceAt(x, y);
|
||||||
|
if (p == null) {
|
||||||
|
sb.append("..");
|
||||||
|
} else {
|
||||||
|
sb.append(p.isWhite() ? "W" : "B");
|
||||||
|
sb.append(p.getType().getSummary());
|
||||||
|
}
|
||||||
|
if (x < width - 1) sb.append(",");
|
||||||
|
}
|
||||||
|
lines[y] = sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
lines[height] = isTurnWhite() ? "W" : "B";
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
public Board(String[] array) {
|
||||||
|
this.width = 8;
|
||||||
|
this.height = 8;
|
||||||
|
this.Pieces = new ArrayList<>();
|
||||||
|
this.moveHistory = new Stack<>();
|
||||||
|
this.hasSelection = false;
|
||||||
this.turnNumber = 0;
|
this.turnNumber = 0;
|
||||||
this.isTurnWhite = true;
|
|
||||||
this.selectedX = -1;
|
|
||||||
this.selectedY = -1;
|
|
||||||
this.highlightedSquares = new ArrayList<>();
|
|
||||||
|
|
||||||
|
for (int y = 0; y < 8; y++) {
|
||||||
|
String[] cells = array[y].split(",");
|
||||||
|
for (int x = 0; x < 8; x++) {
|
||||||
|
String cell = cells[x];
|
||||||
|
if (!cell.equals("..")) {
|
||||||
|
boolean isWhite = cell.charAt(0) == 'W';
|
||||||
|
PieceType type = PieceType.fromSummary(cell.charAt(1));
|
||||||
|
Pieces.add(new Piece(x, y, isWhite, type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.turnWhite = array[8].equals("W");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Board(int width, int height) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.Pieces = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWidth() {
|
public int getWidth() {
|
||||||
return this.width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHeight() {
|
public int getHeight() {
|
||||||
return this.height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTurnNumber() {
|
public int getTurnNumber() {
|
||||||
return this.turnNumber;
|
//TODO
|
||||||
|
return turnNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTurnWhite() {
|
public boolean isTurnWhite() {
|
||||||
return this.isTurnWhite;
|
//TODO
|
||||||
|
return turnWhite;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPiece(boolean isWhite, PieceType type, int x, int y) {
|
public void setPiece(boolean isWhite, PieceType type, int x, int y) {
|
||||||
pieces.removeIf(p -> p.getX() == x && p.getY() == y); // Remove any piece already at position
|
// 1) Remove any piece already at this square
|
||||||
pieces.add(new Piece(x, y, type, isWhite));
|
for (int i = 0; i < Pieces.size(); i++) {
|
||||||
|
Piece p = Pieces.get(i);
|
||||||
|
if (p.getX() == x && p.getY() == y) {
|
||||||
|
Pieces.remove(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Add the new piece
|
||||||
|
Pieces.add(new Piece(x, y, isWhite, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void populateBoard() {
|
public void populateBoard() {
|
||||||
cleanBoard();
|
// black
|
||||||
|
Pieces.add(new Piece(0,0,false,PieceType.Rook));
|
||||||
|
Pieces.add(new Piece(1,0,false,PieceType.Knight));
|
||||||
|
Pieces.add(new Piece(2,0,false,PieceType.Bishop));
|
||||||
|
Pieces.add(new Piece(3,0,false,PieceType.Queen));
|
||||||
|
Pieces.add(new Piece(4,0,false,PieceType.King));
|
||||||
|
Pieces.add(new Piece(5,0,false,PieceType.Bishop));
|
||||||
|
Pieces.add(new Piece(6,0,false,PieceType.Knight));
|
||||||
|
Pieces.add(new Piece(7,0,false,PieceType.Rook));
|
||||||
|
|
||||||
setPiece(false, PieceType.Rook, 0, 0);
|
Pieces.add(new Piece(0,1,false,PieceType.Pawn));
|
||||||
setPiece(false, PieceType.Knight, 1, 0);
|
Pieces.add(new Piece(1,1,false,PieceType.Pawn));
|
||||||
setPiece(false, PieceType.Bishop, 2, 0);
|
Pieces.add(new Piece(2,1,false,PieceType.Pawn));
|
||||||
setPiece(false, PieceType.Queen, 3, 0);
|
Pieces.add(new Piece(3,1,false,PieceType.Pawn));
|
||||||
setPiece(false, PieceType.King, 4, 0);
|
Pieces.add(new Piece(4,1,false,PieceType.Pawn));
|
||||||
setPiece(false, PieceType.Bishop, 5, 0);
|
Pieces.add(new Piece(5,1,false,PieceType.Pawn));
|
||||||
setPiece(false, PieceType.Knight, 6, 0);
|
Pieces.add(new Piece(6,1,false,PieceType.Pawn));
|
||||||
setPiece(false, PieceType.Rook, 7, 0);
|
Pieces.add(new Piece(7,1,false,PieceType.Pawn));
|
||||||
|
|
||||||
|
// white
|
||||||
|
Pieces.add(new Piece(0, 7, true, PieceType.Rook));
|
||||||
|
Pieces.add(new Piece(1, 7, true, PieceType.Knight));
|
||||||
|
Pieces.add(new Piece(2, 7, true, PieceType.Bishop));
|
||||||
|
Pieces.add(new Piece(3, 7, true, PieceType.Queen));
|
||||||
|
Pieces.add(new Piece(4, 7, true, PieceType.King));
|
||||||
|
Pieces.add(new Piece(5, 7, true, PieceType.Bishop));
|
||||||
|
Pieces.add(new Piece(6, 7, true, PieceType.Knight));
|
||||||
|
Pieces.add(new Piece(7, 7, true, PieceType.Rook));
|
||||||
|
|
||||||
|
Pieces.add(new Piece(0,6,true,PieceType.Pawn));
|
||||||
|
Pieces.add(new Piece(1,6,true,PieceType.Pawn));
|
||||||
|
Pieces.add(new Piece(2,6,true,PieceType.Pawn));
|
||||||
|
Pieces.add(new Piece(3,6,true,PieceType.Pawn));
|
||||||
|
Pieces.add(new Piece(4,6,true,PieceType.Pawn));
|
||||||
|
Pieces.add(new Piece(5,6,true,PieceType.Pawn));
|
||||||
|
Pieces.add(new Piece(6,6,true,PieceType.Pawn));
|
||||||
|
Pieces.add(new Piece(7,6,true,PieceType.Pawn));
|
||||||
|
|
||||||
for (int x = 0; x < width; x++) {
|
|
||||||
setPiece(false, PieceType.Pawn, x, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int x = 0; x < width; x++) {
|
public ArrayList<Piece> getPieces(){
|
||||||
setPiece(true, PieceType.Pawn, x, 6);
|
return Pieces;
|
||||||
}
|
|
||||||
|
|
||||||
setPiece(true, PieceType.Rook, 0, 7);
|
|
||||||
setPiece(true, PieceType.Knight, 1, 7);
|
|
||||||
setPiece(true, PieceType.Bishop, 2, 7);
|
|
||||||
setPiece(true, PieceType.Queen, 3, 7);
|
|
||||||
setPiece(true, PieceType.King, 4, 7);
|
|
||||||
setPiece(true, PieceType.Bishop, 5, 7);
|
|
||||||
setPiece(true, PieceType.Knight, 6, 7);
|
|
||||||
setPiece(true, PieceType.Rook, 7, 7);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanBoard() {
|
public void cleanBoard() {
|
||||||
pieces.clear();
|
Pieces.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
for (int x = 0; x < width; x++) {
|
for (int x = 0; x < width; x++) {
|
||||||
Piece p = getPieceAt(x, y);
|
Piece found = null;
|
||||||
if (p != null) {
|
for (Piece p : Pieces) {
|
||||||
sb.append(p.isWhite() ? "W" : "B");
|
if (p.getX() == x && p.getY() == y) {
|
||||||
sb.append(p.getType().getSummary());
|
found = p;
|
||||||
} else {
|
break;
|
||||||
sb.append("__");
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found != null) {
|
||||||
|
String color = found.isWhite() ? "W" : "B";
|
||||||
|
sb.append(color).append(found.getType().getSummary()).append(" ");
|
||||||
|
} else {
|
||||||
|
sb.append(".. ");
|
||||||
}
|
}
|
||||||
sb.append(" ");
|
|
||||||
}
|
}
|
||||||
sb.append("\n");
|
sb.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
public void userTouch(int x, int y) {
|
||||||
public ArrayList<Piece> getPieces() {
|
// 1) Find if you clicked on a piece at (x,y)
|
||||||
return pieces;
|
Piece clicked = null;
|
||||||
|
for (Piece p : Pieces) {
|
||||||
|
if (p.getX() == x && p.getY() == y) {
|
||||||
|
clicked = p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void userTouch(int x, int y) {
|
// 2) If nothing is selected, select a piece of the correct color
|
||||||
Piece selectedPiece = getPieceAt(selectedX, selectedY);
|
if (!hasSelection) {
|
||||||
|
if (clicked != null && clicked.isWhite() == turnWhite) {
|
||||||
if (selectedPiece == null) {
|
hasSelection = true;
|
||||||
Piece piece = getPieceAt(x, y);
|
|
||||||
if (piece != null && piece.isWhite() == isTurnWhite) {
|
|
||||||
selectedX = x;
|
selectedX = x;
|
||||||
selectedY = y;
|
selectedY = y;
|
||||||
highlightedSquares = getValidMoves(piece); // compute highlights normally
|
|
||||||
}
|
}
|
||||||
} else {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) If you click the same square again → deselect
|
||||||
if (x == selectedX && y == selectedY) {
|
if (x == selectedX && y == selectedY) {
|
||||||
selectedX = -1;
|
hasSelection = false;
|
||||||
selectedY = -1;
|
return;
|
||||||
highlightedSquares.clear();
|
}
|
||||||
|
|
||||||
|
// 4) If the square is not highlighted (illegal), ignore it
|
||||||
|
if (!isHighlighted(x, y)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5) Do the move
|
||||||
|
|
||||||
|
// Capture (including en passant)
|
||||||
|
Piece captured = null;
|
||||||
|
for (Piece p : Pieces) {
|
||||||
|
if (p.getX() == x && p.getY() == y) {
|
||||||
|
captured = p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the piece to move (only declare once!)
|
||||||
|
Piece toMove = null;
|
||||||
|
for (Piece p : Pieces) {
|
||||||
|
if (p.getX() == selectedX && p.getY() == selectedY) {
|
||||||
|
toMove = p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// En passant condition
|
||||||
|
if (captured == null && toMove != null && toMove.getType() == PieceType.Pawn) {
|
||||||
|
int dir = toMove.isWhite() ? -1 : 1;
|
||||||
|
if (lastDoubleStepPawn != null &&
|
||||||
|
lastDoubleStepPawn.getX() == x &&
|
||||||
|
lastDoubleStepPawn.getY() == y - dir &&
|
||||||
|
lastDoubleStepPawn.isWhite() != toMove.isWhite()) {
|
||||||
|
|
||||||
|
Pieces.removeIf(p -> p.getX() == lastDoubleStepPawn.getX() && p.getY() == lastDoubleStepPawn.getY());
|
||||||
|
captured = lastDoubleStepPawn;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal capture
|
||||||
|
if (captured != null) {
|
||||||
|
Pieces.remove(captured);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the selected piece
|
||||||
|
if (toMove != null) {
|
||||||
|
Pieces.removeIf(p -> p.getX() == selectedX && p.getY() == selectedY);
|
||||||
|
|
||||||
|
// Check for promotion
|
||||||
|
boolean isWhite = toMove.isWhite();
|
||||||
|
PieceType type = toMove.getType();
|
||||||
|
if (type == PieceType.Pawn && ((isWhite && y == 0) || (!isWhite && y == 7))) {
|
||||||
|
// Promote to queen
|
||||||
|
Pieces.add(new Piece(x, y, isWhite, PieceType.Queen));
|
||||||
} else {
|
} else {
|
||||||
Piece destinationPiece = getPieceAt(x, y);
|
// Normal move
|
||||||
selectedPiece.setX(x);
|
Pieces.add(new Piece(x, y, isWhite, type));
|
||||||
selectedPiece.setY(y);
|
|
||||||
|
|
||||||
if (destinationPiece != null && destinationPiece.isWhite() != selectedPiece.isWhite()) {
|
|
||||||
pieces.remove(destinationPiece);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Track if this move is a double pawn move
|
||||||
|
if (type == PieceType.Pawn && Math.abs(y - toMove.getY()) == 2) {
|
||||||
|
lastDoubleStepPawn = new Piece(x, y, isWhite, PieceType.Pawn);
|
||||||
|
} else {
|
||||||
|
lastDoubleStepPawn = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update state
|
||||||
turnNumber++;
|
turnNumber++;
|
||||||
isTurnWhite = !isTurnWhite;
|
turnWhite = !turnWhite;
|
||||||
|
hasSelection = false;
|
||||||
|
|
||||||
selectedX = -1;
|
Move move = new Move(toMove, x, y, captured); // captured may be null
|
||||||
selectedY = -1;
|
moveHistory.push(move);
|
||||||
highlightedSquares.clear();
|
System.out.println(this);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSelected(int x, int y) {
|
public boolean isSelected(int x, int y) {
|
||||||
return x == selectedX && y == selectedY;
|
// return true if the exact square is currently picked up
|
||||||
|
return hasSelection && selectedX == x && selectedY == y;
|
||||||
|
// hasSelection is true the moment the user clicks on a piece for the first time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The following methods require more work ! */
|
||||||
|
|
||||||
public boolean isHighlighted(int x, int y) {
|
public boolean isHighlighted(int x, int y) {
|
||||||
for (int[] pos : highlightedSquares) {
|
if (!hasSelection) return false;
|
||||||
if (pos[0] == x && pos[1] == y){
|
|
||||||
|
// Find the selected piece
|
||||||
|
Piece selected = null;
|
||||||
|
for (Piece p : Pieces) {
|
||||||
|
if (p.getX() == selectedX && p.getY() == selectedY) {
|
||||||
|
selected = p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selected == null) return false;
|
||||||
|
|
||||||
|
int sx = selected.getX();
|
||||||
|
int sy = selected.getY();
|
||||||
|
boolean isWhite = selected.isWhite();
|
||||||
|
|
||||||
|
// PAWN LOGIC
|
||||||
|
if (selected.getType() == PieceType.Pawn) {
|
||||||
|
int dir = isWhite ? -1 : 1;
|
||||||
|
|
||||||
|
// One square forward
|
||||||
|
if (x == sx && y == sy + dir) {
|
||||||
|
if (getPieceAt(x, y) == null) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Two squares from initial rank
|
||||||
|
if ((isWhite && sy == 6) || (!isWhite && sy == 1)) {
|
||||||
|
if (x == sx && y == sy + 2 * dir) {
|
||||||
|
if (getPieceAt(sx, sy + dir) == null && getPieceAt(x, y) == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
private ArrayList<int[]> getValidMoves(Piece piece) {
|
|
||||||
ArrayList<int[]> moves = new ArrayList<>();
|
|
||||||
int x = piece.getX();
|
|
||||||
int y = piece.getY();
|
|
||||||
boolean isWhite = piece.isWhite();
|
|
||||||
PieceType type = piece.getType();
|
|
||||||
|
|
||||||
if (type == PieceType.Pawn) {
|
// Capture diagonally
|
||||||
int dir = isWhite ? -1 : 1;
|
if ((x == sx + 1 || x == sx - 1) && y == sy + dir) {
|
||||||
if (getPieceAt(x, y + dir) == null) {
|
Piece target = getPieceAt(x, y);
|
||||||
moves.add(new int[]{x, y + dir});
|
if (target != null && target.isWhite() != isWhite) return true;
|
||||||
}
|
|
||||||
// Capture left
|
|
||||||
if (getPieceAt(x - 1, y + dir) != null && getPieceAt(x - 1, y + dir).isWhite() != isWhite) {
|
|
||||||
moves.add(new int[]{x - 1, y + dir});
|
|
||||||
}
|
|
||||||
// Capture right
|
|
||||||
if (getPieceAt(x + 1, y + dir) != null && getPieceAt(x + 1, y + dir).isWhite() != isWhite) {
|
|
||||||
moves.add(new int[]{x + 1, y + dir});
|
|
||||||
}
|
|
||||||
} else if (type == PieceType.Rook) {
|
|
||||||
addLineMoves(moves, x, y, 1, 0, isWhite);
|
|
||||||
addLineMoves(moves, x, y, -1, 0, isWhite);
|
|
||||||
addLineMoves(moves, x, y, 0, 1, isWhite);
|
|
||||||
addLineMoves(moves, x, y, 0, -1, isWhite);
|
|
||||||
} else if (type == PieceType.Bishop) {
|
|
||||||
addLineMoves(moves, x, y, 1, 1, isWhite);
|
|
||||||
addLineMoves(moves, x, y, -1, 1, isWhite);
|
|
||||||
addLineMoves(moves, x, y, 1, -1, isWhite);
|
|
||||||
addLineMoves(moves, x, y, -1, -1, isWhite);
|
|
||||||
} else if (type == PieceType.Queen) {
|
|
||||||
addLineMoves(moves, x, y, 1, 0, isWhite);
|
|
||||||
addLineMoves(moves, x, y, -1, 0, isWhite);
|
|
||||||
addLineMoves(moves, x, y, 0, 1, isWhite);
|
|
||||||
addLineMoves(moves, x, y, 0, -1, isWhite);
|
|
||||||
addLineMoves(moves, x, y, 1, 1, isWhite);
|
|
||||||
addLineMoves(moves, x, y, -1, 1, isWhite);
|
|
||||||
addLineMoves(moves, x, y, 1, -1, isWhite);
|
|
||||||
addLineMoves(moves, x, y, -1, -1, isWhite);
|
|
||||||
} else if (type == PieceType.Knight) {
|
|
||||||
int[][] knightMoves = {
|
|
||||||
{2, 1}, {1, 2}, {-1, 2}, {-2, 1},
|
|
||||||
{-2, -1}, {-1, -2}, {1, -2}, {2, -1}
|
|
||||||
};
|
|
||||||
for (int[] d : knightMoves) {
|
|
||||||
int nx = x + d[0];
|
|
||||||
int ny = y + d[1];
|
|
||||||
if (isInsideBoard(nx, ny)) {
|
|
||||||
Piece p = getPieceAt(nx, ny);
|
|
||||||
if (p == null || p.isWhite() != isWhite) {
|
|
||||||
moves.add(new int[]{nx, ny});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (type == PieceType.King) {
|
|
||||||
for (int dx = -1; dx <= 1; dx++) {
|
|
||||||
for (int dy = -1; dy <= 1; dy++) {
|
|
||||||
if (dx != 0 || dy != 0) {
|
|
||||||
int nx = x + dx;
|
|
||||||
int ny = y + dy;
|
|
||||||
if (isInsideBoard(nx, ny)) {
|
|
||||||
Piece p = getPieceAt(nx, ny);
|
|
||||||
if (p == null || p.isWhite() != isWhite) {
|
|
||||||
moves.add(new int[]{nx, ny});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (type == PieceType.Pawn) {
|
|
||||||
int dir = isWhite ? -1 : 1;
|
|
||||||
|
|
||||||
if (isInsideBoard(x, y + dir) && getPieceAt(x, y + dir) == null) {
|
|
||||||
moves.add(new int[]{x, y + dir});
|
|
||||||
|
|
||||||
if ((isWhite && y == 6) || (!isWhite && y == 1)) {
|
|
||||||
if (isInsideBoard(x, y + 2 * dir) && getPieceAt(x, y + 2 * dir) == null) {
|
|
||||||
moves.add(new int[]{x, y + 2 * dir});
|
|
||||||
}
|
}
|
||||||
|
// En passant highlight
|
||||||
|
if ((x == sx + 1 || x == sx - 1) && y == sy + dir) {
|
||||||
|
if (lastDoubleStepPawn != null &&
|
||||||
|
lastDoubleStepPawn.getX() == x &&
|
||||||
|
lastDoubleStepPawn.getY() == sy &&
|
||||||
|
lastDoubleStepPawn.isWhite() != isWhite) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (isInsideBoard(x - 1, y + dir)) {
|
|
||||||
Piece captureLeft = getPieceAt(x - 1, y + dir);
|
|
||||||
if (captureLeft != null && captureLeft.isWhite() != isWhite) {
|
|
||||||
moves.add(new int[]{x - 1, y + dir});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ROOK LOGIC
|
||||||
|
if (selected.getType() == PieceType.Rook) {
|
||||||
|
int[][] directions = { {1,0}, {-1,0}, {0,1}, {0,-1} };
|
||||||
|
|
||||||
if (isInsideBoard(x + 1, y + dir)) {
|
for (int[] d : directions) {
|
||||||
Piece captureRight = getPieceAt(x + 1, y + dir);
|
int cx = sx + d[0];
|
||||||
if (captureRight != null && captureRight.isWhite() != isWhite) {
|
int cy = sy + d[1];
|
||||||
moves.add(new int[]{x + 1, y + dir});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return moves;
|
while (cx >= 0 && cx < width && cy >= 0 && cy < height) {
|
||||||
}
|
Piece target = getPieceAt(cx, cy);
|
||||||
|
|
||||||
private void addLineMoves(ArrayList<int[]> moves, int x, int y, int dx, int dy, boolean isWhite) {
|
|
||||||
int nx = x + dx;
|
|
||||||
int ny = y + dy;
|
|
||||||
while (isInsideBoard(nx, ny)) {
|
|
||||||
Piece target = getPieceAt(nx, ny);
|
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
moves.add(new int[]{nx, ny});
|
if (cx == x && cy == y) return true;
|
||||||
} else {
|
} else {
|
||||||
if (target.isWhite() != isWhite) {
|
if (target.isWhite() != isWhite && cx == x && cy == y) return true;
|
||||||
moves.add(new int[]{nx, ny});
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nx += dx;
|
|
||||||
ny += dy;
|
cx += d[0];
|
||||||
|
cy += d[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selected.getType() == PieceType.Knight) {
|
||||||
|
int[][] moves = {
|
||||||
|
{1, 2}, {2, 1}, {2, -1}, {1, -2},
|
||||||
|
{-1, -2}, {-2, -1}, {-2, 1}, {-1, 2}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int[] m : moves) {
|
||||||
|
int nx = sx + m[0];
|
||||||
|
int ny = sy + m[1];
|
||||||
|
|
||||||
|
if (nx == x && ny == y && nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
||||||
|
Piece target = getPieceAt(nx, ny);
|
||||||
|
if (target == null || target.isWhite() != isWhite) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// BISHOP LOGIC
|
||||||
|
if (selected.getType() == PieceType.Bishop) {
|
||||||
|
int[][] directions = { {1,1}, {-1,1}, {1,-1}, {-1,-1} };
|
||||||
|
|
||||||
|
for (int[] d : directions) {
|
||||||
|
int cx = sx + d[0];
|
||||||
|
int cy = sy + d[1];
|
||||||
|
|
||||||
|
while (cx >= 0 && cx < width && cy >= 0 && cy < height) {
|
||||||
|
Piece target = getPieceAt(cx, cy);
|
||||||
|
|
||||||
|
if (target == null) {
|
||||||
|
if (cx == x && cy == y) return true;
|
||||||
|
} else {
|
||||||
|
if (target.isWhite() != isWhite && cx == x && cy == y) return true;
|
||||||
|
break; // Stop if any piece blocks the diagonal
|
||||||
|
}
|
||||||
|
|
||||||
|
cx += d[0];
|
||||||
|
cy += d[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// QUEEN LOGIC
|
||||||
|
if (selected.getType() == PieceType.Queen) {
|
||||||
|
int[][] directions = {
|
||||||
|
{1, 0}, {-1, 0}, {0, 1}, {0, -1}, // Rook directions
|
||||||
|
{1, 1}, {-1, 1}, {1, -1}, {-1, -1} // Bishop directions
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int[] d : directions) {
|
||||||
|
int cx = sx + d[0];
|
||||||
|
int cy = sy + d[1];
|
||||||
|
|
||||||
|
while (cx >= 0 && cx < width && cy >= 0 && cy < height) {
|
||||||
|
Piece target = getPieceAt(cx, cy);
|
||||||
|
|
||||||
|
if (target == null) {
|
||||||
|
if (cx == x && cy == y) return true;
|
||||||
|
} else {
|
||||||
|
if (target.isWhite() != isWhite && cx == x && cy == y) return true;
|
||||||
|
break; // Stop if a piece blocks further movement
|
||||||
|
}
|
||||||
|
|
||||||
|
cx += d[0];
|
||||||
|
cy += d[1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInsideBoard(int x, int y) {
|
// KING LOGIC
|
||||||
return (x >= 0 && x < width && y >= 0 && y < height);
|
if (selected.getType() == PieceType.King) {
|
||||||
|
int[][] directions = {
|
||||||
|
{1, 0}, {-1, 0}, {0, 1}, {0, -1},
|
||||||
|
{1, 1}, {-1, 1}, {1, -1}, {-1, -1}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int[] d : directions) {
|
||||||
|
int nx = sx + d[0];
|
||||||
|
int ny = sy + d[1];
|
||||||
|
|
||||||
|
if (nx == x && ny == y && nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
||||||
|
Piece target = getPieceAt(nx, ny);
|
||||||
|
if (target == null || target.isWhite() != isWhite) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void undoLastMove() {
|
public void undoLastMove() {
|
||||||
|
if (moveHistory.isEmpty()) return;
|
||||||
|
|
||||||
|
// Get the last move from the history
|
||||||
|
Move last = moveHistory.pop();
|
||||||
|
|
||||||
|
// Remove the piece from the destination square
|
||||||
|
Pieces.removeIf(p -> p.getX() == last.getToX() && p.getY() == last.getToY());
|
||||||
|
|
||||||
|
// Restore the moved piece to its original position
|
||||||
|
Piece moved = last.getMovedPiece();
|
||||||
|
Pieces.add(new Piece(last.getFromX(), last.getFromY(), moved.isWhite(), moved.getType()));
|
||||||
|
|
||||||
|
// Restore the captured piece if it existed
|
||||||
|
Piece captured = last.getCapturedPiece();
|
||||||
|
if (captured != null) {
|
||||||
|
Pieces.add(new Piece(captured.getX(), captured.getY(), captured.isWhite(), captured.getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] toFileRep() {
|
// Revert turn number and color
|
||||||
|
turnNumber--;
|
||||||
|
turnWhite = !turnWhite;
|
||||||
|
|
||||||
return null;
|
// Clear selection
|
||||||
|
hasSelection = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Board(String[] array) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Board(Board board) {
|
public Board(Board board) {
|
||||||
|
this.width = board.width;
|
||||||
|
this.height = board.height;
|
||||||
|
this.turnNumber = board.turnNumber;
|
||||||
|
this.turnWhite = board.turnWhite;
|
||||||
|
this.hasSelection = board.hasSelection;
|
||||||
|
this.selectedX = board.selectedX;
|
||||||
|
this.selectedY = board.selectedY;
|
||||||
|
|
||||||
|
// Deep copy of pieces
|
||||||
|
this.Pieces = new ArrayList<>();
|
||||||
|
for (Piece p : board.Pieces) {
|
||||||
|
this.Pieces.add(new Piece(p.getX(), p.getY(), p.isWhite(), p.getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Optional: clear move history or leave empty to avoid shared reference
|
||||||
|
this.moveHistory = new Stack<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void playMove(Move move) {
|
public void playMove(Move move) {
|
||||||
|
// Remove the piece from the destination (if a capture)
|
||||||
|
Pieces.removeIf(p -> p.getX() == move.getToX() && p.getY() == move.getToY());
|
||||||
|
|
||||||
|
// Remove the moved piece from its old position
|
||||||
|
Pieces.removeIf(p -> p.getX() == move.getFromX() && p.getY() == move.getFromY());
|
||||||
|
|
||||||
|
// Add the moved piece to the new position
|
||||||
|
Piece moved = move.getMovedPiece();
|
||||||
|
boolean isWhite = moved.isWhite();
|
||||||
|
int toY = move.getToY();
|
||||||
|
PieceType type = moved.getType();
|
||||||
|
|
||||||
|
// Check for promotion
|
||||||
|
if (type == PieceType.Pawn && ((isWhite && toY == 0) || (!isWhite && toY == 7))) {
|
||||||
|
Pieces.add(new Piece(move.getToX(), toY, isWhite, PieceType.Queen));
|
||||||
|
} else {
|
||||||
|
Pieces.add(new Piece(move.getToX(), toY, isWhite, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Piece getPieceAt(int x, int y) {
|
// Save the move to history
|
||||||
for (Piece p : pieces) {
|
moveHistory.push(move);
|
||||||
if (p.getX() == x && p.getY() == y) {
|
|
||||||
return p;
|
// Update turn
|
||||||
|
turnNumber++;
|
||||||
|
turnWhite = !turnWhite;
|
||||||
|
|
||||||
|
// Clear selection
|
||||||
|
hasSelection = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Piece getPieceAt(int x, int y) {
|
||||||
|
for (Piece p : Pieces) {
|
||||||
|
if (p.getX() == x && p.getY() == y) return p;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
public void selectPiece(int x, int y) {
|
||||||
|
hasSelection = true;
|
||||||
|
selectedX = x;
|
||||||
|
selectedY = y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
package backend;
|
package backend;
|
||||||
|
|
||||||
import windowInterface.MyInterface;
|
import windowInterface.MyInterface;
|
||||||
|
|
@ -22,6 +23,13 @@ public class Game extends Thread {
|
||||||
activationAIFlags = new boolean[2];
|
activationAIFlags = new boolean[2];
|
||||||
aiPlayer = new AutoPlayer();
|
aiPlayer = new AutoPlayer();
|
||||||
}
|
}
|
||||||
|
public String[] getFileRepresentation() {
|
||||||
|
return board.toFileRep();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBoard(String[] array) {
|
||||||
|
board = new Board(array);
|
||||||
|
}
|
||||||
|
|
||||||
public int getWidth() {
|
public int getWidth() {
|
||||||
return board.getWidth();
|
return board.getWidth();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,51 @@
|
||||||
|
|
||||||
package backend;
|
package backend;
|
||||||
|
|
||||||
public class Move {
|
public class Move {
|
||||||
|
private final int fromX;
|
||||||
|
private final int fromY;
|
||||||
|
private final int toX;
|
||||||
|
private final int toY;
|
||||||
|
private final Piece movedPiece;
|
||||||
|
private final Piece capturedPiece;
|
||||||
|
|
||||||
|
// Constructor for a move (with or without capture)
|
||||||
|
public Move(Piece movedPiece, int toX, int toY, Piece capturedPiece) {
|
||||||
|
this.fromX = movedPiece.getX();
|
||||||
|
this.fromY = movedPiece.getY();
|
||||||
|
this.toX = toX;
|
||||||
|
this.toY = toY;
|
||||||
|
this.movedPiece = movedPiece;
|
||||||
|
this.capturedPiece = capturedPiece;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience constructor when there's no capture
|
||||||
|
public Move(Piece movedPiece, int toX, int toY) {
|
||||||
|
this(movedPiece, toX, toY, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
public int getFromX() {
|
||||||
|
return fromX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFromY() {
|
||||||
|
return fromY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getToX() {
|
||||||
|
return toX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getToY() {
|
||||||
|
return toY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Piece getMovedPiece() {
|
||||||
|
return movedPiece;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Piece getCapturedPiece() {
|
||||||
|
return capturedPiece;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,17 @@
|
||||||
package backend;
|
package backend;
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a chess piece with its position, type and color.
|
|
||||||
*/
|
|
||||||
public class Piece {
|
public class Piece {
|
||||||
|
|
||||||
private int x;
|
private int x;
|
||||||
private int y;
|
private int y;
|
||||||
private PieceType type;
|
|
||||||
private boolean isWhite;
|
private boolean isWhite;
|
||||||
|
private PieceType type;
|
||||||
|
|
||||||
public Piece(int x, int y, PieceType type, boolean isWhite) {
|
public Piece(int x, int y, boolean isWhite, PieceType type) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
this.type = type;
|
|
||||||
this.isWhite = isWhite;
|
this.isWhite = isWhite;
|
||||||
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getX() {
|
public int getX() {
|
||||||
|
|
@ -32,11 +30,4 @@ public class Piece {
|
||||||
return isWhite;
|
return isWhite;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setX(int x) {
|
|
||||||
this.x = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setY(int y) {
|
|
||||||
this.y = y;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,31 @@
|
||||||
package backend;
|
import backend.Board;
|
||||||
|
import backend.Piece;
|
||||||
|
import backend.PieceType;
|
||||||
|
|
||||||
public class Test_1 {
|
public class Test_1 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// Create a new board of size 8x8
|
||||||
|
Board board = new Board(8, 8);
|
||||||
|
|
||||||
|
// Populate the board with standard chess pieces
|
||||||
|
board.populateBoard();
|
||||||
|
|
||||||
|
// Print the board
|
||||||
|
System.out.println("Initial board:");
|
||||||
|
System.out.println(board.toString());
|
||||||
|
|
||||||
|
// Manually move a white pawn from (0,6) to (0,4) as a first move
|
||||||
|
board.userTouch(0, 6); // Select the pawn
|
||||||
|
board.userTouch(0, 4); // Move to 2 cells forward
|
||||||
|
|
||||||
|
System.out.println("After moving white pawn from (0,6) to (0,4):");
|
||||||
|
System.out.println(board.toString());
|
||||||
|
|
||||||
|
// Print turn and active color
|
||||||
|
System.out.println("Turn: " + board.getTurnNumber());
|
||||||
|
System.out.println("Is white's turn? " + board.isTurnWhite());
|
||||||
|
|
||||||
|
// Highlight test
|
||||||
|
System.out.println("Highlight status (0,3): " + board.isHighlighted(0, 3));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 954 B After Width: | Height: | Size: 954 B |
Binary file not shown.
|
After Width: | Height: | Size: 954 B |
|
|
@ -39,7 +39,11 @@ public class JPanelChessBoard extends JPanel {
|
||||||
selectedPieceType = PieceType.Pawn;
|
selectedPieceType = PieceType.Pawn;
|
||||||
pieceSelectorMode = false;
|
pieceSelectorMode = false;
|
||||||
try {
|
try {
|
||||||
spriteSheet = ImageIO.read(new File("pieces.png"));
|
System.out.println("LOADING: " + getClass().getResource("/pieces.png"));
|
||||||
|
|
||||||
|
spriteSheet = ImageIO.read(getClass().getResource("/pieces.png"));
|
||||||
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ public class MyInterface extends JFrame {
|
||||||
* Create the frame.
|
* Create the frame.
|
||||||
*/
|
*/
|
||||||
public MyInterface() {
|
public MyInterface() {
|
||||||
|
this.setVisible(true);
|
||||||
|
System.out.println("MyInterface constructor started");
|
||||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
setBounds(10, 10, 650, 650);
|
setBounds(10, 10, 650, 650);
|
||||||
contentPane = new JPanel();
|
contentPane = new JPanel();
|
||||||
|
|
@ -133,7 +135,6 @@ public class MyInterface extends JFrame {
|
||||||
|
|
||||||
});
|
});
|
||||||
panelTop.add(chckbxBlackAI);
|
panelTop.add(chckbxBlackAI);
|
||||||
|
|
||||||
panelDraw = new JPanelChessBoard(this);
|
panelDraw = new JPanelChessBoard(this);
|
||||||
contentPane.add(panelDraw, BorderLayout.CENTER);
|
contentPane.add(panelDraw, BorderLayout.CENTER);
|
||||||
}
|
}
|
||||||
|
|
@ -265,5 +266,4 @@ public class MyInterface extends JFrame {
|
||||||
public void eraseLabels() {
|
public void eraseLabels() {
|
||||||
this.setStepBanner("Turn : X");
|
this.setStepBanner("Turn : X");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue