From b20a1a1c9cdc015f7858c3a7d3fc5b74d0c293a1 Mon Sep 17 00:00:00 2001 From: jefei Date: Fri, 16 May 2025 01:03:56 +0200 Subject: [PATCH] Save Load Undo En Passant Working --- src/Main.java | 3 +- src/backend/AutoPlayer.java | 46 +- src/backend/Board.java | 812 ++++++++++++++-------- src/backend/Game.java | 8 + src/backend/Move.java | 48 +- src/backend/Piece.java | 65 +- src/backend/Test_1.java | 28 +- pieces.png => src/pieces.png | Bin src/resources/pieces.png | Bin 0 -> 954 bytes src/windowInterface/JPanelChessBoard.java | 6 +- src/windowInterface/MyInterface.java | 6 +- 11 files changed, 678 insertions(+), 344 deletions(-) rename pieces.png => src/pieces.png (100%) create mode 100644 src/resources/pieces.png diff --git a/src/Main.java b/src/Main.java index ce07336..870cae7 100644 --- a/src/Main.java +++ b/src/Main.java @@ -18,4 +18,5 @@ public class Main { MyInterface mjf = new MyInterface(); mjf.setVisible(true); } -} \ No newline at end of file + +} diff --git a/src/backend/AutoPlayer.java b/src/backend/AutoPlayer.java index a988a22..a5364ca 100644 --- a/src/backend/AutoPlayer.java +++ b/src/backend/AutoPlayer.java @@ -1,17 +1,35 @@ + package backend; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Random; + + public class AutoPlayer { - - - /** - * returns the best Move to try on provided board for active player - * @param board - * @return - */ - public Move computeBestMove(Board board) { - - return null; - } - - -} + private Random rand = new Random(); + + public Move computeBestMove(Board board) { + ArrayList allMoves = new ArrayList<>(); + for (Piece p : board.getPieces()) { + if (p.isWhite() == board.isTurnWhite()) { + int fromX = p.getX(); + int fromY = p.getY(); + + 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())); + } +} \ No newline at end of file diff --git a/src/backend/Board.java b/src/backend/Board.java index 594d56b..6969ba9 100644 --- a/src/backend/Board.java +++ b/src/backend/Board.java @@ -1,303 +1,543 @@ package backend; import java.util.ArrayList; +import java.util.Stack; public class Board { - private int width; - private int height; - private ArrayList pieces; - private int turnNumber; - private boolean isTurnWhite; - private int selectedX, selectedY; - private ArrayList highlightedSquares; +private Piece lastDoubleStepPawn = null; +private int width; +private int height; +private ArrayList Pieces; +private Stack moveHistory = new Stack<>(); - public Board(int colNum, int lineNum) { - this.width = colNum; - this.height = lineNum; - this.pieces = new ArrayList<>(); - this.turnNumber = 0; - this.isTurnWhite = true; - this.selectedX = -1; - this.selectedY = -1; - this.highlightedSquares = new ArrayList<>(); +// ── NEW FIELDS FOR userTouch ─────────────────────────────────────── +private boolean hasSelection = false; // did we already click to pick up a piece? +private int selectedX, selectedY; // if so, which square is “in hand”? +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]; - } - - public int getWidth() { - return this.width; - } - - public int getHeight() { - return this.height; - } - - public int getTurnNumber() { - return this.turnNumber; - } - - public boolean isTurnWhite() { - return this.isTurnWhite; - } - - 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 - pieces.add(new Piece(x, y, type, isWhite)); - } - - public void populateBoard() { - cleanBoard(); - - setPiece(false, PieceType.Rook, 0, 0); - setPiece(false, PieceType.Knight, 1, 0); - setPiece(false, PieceType.Bishop, 2, 0); - setPiece(false, PieceType.Queen, 3, 0); - setPiece(false, PieceType.King, 4, 0); - setPiece(false, PieceType.Bishop, 5, 0); - setPiece(false, PieceType.Knight, 6, 0); - setPiece(false, PieceType.Rook, 7, 0); - - for (int x = 0; x < width; x++) { - setPiece(false, PieceType.Pawn, x, 1); - } - - for (int x = 0; x < width; x++) { - setPiece(true, PieceType.Pawn, x, 6); - } - - 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() { - pieces.clear(); - } - - public String toString() { + for (int y = 0; y < height; y++) { StringBuilder sb = new StringBuilder(); - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - Piece p = getPieceAt(x, y); - if (p != null) { - sb.append(p.isWhite() ? "W" : "B"); - sb.append(p.getType().getSummary()); - } else { - sb.append("__"); - } - sb.append(" "); - } - sb.append("\n"); - } - return sb.toString(); - } - - public ArrayList getPieces() { - return pieces; - } - - public void userTouch(int x, int y) { - Piece selectedPiece = getPieceAt(selectedX, selectedY); - - if (selectedPiece == null) { - Piece piece = getPieceAt(x, y); - if (piece != null && piece.isWhite() == isTurnWhite) { - selectedX = x; - selectedY = y; - highlightedSquares = getValidMoves(piece); // compute highlights normally - } - } else { - if (x == selectedX && y == selectedY) { - selectedX = -1; - selectedY = -1; - highlightedSquares.clear(); - } else { - Piece destinationPiece = getPieceAt(x, y); - selectedPiece.setX(x); - selectedPiece.setY(y); - - if (destinationPiece != null && destinationPiece.isWhite() != selectedPiece.isWhite()) { - pieces.remove(destinationPiece); - } - - turnNumber++; - isTurnWhite = !isTurnWhite; - - selectedX = -1; - selectedY = -1; - highlightedSquares.clear(); - } - } - } - - public boolean isSelected(int x, int y) { - return x == selectedX && y == selectedY; - } - - public boolean isHighlighted(int x, int y) { - for (int[] pos : highlightedSquares) { - if (pos[0] == x && pos[1] == y){ - return true; - } - } - return false; - } - private ArrayList getValidMoves(Piece piece) { - ArrayList moves = new ArrayList<>(); - int x = piece.getX(); - int y = piece.getY(); - boolean isWhite = piece.isWhite(); - PieceType type = piece.getType(); - - if (type == PieceType.Pawn) { - int dir = isWhite ? -1 : 1; - if (getPieceAt(x, y + dir) == null) { - moves.add(new int[]{x, y + dir}); - } - // 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}); - } - } - } - - - 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}); - } - } - - - if (isInsideBoard(x + 1, y + dir)) { - Piece captureRight = getPieceAt(x + 1, y + dir); - if (captureRight != null && captureRight.isWhite() != isWhite) { - moves.add(new int[]{x + 1, y + dir}); - } - } - } - - return moves; - } - - private void addLineMoves(ArrayList 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) { - moves.add(new int[]{nx, ny}); + for (int x = 0; x < width; x++) { + Piece p = getPieceAt(x, y); + if (p == null) { + sb.append(".."); } else { - if (target.isWhite() != isWhite) { - moves.add(new int[]{nx, ny}); + 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; + + 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() { + return width; +} + +public int getHeight() { + return height; +} + +public int getTurnNumber() { + //TODO + return turnNumber; +} + +public boolean isTurnWhite() { + //TODO + return turnWhite; +} + +public void setPiece(boolean isWhite, PieceType type, int x, int y) { + // 1) Remove any piece already at this square + 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() { + // 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)); + + Pieces.add(new Piece(0,1,false,PieceType.Pawn)); + Pieces.add(new Piece(1,1,false,PieceType.Pawn)); + Pieces.add(new Piece(2,1,false,PieceType.Pawn)); + Pieces.add(new Piece(3,1,false,PieceType.Pawn)); + Pieces.add(new Piece(4,1,false,PieceType.Pawn)); + Pieces.add(new Piece(5,1,false,PieceType.Pawn)); + Pieces.add(new Piece(6,1,false,PieceType.Pawn)); + 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)); + +} + +public ArrayList getPieces(){ + return Pieces; +} + +public void cleanBoard() { + Pieces.clear(); +} + +public String toString() { + StringBuilder sb = new StringBuilder(); + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + Piece found = null; + for (Piece p : Pieces) { + if (p.getX() == x && p.getY() == y) { + found = p; + break; } - break; } - nx += dx; - ny += dy; + + if (found != null) { + String color = found.isWhite() ? "W" : "B"; + sb.append(color).append(found.getType().getSummary()).append(" "); + } else { + sb.append(".. "); + } + } + sb.append("\n"); + } + + return sb.toString(); +} +public void userTouch(int x, int y) { + // 1) Find if you clicked on a piece at (x,y) + Piece clicked = null; + for (Piece p : Pieces) { + if (p.getX() == x && p.getY() == y) { + clicked = p; + break; } } - private boolean isInsideBoard(int x, int y) { - return (x >= 0 && x < width && y >= 0 && y < height); - } - - public void undoLastMove() { - - } - - public String[] toFileRep() { - - return null; - } - - public Board(String[] array) { - - } - - public Board(Board board) { - - } - - public void playMove(Move move) { - - } - - private Piece getPieceAt(int x, int y) { - for (Piece p : pieces) { - if (p.getX() == x && p.getY() == y) { - return p; - } + // 2) If nothing is selected, select a piece of the correct color + if (!hasSelection) { + if (clicked != null && clicked.isWhite() == turnWhite) { + hasSelection = true; + selectedX = x; + selectedY = y; } - return null; + return; + } + + // 3) If you click the same square again → deselect + if (x == selectedX && y == selectedY) { + hasSelection = false; + return; + } + + // 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 { + // Normal move + Pieces.add(new Piece(x, y, isWhite, type)); + } + + // 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++; + turnWhite = !turnWhite; + hasSelection = false; + + Move move = new Move(toMove, x, y, captured); // captured may be null + moveHistory.push(move); + System.out.println(this); } } + +public boolean isSelected(int x, int y) { + // 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) { + if (!hasSelection) return false; + + // 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; + } + } + } + + // Capture diagonally + if ((x == sx + 1 || x == sx - 1) && y == sy + dir) { + Piece target = getPieceAt(x, y); + if (target != null && target.isWhite() != isWhite) return true; + } + // 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; + } + } + + } + + // ROOK LOGIC + if (selected.getType() == PieceType.Rook) { + int[][] directions = { {1,0}, {-1,0}, {0,1}, {0,-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; + } + + 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]; + } + } + } + + // KING LOGIC + 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() { + 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())); + } + + // Revert turn number and color + turnNumber--; + turnWhite = !turnWhite; + + // Clear selection + hasSelection = false; +} + + +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) { + // 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)); + } + + // Save the move to history + moveHistory.push(move); + + // 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; +} +public void selectPiece(int x, int y) { + hasSelection = true; + selectedX = x; + selectedY = y; +} +} diff --git a/src/backend/Game.java b/src/backend/Game.java index 4c64f70..41ca541 100644 --- a/src/backend/Game.java +++ b/src/backend/Game.java @@ -1,3 +1,4 @@ + package backend; import windowInterface.MyInterface; @@ -22,6 +23,13 @@ public class Game extends Thread { activationAIFlags = new boolean[2]; aiPlayer = new AutoPlayer(); } + public String[] getFileRepresentation() { + return board.toFileRep(); + } + + public void setBoard(String[] array) { + board = new Board(array); + } public int getWidth() { return board.getWidth(); diff --git a/src/backend/Move.java b/src/backend/Move.java index 5f64282..b62286e 100644 --- a/src/backend/Move.java +++ b/src/backend/Move.java @@ -1,5 +1,51 @@ + package backend; 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; + } } diff --git a/src/backend/Piece.java b/src/backend/Piece.java index 0069582..40d9369 100644 --- a/src/backend/Piece.java +++ b/src/backend/Piece.java @@ -1,42 +1,33 @@ package backend; -/** - * Represents a chess piece with its position, type and color. - */ public class Piece { - private int x; - private int y; - private PieceType type; - private boolean isWhite; + + private int x; + private int y; + private boolean isWhite; + private PieceType type; + + public Piece(int x, int y, boolean isWhite, PieceType type) { + this.x = x; + this.y = y; + this.isWhite = isWhite; + this.type = type; + } + + public int getX() { + return x; + } - public Piece(int x, int y, PieceType type, boolean isWhite) { - this.x = x; - this.y = y; - this.type = type; - this.isWhite = isWhite; - } - - public int getX() { - return x; - } - - public int getY() { - return y; - } - - public PieceType getType() { - return type; - } - - public boolean isWhite() { - return isWhite; - } - - public void setX(int x) { - this.x = x; - } - - public void setY(int y) { - this.y = y; - } + public int getY() { + return y; + } + + public PieceType getType() { + return type; + } + + public boolean isWhite() { + return isWhite; + } + } diff --git a/src/backend/Test_1.java b/src/backend/Test_1.java index 239f87c..b474d46 100644 --- a/src/backend/Test_1.java +++ b/src/backend/Test_1.java @@ -1,5 +1,31 @@ -package backend; +import backend.Board; +import backend.Piece; +import backend.PieceType; 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)); + } } diff --git a/pieces.png b/src/pieces.png similarity index 100% rename from pieces.png rename to src/pieces.png diff --git a/src/resources/pieces.png b/src/resources/pieces.png new file mode 100644 index 0000000000000000000000000000000000000000..01cc2f8e0723c40907fcafb30d2044adb1dbd2ff GIT binary patch literal 954 zcmV;r14aCaP)Px&bV)=(RA_n93+CyBv1*&Oq{|ll?3Z58QD>Akp8lm*j5papY>-F z_|!G7(E+F0t>l*zXgEm&ZX>9f!1N&qw-hUoZ8N-SbSxaZQZ4>gfJ_4KfM-5!RAwmJ zMI2yF^HZ4sCXebFxEx$X2W8v9$LS)4Z@xqo@XOd44k-syX8#}){C6-GEbrN>nHrbpkZqDvUnK2wjy?t@5Rq@NFzyDK7;PhNe%$nS?gU#z?WPf0 z=Bh{9D_%50EY8Tmu^pC9C;6oj)D`T4XjaOO$^;XQ5ZQ&5aq|iC@qZ7s^`d)qG970lGuj~I+H*dh?h7i*(5ku$?%p{z4<&P9=274 zgXq}=KDD{39dO#*N`5DSnpAR7{v54Ix!65KGqwpIS0_1l@pkYLe#J+}w~8l>Q`XTg{0sZ)wNvYW cJN8}q0;pW6z5*s-O#lD@07*qoM6N<$g2Ji5hX4Qo literal 0 HcmV?d00001 diff --git a/src/windowInterface/JPanelChessBoard.java b/src/windowInterface/JPanelChessBoard.java index 78a68de..1368e37 100644 --- a/src/windowInterface/JPanelChessBoard.java +++ b/src/windowInterface/JPanelChessBoard.java @@ -39,7 +39,11 @@ public class JPanelChessBoard extends JPanel { selectedPieceType = PieceType.Pawn; pieceSelectorMode = false; 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) { e.printStackTrace(); } diff --git a/src/windowInterface/MyInterface.java b/src/windowInterface/MyInterface.java index b7e2549..513842a 100644 --- a/src/windowInterface/MyInterface.java +++ b/src/windowInterface/MyInterface.java @@ -47,6 +47,8 @@ public class MyInterface extends JFrame { * Create the frame. */ public MyInterface() { + this.setVisible(true); + System.out.println("MyInterface constructor started"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(10, 10, 650, 650); contentPane = new JPanel(); @@ -133,7 +135,6 @@ public class MyInterface extends JFrame { }); panelTop.add(chckbxBlackAI); - panelDraw = new JPanelChessBoard(this); contentPane.add(panelDraw, BorderLayout.CENTER); } @@ -265,5 +266,4 @@ public class MyInterface extends JFrame { public void eraseLabels() { this.setStepBanner("Turn : X"); } - -} +} \ No newline at end of file