From dc8c3d1faa228b73c6bf671052e5ffd4e180314b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?El=C3=A8ve?= Date: Fri, 18 Apr 2025 16:57:13 +0200 Subject: [PATCH] adding all the movements possibility and highlighting the squares. --- src/backend/Board.java | 491 +++++++++++++++++++++++++---------------- 1 file changed, 296 insertions(+), 195 deletions(-) diff --git a/src/backend/Board.java b/src/backend/Board.java index 33f3e10..a175569 100644 --- a/src/backend/Board.java +++ b/src/backend/Board.java @@ -3,56 +3,56 @@ package backend; import java.util.ArrayList; public class Board { - - private int selectedX = -1; //negative value means impossible x and y so unselected - private int selectedY = -1; - - private int turnNumber = 0; //track current turn - private int width; - private int height; - private Piece[][] board; //2D array chess board - public Board(int colNum, int lineNum) { - this.width = colNum; - this.height = lineNum; - this.board = new Piece[width][height]; //first empty board - clearConsole(); - System.out.println(toString()); //print the chess at the beginning of the game - } + private int selectedX = -1; // negative value means impossible x and y so unselected + private int selectedY = -1; - public int getWidth() { - return width; - } + private int turnNumber = 0; // track current turn + private int width; + private int height; + private Piece[][] board; // 2D array chess board + private ArrayList highlightedPositions = new ArrayList<>(); // list of valid positions to highlight - public int getHeight() { - return height; - } - - // new piece on the board at x,y - public void setPiece(boolean isWhite, PieceType type, int x, int y) { - board[x][y] = new Piece(x, y, type, isWhite); - } - - public boolean isTurnWhite() { - if (turnNumber % 2 == 0) { // even turns including O are white's ones - return true; - } - else { // same reasoning, odd turns are black's ones - return false; - } - } - - public int getTurnNumber() { //theses classes change the turn and the increment one solve a problem of infinite loop - return turnNumber; - } - - public void incrementTurn() { - turnNumber++; - } + public Board(int colNum, int lineNum) { + this.width = colNum; + this.height = lineNum; + this.board = new Piece[width][height]; // first empty board + clearConsole(); + System.out.println(toString()); // print the chess at the beginning of the game + } - //set up the chess board taking it as a matrix - public void populateBoard() { - // Black + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + // new piece on the board at x,y + public void setPiece(boolean isWhite, PieceType type, int x, int y) { + board[x][y] = new Piece(x, y, type, isWhite); + } + + public boolean isTurnWhite() { + if (turnNumber % 2 == 0) { // even turns including 0 are white's ones + return true; + } else { // same reasoning, odd turns are black's ones + return false; + } + } + + public int getTurnNumber() { // these classes change the turn and the increment one solves a problem of infinite loop + return turnNumber; + } + + public void incrementTurn() { + turnNumber++; + } + + // set up the chess board taking it as a matrix + public void populateBoard() { + // Black setPiece(false, PieceType.Rook, 0, 0); setPiece(false, PieceType.Knight, 1, 0); setPiece(false, PieceType.Bishop, 2, 0); @@ -63,12 +63,12 @@ public class Board { setPiece(false, PieceType.Rook, 7, 0); // Black pawns - for(int i = 0; i < 8; i++) { + for (int i = 0; i < 8; i++) { setPiece(false, PieceType.Pawn, i, 1); } // White pawns - for(int i = 0; i < 8; i++) { + for (int i = 0; i < 8; i++) { setPiece(true, PieceType.Pawn, i, 6); } @@ -81,164 +81,265 @@ public class Board { setPiece(true, PieceType.Bishop, 5, 7); setPiece(true, PieceType.Knight, 6, 7); setPiece(true, PieceType.Rook, 7, 7); - } - - public void cleanBoard() { - for(int x = 0; x < width; x++) { - for(int y = 0; y < height; y++) { - board[x][y] = null; //each position become empty - } - } - } - + } - private void clearConsole() { - for(int i = 0; i < 50; i++) { - System.out.println(); // Print 50 empty lines to "clear" the console - } - } - - public String toString() { - StringBuilder str = new StringBuilder(); - - str.append(" A B C D E F G H\n"); //columns letter at the top - - // representation of the rows - for(int y = 0; y < height; y++) { - str.append(8 - y).append(" "); // row number on the left - - for(int x = 0; x < width; x++) { - if(board[x][y] == null) { - str.append("- "); // empty positions - } else { - - // convert each piece of both color into a character - Piece piece = board[x][y]; - char pieceChar; //one character - - switch(piece.getType()) { //switch function solve the problem of too many if-else - case King: pieceChar = 'K'; break; //case is reading in king and break stop the switch function - case Queen: pieceChar = 'Q'; break; - case Bishop: pieceChar = 'B'; break; - case Knight: pieceChar = 'N'; break; // N because we already have King - case Rook: pieceChar = 'R'; break; - case Pawn: pieceChar = 'P'; break; - default: pieceChar = '?'; break; //solve an issue of unresolved compilation and act as a safety net - } - - // Make black pieces in lowercase - if(!piece.isWhite()) { - pieceChar = Character.toLowerCase(pieceChar); - } - - str.append(pieceChar).append(" "); //gives structure to the output - } - } - str.append("\n"); //change of row - } - - // Additional infos for a proper ouput - str.append("Turn ").append(getTurnNumber()).append(": "); //turnnumber - str.append(isTurnWhite() ? "White" : "Black"); //color's turn - - return str.toString(); - } - - //list the placement of the pieces on the board - public ArrayList getPieces() { - ArrayList pieces = new ArrayList<>(); - //collect infos for the empty positions - for(int x = 0; x < width; x++) { - for(int y = 0; y < height; y++) { - if(board[x][y] != null) { - pieces.add(board[x][y]); - } - } - } - return pieces; - } + public void cleanBoard() { + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + board[x][y] = null; // each position becomes empty + } + } + } - //user click on the board - public void userTouch(int x, int y) { - // 1: no position was previously selected - if (selectedX == -1 && selectedY == -1) { - // check if the position is empty and the color - if (board[x][y] != null && board[x][y].isWhite() == isTurnWhite()) { - // select it as active location - selectedX = x; - selectedY = y; - } - } - // 2: position was already selected - else { - // 2.1: click on the same position - if (x == selectedX && y == selectedY) { - // unselect it - selectedX = -1; - selectedY = -1; - } - // 2.2: click on a different position - else { - // Move piece - Piece pieceToMove = board[selectedX][selectedY]; - board[x][y] = new Piece(x, y, pieceToMove.getType(), pieceToMove.isWhite()); - board[selectedX][selectedY] = null; - - // reset the choose of position - selectedX = -1; - selectedY = -1; - - //update the game - incrementTurn(); - clearConsole(); - System.out.println(toString()); - } - } - - } - - public boolean isSelected(int x, int y) { - return (x == selectedX && y == selectedY);//true if matching position - } - - /* saving-loading feature :*/ + private void clearConsole() { + for (int i = 0; i < 50; i++) { + System.out.println(); // Print 50 empty lines to "clear" the console + } + } - public String[] toFileRep() { - //TODO - return null; - } + public String toString() { + StringBuilder str = new StringBuilder(); + str.append(" A B C D E F G H\n"); // columns letter at the top - public Board(String[] array) { - //TODO + // representation of the rows + for (int y = 0; y < height; y++) { + str.append(8 - y).append(" "); // row number on the left - } - - /* The following methods require more work ! */ + for (int x = 0; x < width; x++) { + if (board[x][y] == null) { + str.append("- "); // empty positions + } else { + // convert each piece of both color into a character + Piece piece = board[x][y]; + char pieceChar; - public boolean isHighlighted(int x, int y) { - //TODO - return false; - } + switch (piece.getType()) { // switch function avoids too many if-else + case King: pieceChar = 'K'; break; + case Queen: pieceChar = 'Q'; break; + case Bishop: pieceChar = 'B'; break; + case Knight: pieceChar = 'N'; break; // N because we already have King + case Rook: pieceChar = 'R'; break; + case Pawn: pieceChar = 'P'; break; + default: pieceChar = '?'; break; // safety net + } - public void undoLastMove() { - //TODO - - } + // Make black pieces in lowercase + if (!piece.isWhite()) { + pieceChar = Character.toLowerCase(pieceChar); + } - public Board(Board board) { - //TODO + str.append(pieceChar).append(" "); // gives structure to the output + } + } + str.append("\n"); // change of row + } - } - - public void playMove(Move move) { - //TODO + // Additional infos for a proper output + str.append("Turn ").append(getTurnNumber()).append(": "); + str.append(isTurnWhite() ? "White" : "Black"); - } + return str.toString(); + } - public boolean isEmpty(int x, int newY) { - // TODO Auto-generated method stub - return false; - } + // list the placement of the pieces on the board + public ArrayList getPieces() { + ArrayList pieces = new ArrayList<>(); + // collect infos for the non-empty positions + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + if (board[x][y] != null) { + pieces.add(board[x][y]); + } + } + } + return pieces; + } + // user clicks on the board + public void userTouch(int x, int y) { + if (selectedX == -1 && selectedY == -1) { + // check if the position is empty and the color + if (board[x][y] != null && board[x][y].isWhite() == isTurnWhite()) { + // select it as active location + selectedX = x; + selectedY = y; + highlightedPositions = getValidMoves(board[x][y]); // compute moves + } + } else { + if (x == selectedX && y == selectedY) { + // unselect it + selectedX = -1; + selectedY = -1; + highlightedPositions.clear(); + } else { + // move if valid destination + boolean valid = false; + for (int[] pos : highlightedPositions) { + if (pos[0] == x && pos[1] == y) { + valid = true; + break; + } + } + if (valid) { + Piece pieceToMove = board[selectedX][selectedY]; + board[x][y] = new Piece(x, y, pieceToMove.getType(), pieceToMove.isWhite()); + board[selectedX][selectedY] = null; + incrementTurn(); + } + + // reset selection + selectedX = -1; + selectedY = -1; + highlightedPositions.clear(); + clearConsole(); + System.out.println(toString()); + } + } + } + + public boolean isSelected(int x, int y) { + return (x == selectedX && y == selectedY); // true if matching position + } + + public boolean isHighlighted(int x, int y) { + for (int[] pos : highlightedPositions) { + if (pos[0] == x && pos[1] == y) { + return true; + } + } + return false; + } + + /* utility methods */ + private boolean isInBounds(int x, int y) { + return x >= 0 && x < width && y >= 0 && y < height; + } + + private void addLinearMoves(ArrayList moves, int x, int y, Piece piece, int dx, int dy) { + int nx = x + dx; + int ny = y + dy; + while (isInBounds(nx, ny)) { + if (board[nx][ny] == null) { + moves.add(new int[]{nx, ny}); + } else { + if (board[nx][ny].isWhite() != piece.isWhite()) { + moves.add(new int[]{nx, ny}); + } + break; + } + nx += dx; + ny += dy; + } + } + + private ArrayList getValidMoves(Piece piece) { + ArrayList moves = new ArrayList<>(); + int x = piece.getX(); + int y = piece.getY(); + + switch (piece.getType()) { + case Pawn: + int direction = piece.isWhite() ? -1 : 1; + int nextY = y + direction; + + // forward move + if (isInBounds(x, nextY) && board[x][nextY] == null) { + moves.add(new int[]{x, nextY}); + + // double move from starting position + int startRow = piece.isWhite() ? 6 : 1; + int doubleStepY = y + 2 * direction; + if (y == startRow && isInBounds(x, doubleStepY) && board[x][doubleStepY] == null) { + moves.add(new int[]{x, doubleStepY}); + } + } + + // diagonal captures + for (int dx = -1; dx <= 1; dx += 2) { + int nx = x + dx; + if (isInBounds(nx, nextY) && board[nx][nextY] != null && board[nx][nextY].isWhite() != piece.isWhite()) { + moves.add(new int[]{nx, nextY}); + } + } + break; + + case Rook: + addLinearMoves(moves, x, y, piece, 1, 0); + addLinearMoves(moves, x, y, piece, -1, 0); + addLinearMoves(moves, x, y, piece, 0, 1); + addLinearMoves(moves, x, y, piece, 0, -1); + break; + + case Bishop: + addLinearMoves(moves, x, y, piece, 1, 1); + addLinearMoves(moves, x, y, piece, -1, 1); + addLinearMoves(moves, x, y, piece, 1, -1); + addLinearMoves(moves, x, y, piece, -1, -1); + break; + + case Queen: + for (int dx = -1; dx <= 1; dx++) { + for (int dy = -1; dy <= 1; dy++) { + if (dx != 0 || dy != 0) { + addLinearMoves(moves, x, y, piece, dx, dy); + } + } + } + break; + + case 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 (isInBounds(nx, ny) && (board[nx][ny] == null || board[nx][ny].isWhite() != piece.isWhite())) { + moves.add(new int[]{nx, ny}); + } + } + } + } + break; + + case Knight: + int[][] jumps = { + {1, 2}, {2, 1}, {-1, 2}, {-2, 1}, + {-1, -2}, {-2, -1}, {1, -2}, {2, -1} + }; + for (int[] j : jumps) { + int nx = x + j[0]; + int ny = y + j[1]; + if (isInBounds(nx, ny) && (board[nx][ny] == null || board[nx][ny].isWhite() != piece.isWhite())) { + moves.add(new int[]{nx, ny}); + } + } + break; + } + + return moves; + } + + /* saving-loading feature : */ + public String[] toFileRep() { + // TODO + return null; + } + + public Board(String[] array) { + // TODO + } + + /* additional functionality to implement later */ + public void undoLastMove() { + // TODO + } + + public void playMove(Move move) { + // TODO + } + + public Board(Board board) { + // TODO + } }