diff --git a/.gitignore b/.gitignore index f5d05e7..d19c5f6 100644 --- a/.gitignore +++ b/.gitignore @@ -112,4 +112,5 @@ buildNumber.properties # JDT-specific (Eclipse Java Development Tools) .classpath +.idea # End of https://www.toptal.com/developers/gitignore/api/java,maven,eclipse diff --git a/pom.xml b/pom.xml index 5bafd03..429da2c 100644 --- a/pom.xml +++ b/pom.xml @@ -100,19 +100,6 @@ maven-project-info-reports-plugin 3.0.0 - - - org.pitest - pitest-maven - 1.15.2 - - - org.pitest - pitest-junit5-plugin - 1.2.1 - - - diff --git a/src/main/java/com/rogeriofrsouza/app/Program.java b/src/main/java/com/rogeriofrsouza/app/Program.java index f6f806f..95fb381 100644 --- a/src/main/java/com/rogeriofrsouza/app/Program.java +++ b/src/main/java/com/rogeriofrsouza/app/Program.java @@ -1,10 +1,5 @@ package com.rogeriofrsouza.app; -import com.rogeriofrsouza.app.chess.ChessException; -import com.rogeriofrsouza.app.chess.ChessMatch; -import com.rogeriofrsouza.app.chess.ChessPiece; -import com.rogeriofrsouza.app.chess.ChessPosition; - import java.util.ArrayList; import java.util.InputMismatchException; import java.util.List; @@ -12,6 +7,11 @@ import java.util.Optional; import java.util.Scanner; +import com.rogeriofrsouza.app.chess.ChessException; +import com.rogeriofrsouza.app.chess.ChessMatch; +import com.rogeriofrsouza.app.chess.ChessPiece; +import com.rogeriofrsouza.app.chess.ChessPosition; + public class Program { public static void main(String[] args) { @@ -42,14 +42,14 @@ public static void main(String[] args) { if (chessMatch.getPromoted() != null) { System.out.print("Enter piece for promotion (B/N/R/Q): "); - String type = scanner.nextLine().substring(0, 1).toUpperCase(); + ChessPiece.Name pieceName = ui.readPromotedPiece(scanner); - while (!List.of("B", "N", "R", "Q").contains(type)) { + while (pieceName == null) { System.err.print("Invalid value! Enter piece for promotion (B/N/R/Q): "); - type = scanner.nextLine().substring(0, 1).toUpperCase(); + pieceName = ui.readPromotedPiece(scanner); } - chessMatch.replacePromotedPiece(type); + chessMatch.replacePromotedPiece(pieceName); } } catch (ChessException | InputMismatchException exception) { System.err.println(exception.getMessage()); diff --git a/src/main/java/com/rogeriofrsouza/app/UI.java b/src/main/java/com/rogeriofrsouza/app/UI.java index ca058be..c7f9248 100644 --- a/src/main/java/com/rogeriofrsouza/app/UI.java +++ b/src/main/java/com/rogeriofrsouza/app/UI.java @@ -3,12 +3,10 @@ import com.rogeriofrsouza.app.chess.ChessMatch; import com.rogeriofrsouza.app.chess.ChessPiece; import com.rogeriofrsouza.app.chess.ChessPosition; -import com.rogeriofrsouza.app.chess.Color; import java.util.InputMismatchException; import java.util.List; import java.util.Scanner; -import java.util.stream.Collectors; public class UI { @@ -30,21 +28,18 @@ public void clearScreen() { public void printMatch(ChessMatch chessMatch, List captured) { printBoard(chessMatch.getPieces(), null); - List white = - captured.stream() - .filter(piece -> piece.getColor() == Color.WHITE) - .collect(Collectors.toList()); + List white = captured.stream() + .filter(piece -> piece.getColor() == ChessPiece.Color.WHITE) + .toList(); - List black = - captured.stream() - .filter(piece -> piece.getColor() == Color.BLACK) - .collect(Collectors.toList()); + List black = captured.stream() + .filter(piece -> piece.getColor() == ChessPiece.Color.BLACK) + .toList(); System.out.println("\nCaptured pieces"); - System.out.printf( - "White: %s%s%n%sBlack: %s%s%n%s", - ANSI_WHITE, white, ANSI_RESET, ANSI_YELLOW, black, ANSI_RESET); + System.out.printf("White: %s%s%n%sBlack: %s%s%n%s", + ANSI_WHITE, white, ANSI_RESET, ANSI_YELLOW, black, ANSI_RESET); System.out.println("\nTurn: " + chessMatch.getTurn()); @@ -64,7 +59,7 @@ public void printBoard(ChessPiece[][] pieces, boolean[][] possibleMoves) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < pieces.length; i++) { - stringBuilder.append((8 - i) + " "); + stringBuilder.append((8 - i)).append(" "); for (int j = 0; j < pieces[i].length; j++) { if (possibleMoves != null && possibleMoves[i][j]) { @@ -74,9 +69,10 @@ public void printBoard(ChessPiece[][] pieces, boolean[][] possibleMoves) { if (pieces[i][j] == null) { stringBuilder.append("-"); } else { - String color = - pieces[i][j].getColor() == Color.WHITE ? ANSI_WHITE : ANSI_YELLOW; - stringBuilder.append(color + pieces[i][j]); + String color = pieces[i][j].getColor() == ChessPiece.Color.WHITE + ? ANSI_WHITE + : ANSI_YELLOW; + stringBuilder.append(color).append(pieces[i][j]); } stringBuilder.append(ANSI_RESET + " "); @@ -86,15 +82,25 @@ public void printBoard(ChessPiece[][] pieces, boolean[][] possibleMoves) { } stringBuilder.append(" a b c d e f g h"); - System.out.println(stringBuilder.toString()); + System.out.println(stringBuilder); } - public ChessPosition readChessPosition(Scanner scanner) { + private String readInput(Scanner scanner) { String input = scanner.nextLine(); + if (input == null || input.trim().isBlank()) { + throw new InputMismatchException("Error reading input: cannot be null or blank."); + } + + return input.trim(); + } + + public ChessPosition readChessPosition(Scanner scanner) { + String input = readInput(scanner); + if (!input.matches("[a-h][1-8]")) { throw new InputMismatchException( - "Error reading ChessPosition. Valid values are from a1 to h8."); + "Error reading ChessPosition. Valid values are from a1 to h8."); } char column = input.charAt(0); @@ -102,4 +108,14 @@ public ChessPosition readChessPosition(Scanner scanner) { return new ChessPosition(column, row); } + + public ChessPiece.Name readPromotedPiece(Scanner scanner) { + String input = readInput(scanner).substring(0, 1); + + return ChessMatch.possiblePromotedPieces + .stream() + .filter(pieceName -> pieceName.getLetter().equalsIgnoreCase(input)) + .findFirst() + .orElse(null); + } } diff --git a/src/main/java/com/rogeriofrsouza/app/boardgame/Piece.java b/src/main/java/com/rogeriofrsouza/app/boardgame/Piece.java index 9e4a6d9..5d20b06 100644 --- a/src/main/java/com/rogeriofrsouza/app/boardgame/Piece.java +++ b/src/main/java/com/rogeriofrsouza/app/boardgame/Piece.java @@ -1,45 +1,31 @@ package com.rogeriofrsouza.app.boardgame; import lombok.EqualsAndHashCode; +import lombok.Getter; +@Getter @EqualsAndHashCode public abstract class Piece { - // Não é ainda a posição do xadrez, é uma posição simples de matriz. Não deve ser visível na - // camada de xadrez protected Position position; + private final Board board; - private Board board; - - // A posição de uma peça recém criada será nula, pois ainda não foi colocada no tabuleiro - public Piece(Board board) { + protected Piece(Board board) { this.board = board; - // position = null; - } - - // Somente classes do mesmo pacote e subclasses podem acessar o Board - protected Board getBoard() { - return board; } - // Não permitir que o Board seja alterado. Remover o setBoard() - - public abstract boolean[][] possibleMoves(); + public abstract boolean[][] computePossibleMoves(); - /* - * Hook method: método que faz um gancho com a subclasse. - * Chama uma possível implementação de alguma subclasse concreta da classe Piece - */ - public boolean possibleMove(Position position) { - return possibleMoves()[position.getRow()][position.getColumn()]; + public boolean isTargetPossibleMove(Position target) { + return computePossibleMoves()[target.getRow()][target.getColumn()]; } public boolean isThereAnyPossibleMove() { - boolean[][] mat = possibleMoves(); + boolean[][] possibleMoves = computePossibleMoves(); - for (int i = 0; i < mat.length; i++) { - for (int j = 0; j < mat.length; j++) { - if (mat[i][j]) { + for (boolean[] row : possibleMoves) { + for (boolean move : row) { + if (move) { return true; } } diff --git a/src/main/java/com/rogeriofrsouza/app/chess/ChessMatch.java b/src/main/java/com/rogeriofrsouza/app/chess/ChessMatch.java index 1c1de6f..d915a8f 100644 --- a/src/main/java/com/rogeriofrsouza/app/chess/ChessMatch.java +++ b/src/main/java/com/rogeriofrsouza/app/chess/ChessMatch.java @@ -1,5 +1,9 @@ package com.rogeriofrsouza.app.chess; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + import com.rogeriofrsouza.app.boardgame.Board; import com.rogeriofrsouza.app.boardgame.Piece; import com.rogeriofrsouza.app.boardgame.Position; @@ -13,16 +17,12 @@ import lombok.Getter; import lombok.Setter; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - @Getter @Setter public class ChessMatch { private int turn; - private Color currentPlayer; + private ChessPiece.Color currentPlayer; private boolean check; private boolean checkMate; private ChessPiece enPassantVulnerable; @@ -33,20 +33,25 @@ public class ChessMatch { private List piecesOnTheBoard = new ArrayList<>(); private List capturedPieces = new ArrayList<>(); + public static final List possiblePromotedPieces = + List.of( + ChessPiece.Name.BISHOP, ChessPiece.Name.KNIGHT, + ChessPiece.Name.ROOK, ChessPiece.Name.QUEEN); + public ChessMatch() { board = new Board(8, 8); turn = 1; - currentPlayer = Color.WHITE; + currentPlayer = ChessPiece.Color.WHITE; initialSetup(); } private void initialSetup() { - Color color = Color.BLACK; + ChessPiece.Color color = ChessPiece.Color.BLACK; for (int row : new int[] {8, 7, 2, 1}) { if (row <= 2) { - color = Color.WHITE; + color = ChessPiece.Color.WHITE; } for (char column = 'a'; column < 'i'; column++) { @@ -61,7 +66,7 @@ private void initialSetup() { } } - private ChessPiece switchPiece(char column, Board board, Color color) { + private ChessPiece switchPiece(char column, Board board, ChessPiece.Color color) { return switch (column) { case 'a', 'h' -> new Rook(board, color); case 'b', 'g' -> new Knight(board, color); @@ -91,7 +96,7 @@ public boolean[][] computePossibleMoves(ChessPosition sourcePosition) { Position position = sourcePosition.toPosition(); validateSourcePosition(position); - return board.piece(position).possibleMoves(); + return board.piece(position).computePossibleMoves(); } public ChessPiece performChessMove(ChessPosition sourcePosition, ChessPosition targetPosition) { @@ -123,8 +128,10 @@ public ChessPiece performChessMove(ChessPosition sourcePosition, ChessPosition t if (movedPiece instanceof Pawn) { // Special move: Promotion - if (movedPiece.getColor() == Color.WHITE && target.getRow() == 0 - || movedPiece.getColor() == Color.BLACK && target.getRow() == 7) { + if (movedPiece.getColor() == ChessPiece.Color.WHITE + && target.getRow() == 0 + || movedPiece.getColor() == ChessPiece.Color.BLACK + && target.getRow() == 7) { promoted = movedPiece; promoted = replacePromotedPiece("Q"); } @@ -153,7 +160,7 @@ private void validateSourcePosition(Position position) { } private void validateTargetPosition(Position source, Position target) { - if (!board.piece(source).possibleMove(target)) { + if (!board.piece(source).isTargetPossibleMove(target)) { throw new ChessException("The chosen piece can't move to target position"); } } @@ -195,7 +202,7 @@ private Piece makeMove(Position source, Position target) { && source.getColumn() != target.getColumn() && capturedPiece == null) { int targetRow = - movingPiece.getColor() == Color.WHITE + movingPiece.getColor() == ChessPiece.Color.WHITE ? target.getRow() + 1 : target.getRow() - 1; @@ -247,7 +254,7 @@ private void undoMove(Position source, Position target, Piece capturedPiece) { && capturedPiece == enPassantVulnerable) { ChessPiece pawn = (ChessPiece) board.removePiece(target); - int targetRow = movingPiece.getColor() == Color.WHITE ? 3 : 4; + int targetRow = movingPiece.getColor() == ChessPiece.Color.WHITE ? 3 : 4; Position pawnPosition = new Position(targetRow, target.getColumn()); board.placePiece(pawn, pawnPosition); @@ -259,34 +266,35 @@ private void nextTurn() { currentPlayer = getOpponentPlayer(currentPlayer); } - private boolean testCheck(Color color) { + private boolean testCheck(ChessPiece.Color color) { Position kingPosition = searchKing(color).getChessPosition().toPosition(); - Color opponentPlayer = getOpponentPlayer(color); + ChessPiece.Color opponentPlayer = getOpponentPlayer(color); return piecesOnTheBoard.stream() .filter(piece -> ((ChessPiece) piece).getColor() == opponentPlayer) .anyMatch(piece -> { - boolean[][] possibleMoves = piece.possibleMoves(); + boolean[][] possibleMoves = piece.computePossibleMoves(); return possibleMoves[kingPosition.getRow()][kingPosition.getColumn()]; }); } - private ChessPiece searchKing(Color color) { + private ChessPiece searchKing(ChessPiece.Color color) { return piecesOnTheBoard.stream() - .filter(piece -> piece instanceof King && ((ChessPiece) piece).getColor() == color) + .filter(piece -> piece instanceof King + && ((ChessPiece) piece).getColor() == color) .findFirst() .map(ChessPiece.class::cast) .orElseThrow(() -> new IllegalStateException( "There is no " + color + " king on the board")); } - private Color getOpponentPlayer(Color color) { - return color == Color.WHITE - ? Color.BLACK - : Color.WHITE; + private ChessPiece.Color getOpponentPlayer(ChessPiece.Color color) { + return color == ChessPiece.Color.WHITE + ? ChessPiece.Color.BLACK + : ChessPiece.Color.WHITE; } - private boolean testCheckMate(Color color) { + private boolean testCheckMate(ChessPiece.Color color) { if (!testCheck(color)) { return false; } @@ -297,7 +305,7 @@ private boolean testCheckMate(Color color) { .collect(Collectors.toList()); for (Piece piece : piecesFiltered) { - boolean[][] possibleMoves = piece.possibleMoves(); + boolean[][] possibleMoves = piece.computePossibleMoves(); for (int i = 0; i < board.getRows(); i++) { for (int j = 0; j < board.getColumns(); j++) { @@ -320,6 +328,10 @@ private boolean testCheckMate(Color color) { return true; } + public ChessPiece replacePromotedPiece(ChessPiece.Name pieceName) { + return replacePromotedPiece(pieceName.getLetter()); + } + public ChessPiece replacePromotedPiece(String type) { if (promoted == null) { throw new IllegalStateException("There is no piece to be promoted"); diff --git a/src/main/java/com/rogeriofrsouza/app/chess/ChessMoveDirection.java b/src/main/java/com/rogeriofrsouza/app/chess/ChessMoveDirection.java new file mode 100644 index 0000000..18e2e16 --- /dev/null +++ b/src/main/java/com/rogeriofrsouza/app/chess/ChessMoveDirection.java @@ -0,0 +1,12 @@ +package com.rogeriofrsouza.app.chess; + +public enum ChessMoveDirection { + UP, + DOWN, + LEFT, + RIGHT, + UP_LEFT, + UP_RIGHT, + DOWN_LEFT, + DOWN_RIGHT +} diff --git a/src/main/java/com/rogeriofrsouza/app/chess/ChessPiece.java b/src/main/java/com/rogeriofrsouza/app/chess/ChessPiece.java index 75c11cf..5de512c 100644 --- a/src/main/java/com/rogeriofrsouza/app/chess/ChessPiece.java +++ b/src/main/java/com/rogeriofrsouza/app/chess/ChessPiece.java @@ -3,38 +3,44 @@ import com.rogeriofrsouza.app.boardgame.Board; import com.rogeriofrsouza.app.boardgame.Piece; import com.rogeriofrsouza.app.boardgame.Position; - +import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; +import lombok.Getter; + +import java.util.List; +import java.util.Optional; +@Getter @EqualsAndHashCode(callSuper = true) public abstract class ChessPiece extends Piece { - private Color color; + private final Name name; + private final Color color; private int moveCount; + private List chessMoveDirections; - public ChessPiece(Board board, Color color) { + protected ChessPiece(Board board, Color color) { super(board); + this.name = null; this.color = color; } - public Color getColor() { - return color; - } - - public int getMoveCount() { - return moveCount; + protected ChessPiece( + Board board, Color color, Name name, List chessMoveDirections) { + super(board); + this.color = color; + this.name = name; + this.chessMoveDirections = chessMoveDirections; } - // Não permitir que a cor de uma peça seja modificada. Remover o setColor() - public ChessPosition getChessPosition() { return ChessPosition.fromPosition(position); } protected boolean isThereOpponentPiece(Position position) { - ChessPiece p = (ChessPiece) getBoard().piece(position); // Downcasting + ChessPiece piece = (ChessPiece) getBoard().piece(position); - return p != null && p.getColor() != color; + return piece != null && piece.getColor() != color; } protected void increaseMoveCount() { @@ -44,4 +50,78 @@ protected void increaseMoveCount() { protected void decreaseMoveCount() { moveCount--; } + + @Override + public String toString() { + return getName().getLetter(); + } + + @Override + public boolean[][] computePossibleMoves() { + boolean[][] possibleMoves = new boolean[getBoard().getRows()][getBoard().getColumns()]; + + Optional.ofNullable(getChessMoveDirections()) + .filter(directions -> !directions.isEmpty()) + .ifPresent(directions -> directions.forEach( + direction -> checkMoves(possibleMoves, direction))); + + return possibleMoves; + } + + protected void checkMoves(boolean[][] possibleMoves, ChessMoveDirection direction) { + Position targetPosition = new Position(position.getRow(), position.getColumn()); + + while (true) { + changeTargetPosition(targetPosition, direction); + + if (!getBoard().positionExists(targetPosition)) { + return; + } + + if (getBoard().thereIsAPiece(targetPosition)) { + possibleMoves[targetPosition.getRow()][targetPosition.getColumn()] = + isThereOpponentPiece(targetPosition); + return; + } + + possibleMoves[targetPosition.getRow()][targetPosition.getColumn()] = true; + } + } + + private void changeTargetPosition(Position targetPosition, ChessMoveDirection direction) { + switch (direction) { + case UP -> targetPosition.setRow(targetPosition.getRow() - 1); + case DOWN -> targetPosition.setRow(targetPosition.getRow() + 1); + case LEFT -> targetPosition.setColumn(targetPosition.getColumn() - 1); + case RIGHT -> targetPosition.setColumn(targetPosition.getColumn() + 1); + case UP_LEFT -> targetPosition.setValues( + targetPosition.getRow() - 1, targetPosition.getColumn() - 1); + case UP_RIGHT -> targetPosition.setValues( + targetPosition.getRow() - 1, targetPosition.getColumn() + 1); + case DOWN_LEFT -> targetPosition.setValues( + targetPosition.getRow() + 1, targetPosition.getColumn() - 1); + case DOWN_RIGHT -> targetPosition.setValues( + targetPosition.getRow() + 1, targetPosition.getColumn() + 1); + default -> throw new IllegalArgumentException("Invalid direction"); + } + } + + @AllArgsConstructor + @Getter + public enum Name { + + ROOK("R"), + KNIGHT("N"), + BISHOP("B"), + QUEEN("Q"), + KING("K"), + PAWN("P"); + + private final String letter; + } + + public enum Color { + BLACK, + WHITE + } } diff --git a/src/main/java/com/rogeriofrsouza/app/chess/ChessPosition.java b/src/main/java/com/rogeriofrsouza/app/chess/ChessPosition.java index f654e60..b7a20c8 100644 --- a/src/main/java/com/rogeriofrsouza/app/chess/ChessPosition.java +++ b/src/main/java/com/rogeriofrsouza/app/chess/ChessPosition.java @@ -27,7 +27,7 @@ public int getRow() { // Não permitir que a coluna e a linha sejam livremente alteradas - protected Position toPosition() { + public Position toPosition() { return new Position(8 - row, column - 'a'); } diff --git a/src/main/java/com/rogeriofrsouza/app/chess/Color.java b/src/main/java/com/rogeriofrsouza/app/chess/Color.java deleted file mode 100644 index 7c352e2..0000000 --- a/src/main/java/com/rogeriofrsouza/app/chess/Color.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.rogeriofrsouza.app.chess; - -public enum Color { - BLACK, - WHITE; -} diff --git a/src/main/java/com/rogeriofrsouza/app/chess/pieces/Bishop.java b/src/main/java/com/rogeriofrsouza/app/chess/pieces/Bishop.java index 8238c04..9bd0da0 100644 --- a/src/main/java/com/rogeriofrsouza/app/chess/pieces/Bishop.java +++ b/src/main/java/com/rogeriofrsouza/app/chess/pieces/Bishop.java @@ -1,75 +1,18 @@ package com.rogeriofrsouza.app.chess.pieces; import com.rogeriofrsouza.app.boardgame.Board; -import com.rogeriofrsouza.app.boardgame.Position; +import com.rogeriofrsouza.app.chess.ChessMoveDirection; import com.rogeriofrsouza.app.chess.ChessPiece; -import com.rogeriofrsouza.app.chess.Color; -public class Bishop extends ChessPiece { - - public Bishop(Board board, Color color) { - super(board, color); - } - - @Override - public String toString() { - return "B"; - } - - @Override - public boolean[][] possibleMoves() { - boolean[][] mat = new boolean[getBoard().getRows()][getBoard().getColumns()]; - - Position p = new Position(0, 0); - - // north-west - p.setValues(position.getRow() - 1, position.getColumn() - 1); - - while (getBoard().positionExists(p) && !getBoard().thereIsAPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - p.setValues(p.getRow() - 1, p.getColumn() - 1); - } +import java.util.List; - if (getBoard().positionExists(p) && isThereOpponentPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - } - - // north-east - p.setValues(position.getRow() - 1, position.getColumn() + 1); - - while (getBoard().positionExists(p) && !getBoard().thereIsAPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - p.setValues(p.getRow() - 1, p.getColumn() + 1); - } - - if (getBoard().positionExists(p) && isThereOpponentPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - } - - // south-east - p.setValues(position.getRow() + 1, position.getColumn() + 1); - - while (getBoard().positionExists(p) && !getBoard().thereIsAPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - p.setValues(p.getRow() + 1, p.getColumn() + 1); - } - - if (getBoard().positionExists(p) && isThereOpponentPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - } - - // south-west - p.setValues(position.getRow() + 1, position.getColumn() - 1); - - while (getBoard().positionExists(p) && !getBoard().thereIsAPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - p.setValues(p.getRow() + 1, p.getColumn() - 1); - } +public class Bishop extends ChessPiece { - if (getBoard().positionExists(p) && isThereOpponentPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - } + private static final List CHESS_MOVE_DIRECTIONS = List.of( + ChessMoveDirection.UP_LEFT, ChessMoveDirection.UP_RIGHT, + ChessMoveDirection.DOWN_LEFT, ChessMoveDirection.DOWN_RIGHT); - return mat; + public Bishop(Board board, Color color) { + super(board, color, Name.BISHOP, CHESS_MOVE_DIRECTIONS); } } diff --git a/src/main/java/com/rogeriofrsouza/app/chess/pieces/King.java b/src/main/java/com/rogeriofrsouza/app/chess/pieces/King.java index d3d1ce5..76fafbf 100644 --- a/src/main/java/com/rogeriofrsouza/app/chess/pieces/King.java +++ b/src/main/java/com/rogeriofrsouza/app/chess/pieces/King.java @@ -4,7 +4,6 @@ import com.rogeriofrsouza.app.boardgame.Position; import com.rogeriofrsouza.app.chess.ChessMatch; import com.rogeriofrsouza.app.chess.ChessPiece; -import com.rogeriofrsouza.app.chess.Color; public class King extends ChessPiece { @@ -21,7 +20,7 @@ public String toString() { } @Override - public boolean[][] possibleMoves() { + public boolean[][] computePossibleMoves() { boolean[][] mat = new boolean[getBoard().getRows()][getBoard().getColumns()]; Position p = new Position(0, 0); diff --git a/src/main/java/com/rogeriofrsouza/app/chess/pieces/Knight.java b/src/main/java/com/rogeriofrsouza/app/chess/pieces/Knight.java index fb66d57..68a7c01 100644 --- a/src/main/java/com/rogeriofrsouza/app/chess/pieces/Knight.java +++ b/src/main/java/com/rogeriofrsouza/app/chess/pieces/Knight.java @@ -3,7 +3,6 @@ import com.rogeriofrsouza.app.boardgame.Board; import com.rogeriofrsouza.app.boardgame.Position; import com.rogeriofrsouza.app.chess.ChessPiece; -import com.rogeriofrsouza.app.chess.Color; public class Knight extends ChessPiece { @@ -17,7 +16,7 @@ public String toString() { } @Override - public boolean[][] possibleMoves() { + public boolean[][] computePossibleMoves() { boolean[][] mat = new boolean[getBoard().getRows()][getBoard().getColumns()]; Position p = new Position(0, 0); diff --git a/src/main/java/com/rogeriofrsouza/app/chess/pieces/Pawn.java b/src/main/java/com/rogeriofrsouza/app/chess/pieces/Pawn.java index 399ab66..fcd7a72 100644 --- a/src/main/java/com/rogeriofrsouza/app/chess/pieces/Pawn.java +++ b/src/main/java/com/rogeriofrsouza/app/chess/pieces/Pawn.java @@ -4,7 +4,6 @@ import com.rogeriofrsouza.app.boardgame.Position; import com.rogeriofrsouza.app.chess.ChessMatch; import com.rogeriofrsouza.app.chess.ChessPiece; -import com.rogeriofrsouza.app.chess.Color; public class Pawn extends ChessPiece { @@ -21,7 +20,7 @@ public String toString() { } @Override - public boolean[][] possibleMoves() { + public boolean[][] computePossibleMoves() { boolean[][] mat = new boolean[getBoard().getRows()][getBoard().getColumns()]; Position p = new Position(0, 0); diff --git a/src/main/java/com/rogeriofrsouza/app/chess/pieces/Queen.java b/src/main/java/com/rogeriofrsouza/app/chess/pieces/Queen.java index 80ed57b..fbbdd01 100644 --- a/src/main/java/com/rogeriofrsouza/app/chess/pieces/Queen.java +++ b/src/main/java/com/rogeriofrsouza/app/chess/pieces/Queen.java @@ -1,123 +1,20 @@ package com.rogeriofrsouza.app.chess.pieces; import com.rogeriofrsouza.app.boardgame.Board; -import com.rogeriofrsouza.app.boardgame.Position; +import com.rogeriofrsouza.app.chess.ChessMoveDirection; import com.rogeriofrsouza.app.chess.ChessPiece; -import com.rogeriofrsouza.app.chess.Color; -public class Queen extends ChessPiece { - - public Queen(Board board, Color color) { - super(board, color); - } - - @Override - public String toString() { - return "Q"; - } - - @Override - public boolean[][] possibleMoves() { - boolean[][] mat = new boolean[getBoard().getRows()][getBoard().getColumns()]; - - Position p = new Position(0, 0); - - // above - p.setValues(position.getRow() - 1, position.getColumn()); - - while (getBoard().positionExists(p) && !getBoard().thereIsAPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - p.setRow(p.getRow() - 1); - } - - if (getBoard().positionExists(p) && isThereOpponentPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - } - - // left - p.setValues(position.getRow(), position.getColumn() - 1); - - while (getBoard().positionExists(p) && !getBoard().thereIsAPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - p.setColumn(p.getColumn() - 1); - } - - if (getBoard().positionExists(p) && isThereOpponentPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - } - - // right - p.setValues(position.getRow(), position.getColumn() + 1); - - while (getBoard().positionExists(p) && !getBoard().thereIsAPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - p.setColumn(p.getColumn() + 1); - } +import java.util.List; - if (getBoard().positionExists(p) && isThereOpponentPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - } - - // below - p.setValues(position.getRow() + 1, position.getColumn()); - - while (getBoard().positionExists(p) && !getBoard().thereIsAPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - p.setRow(p.getRow() + 1); - } - - if (getBoard().positionExists(p) && isThereOpponentPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - } - - // north-west - p.setValues(position.getRow() - 1, position.getColumn() - 1); - - while (getBoard().positionExists(p) && !getBoard().thereIsAPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - p.setValues(p.getRow() - 1, p.getColumn() - 1); - } - - if (getBoard().positionExists(p) && isThereOpponentPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - } - - // north-east - p.setValues(position.getRow() - 1, position.getColumn() + 1); - - while (getBoard().positionExists(p) && !getBoard().thereIsAPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - p.setValues(p.getRow() - 1, p.getColumn() + 1); - } - - if (getBoard().positionExists(p) && isThereOpponentPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - } - - // south-east - p.setValues(position.getRow() + 1, position.getColumn() + 1); - - while (getBoard().positionExists(p) && !getBoard().thereIsAPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - p.setValues(p.getRow() + 1, p.getColumn() + 1); - } - - if (getBoard().positionExists(p) && isThereOpponentPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - } - - // south-west - p.setValues(position.getRow() + 1, position.getColumn() - 1); - - while (getBoard().positionExists(p) && !getBoard().thereIsAPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - p.setValues(p.getRow() + 1, p.getColumn() - 1); - } +public class Queen extends ChessPiece { - if (getBoard().positionExists(p) && isThereOpponentPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - } + private static final List CHESS_MOVE_DIRECTIONS = List.of( + ChessMoveDirection.UP, ChessMoveDirection.RIGHT, + ChessMoveDirection.DOWN, ChessMoveDirection.LEFT, + ChessMoveDirection.UP_LEFT, ChessMoveDirection.UP_RIGHT, + ChessMoveDirection.DOWN_RIGHT, ChessMoveDirection.DOWN_LEFT); - return mat; + public Queen(Board board, Color color) { + super(board, color, Name.QUEEN, CHESS_MOVE_DIRECTIONS); } } diff --git a/src/main/java/com/rogeriofrsouza/app/chess/pieces/Rook.java b/src/main/java/com/rogeriofrsouza/app/chess/pieces/Rook.java index 6e5dbe9..1e72411 100644 --- a/src/main/java/com/rogeriofrsouza/app/chess/pieces/Rook.java +++ b/src/main/java/com/rogeriofrsouza/app/chess/pieces/Rook.java @@ -1,76 +1,18 @@ package com.rogeriofrsouza.app.chess.pieces; import com.rogeriofrsouza.app.boardgame.Board; -import com.rogeriofrsouza.app.boardgame.Position; +import com.rogeriofrsouza.app.chess.ChessMoveDirection; import com.rogeriofrsouza.app.chess.ChessPiece; -import com.rogeriofrsouza.app.chess.Color; -// Torre -public class Rook extends ChessPiece { - - public Rook(Board board, Color color) { - super(board, color); - } - - @Override - public String toString() { - return "R"; - } - - @Override - public boolean[][] possibleMoves() { - boolean[][] mat = new boolean[getBoard().getRows()][getBoard().getColumns()]; - - Position p = new Position(0, 0); - - // above - p.setValues(position.getRow() - 1, position.getColumn()); - - while (getBoard().positionExists(p) && !getBoard().thereIsAPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - p.setRow(p.getRow() - 1); - } +import java.util.List; - if (getBoard().positionExists(p) && isThereOpponentPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - } - - // left - p.setValues(position.getRow(), position.getColumn() - 1); - - while (getBoard().positionExists(p) && !getBoard().thereIsAPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - p.setColumn(p.getColumn() - 1); - } - - if (getBoard().positionExists(p) && isThereOpponentPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - } - - // right - p.setValues(position.getRow(), position.getColumn() + 1); - - while (getBoard().positionExists(p) && !getBoard().thereIsAPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - p.setColumn(p.getColumn() + 1); - } - - if (getBoard().positionExists(p) && isThereOpponentPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - } - - // below - p.setValues(position.getRow() + 1, position.getColumn()); - - while (getBoard().positionExists(p) && !getBoard().thereIsAPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - p.setRow(p.getRow() + 1); - } +public class Rook extends ChessPiece { - if (getBoard().positionExists(p) && isThereOpponentPiece(p)) { - mat[p.getRow()][p.getColumn()] = true; - } + private static final List CHESS_MOVE_DIRECTIONS = List.of( + ChessMoveDirection.UP, ChessMoveDirection.RIGHT, + ChessMoveDirection.DOWN, ChessMoveDirection.LEFT); - return mat; + public Rook(Board board, Color color) { + super(board, color, Name.ROOK, CHESS_MOVE_DIRECTIONS); } } diff --git a/src/test/java/com/rogeriofrsouza/app/UITest.java b/src/test/java/com/rogeriofrsouza/app/UITest.java index 7515d2a..334de4a 100644 --- a/src/test/java/com/rogeriofrsouza/app/UITest.java +++ b/src/test/java/com/rogeriofrsouza/app/UITest.java @@ -6,34 +6,37 @@ import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.verify; -import com.rogeriofrsouza.app.boardgame.Board; -import com.rogeriofrsouza.app.chess.ChessMatch; -import com.rogeriofrsouza.app.chess.ChessPiece; -import com.rogeriofrsouza.app.chess.ChessPosition; -import com.rogeriofrsouza.app.chess.Color; -import com.rogeriofrsouza.app.chess.pieces.Rook; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.PrintStream; +import java.util.InputMismatchException; +import java.util.List; +import java.util.Scanner; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.mockito.InjectMocks; import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.io.PrintStream; -import java.util.InputMismatchException; -import java.util.List; -import java.util.Scanner; +import com.rogeriofrsouza.app.boardgame.Board; +import com.rogeriofrsouza.app.chess.ChessMatch; +import com.rogeriofrsouza.app.chess.ChessPiece; +import com.rogeriofrsouza.app.chess.ChessPosition; +import com.rogeriofrsouza.app.chess.pieces.Rook; @ExtendWith(MockitoExtension.class) class UITest { - @InjectMocks @Spy private UI ui; + @InjectMocks + @Spy + private UI ui; private final PrintStream systemOut = System.out; private ByteArrayOutputStream outputStream; @@ -72,32 +75,25 @@ void printMatch_notCheckNotCheckmate_logMatch() { ChessMatch chessMatch = new ChessMatch(); Board board = new Board(8, 8); - List captured = - List.of( - new Rook(board, Color.WHITE), - new Rook(board, Color.WHITE), - new Rook(board, Color.BLACK), - new Rook(board, Color.BLACK)); - - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder - .append( - String.format( - "%nCaptured pieces%nWhite: %s%s%n%sBlack: %s%s%n%s", - UI.ANSI_WHITE, - captured.subList(0, 2), - UI.ANSI_RESET, - UI.ANSI_YELLOW, - captured.subList(2, 4), - UI.ANSI_RESET)) - .append("\nTurn: " + chessMatch.getTurn() + "\n") - .append("Waiting player: " + chessMatch.getCurrentPlayer() + "\n"); + List captured = List.of( + new Rook(board, ChessPiece.Color.WHITE), new Rook(board, ChessPiece.Color.WHITE), + new Rook(board, ChessPiece.Color.BLACK), new Rook(board, ChessPiece.Color.BLACK)); + + String outputExpected = String.format( + "%nCaptured pieces%nWhite: %s%s%n%sBlack: %s%s%n%s", + UI.ANSI_WHITE, + captured.subList(0, 2), + UI.ANSI_RESET, + UI.ANSI_YELLOW, + captured.subList(2, 4), + UI.ANSI_RESET) + + "\nTurn: " + chessMatch.getTurn() + "\n" + + "Waiting player: " + chessMatch.getCurrentPlayer() + "\n"; doNothing().when(ui).printBoard(any(ChessPiece[][].class), any()); - ui.printMatch(chessMatch, captured); - assertEquals(stringBuilder.toString(), outputStream.toString()); + assertEquals(outputExpected, outputStream.toString()); verify(ui).printBoard(any(ChessPiece[][].class), any()); } @@ -107,32 +103,28 @@ void printMatch_isCheck_logMatchAndCheck() { ChessMatch chessMatch = new ChessMatch(); chessMatch.setCheck(true); chessMatch.setTurn(50); - chessMatch.setCurrentPlayer(Color.BLACK); + chessMatch.setCurrentPlayer(ChessPiece.Color.BLACK); Board board = new Board(8, 8); - List captured = - List.of(new Rook(board, Color.WHITE), new Rook(board, Color.WHITE)); - - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder - .append( - String.format( - "%nCaptured pieces%nWhite: %s%s%n%sBlack: %s%s%n%s", - UI.ANSI_WHITE, - captured, - UI.ANSI_RESET, - UI.ANSI_YELLOW, - List.of(), - UI.ANSI_RESET)) - .append("\nTurn: " + chessMatch.getTurn() + "\n") - .append("Waiting player: " + chessMatch.getCurrentPlayer() + "\n") - .append("CHECK!\n"); + List captured = List.of( + new Rook(board, ChessPiece.Color.WHITE), new Rook(board, ChessPiece.Color.WHITE)); + + String outputExpected = String.format( + "%nCaptured pieces%nWhite: %s%s%n%sBlack: %s%s%n%s", + UI.ANSI_WHITE, + captured, + UI.ANSI_RESET, + UI.ANSI_YELLOW, + List.of(), + UI.ANSI_RESET) + + "\nTurn: " + chessMatch.getTurn() + "\n" + + "Waiting player: " + chessMatch.getCurrentPlayer() + "\n" + + "CHECK!\n"; doNothing().when(ui).printBoard(any(ChessPiece[][].class), any()); - ui.printMatch(chessMatch, captured); - assertEquals(stringBuilder.toString(), outputStream.toString()); + assertEquals(outputExpected, outputStream.toString()); verify(ui).printBoard(any(ChessPiece[][].class), any()); } @@ -142,31 +134,27 @@ void printMatch_isCheckMate_logMatchAndCheckMate() { ChessMatch chessMatch = new ChessMatch(); chessMatch.setCheckMate(true); chessMatch.setTurn(10); - chessMatch.setCurrentPlayer(Color.BLACK); + chessMatch.setCurrentPlayer(ChessPiece.Color.BLACK); Board board = new Board(8, 8); - List captured = - List.of(new Rook(board, Color.BLACK), new Rook(board, Color.BLACK)); - - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder - .append( - String.format( - "%nCaptured pieces%nWhite: %s%s%n%sBlack: %s%s%n%s", - UI.ANSI_WHITE, - List.of(), - UI.ANSI_RESET, - UI.ANSI_YELLOW, - captured, - UI.ANSI_RESET)) - .append("\nTurn: " + chessMatch.getTurn() + "\n") - .append("CHECKMATE!\nWinner: " + chessMatch.getCurrentPlayer() + "\n"); + List captured = List.of( + new Rook(board, ChessPiece.Color.BLACK), new Rook(board, ChessPiece.Color.BLACK)); + + String stringBuilder = String.format( + "%nCaptured pieces%nWhite: %s%s%n%sBlack: %s%s%n%s", + UI.ANSI_WHITE, + List.of(), + UI.ANSI_RESET, + UI.ANSI_YELLOW, + captured, + UI.ANSI_RESET) + + "\nTurn: " + chessMatch.getTurn() + "\n" + + "CHECKMATE!\nWinner: " + chessMatch.getCurrentPlayer() + "\n"; doNothing().when(ui).printBoard(any(ChessPiece[][].class), any()); - ui.printMatch(chessMatch, captured); - assertEquals(stringBuilder.toString(), outputStream.toString()); + assertEquals(stringBuilder, outputStream.toString()); verify(ui).printBoard(any(ChessPiece[][].class), any()); } @@ -175,20 +163,16 @@ void printMatch_isCheckMate_logMatchAndCheckMate() { void printBoard_noPossibleMove_printBoardPiecesColors() { Board board = new Board(4, 1); - ChessPiece[][] pieces = - new ChessPiece[][] { - {new Rook(board, Color.BLACK)}, {null}, {null}, {new Rook(board, Color.WHITE)} - }; - - String stringExpected = - String.format( - "8 %sR%s %n7 -%s %n6 -%s %n5 %sR%s %n a b c d e f g h%n", - UI.ANSI_YELLOW, - UI.ANSI_RESET, - UI.ANSI_RESET, - UI.ANSI_RESET, - UI.ANSI_WHITE, - UI.ANSI_RESET); + ChessPiece[][] pieces = new ChessPiece[][]{ + {new Rook(board, ChessPiece.Color.BLACK)}, + {null}, {null}, + {new Rook(board, ChessPiece.Color.WHITE)} + }; + + String stringExpected = String.format( + "8 %sR%s %n7 -%s %n6 -%s %n5 %sR%s %n a b c d e f g h%n", + UI.ANSI_YELLOW, UI.ANSI_RESET, UI.ANSI_RESET, + UI.ANSI_RESET, UI.ANSI_WHITE, UI.ANSI_RESET); ui.printBoard(pieces, null); assertEquals(stringExpected, outputStream.toString()); @@ -199,24 +183,19 @@ void printBoard_noPossibleMove_printBoardPiecesColors() { void printBoard_hasPossibleMoves_printBoardPiecesColorsMoves() { Board board = new Board(4, 1); - ChessPiece[][] pieces = - new ChessPiece[][] { - {new Rook(board, Color.BLACK)}, {null}, {null}, {new Rook(board, Color.WHITE)} - }; - - boolean[][] possibleMoves = new boolean[][] {{true}, {true}, {false}, {false}}; - - String stringExpected = - String.format( - "8 %s%sR%s %n7 %s-%s %n6 -%s %n5 %sR%s %n a b c d e f g h%n", - UI.ANSI_BLUE_BACKGROUND, - UI.ANSI_YELLOW, - UI.ANSI_RESET, - UI.ANSI_BLUE_BACKGROUND, - UI.ANSI_RESET, - UI.ANSI_RESET, - UI.ANSI_WHITE, - UI.ANSI_RESET); + ChessPiece[][] pieces = new ChessPiece[][]{ + {new Rook(board, ChessPiece.Color.BLACK)}, + {null}, {null}, + {new Rook(board, ChessPiece.Color.WHITE)} + }; + + boolean[][] possibleMoves = new boolean[][]{{true}, {true}, {false}, {false}}; + + String stringExpected = String.format( + "8 %s%sR%s %n7 %s-%s %n6 -%s %n5 %sR%s %n a b c d e f g h%n", + UI.ANSI_BLUE_BACKGROUND, UI.ANSI_YELLOW, UI.ANSI_RESET, + UI.ANSI_BLUE_BACKGROUND, UI.ANSI_RESET, UI.ANSI_RESET, + UI.ANSI_WHITE, UI.ANSI_RESET); ui.printBoard(pieces, possibleMoves); assertEquals(stringExpected, outputStream.toString()); @@ -224,7 +203,7 @@ void printBoard_hasPossibleMoves_printBoardPiecesColorsMoves() { @Test @DisplayName( - "should create a ChessPosition object with column and row values provided from input") + "should create a ChessPosition object with column and row values provided from input") void readChessPosition_validInput_createChessPosition() { provideInput("a8"); @@ -235,17 +214,14 @@ void readChessPosition_validInput_createChessPosition() { assertEquals(chessPositionExpected.getColumn(), chessPositionReal.getColumn()); } - @Test + @ParameterizedTest + @ValueSource(strings = {"a9", "i2", "ff", "33"}) @DisplayName("should throw InputMismatchException if input is invalid") - void readChessPosition_invalidInput_throwInputMismatchException() { - List.of("a9", "i2", "ff", "33", " b6") - .forEach( - input -> { - provideInput(input); - - assertThrowsExactly( - InputMismatchException.class, - () -> ui.readChessPosition(new Scanner(System.in))); - }); + void readChessPosition_invalidInput_throwInputMismatchException(String invalidInput) { + provideInput(invalidInput); + + assertThrowsExactly( + InputMismatchException.class, + () -> ui.readChessPosition(new Scanner(System.in))); } } diff --git a/src/test/java/com/rogeriofrsouza/app/chess/ChessMatchTest.java b/src/test/java/com/rogeriofrsouza/app/chess/ChessMatchTest.java index ae0bd8c..91e7e3c 100644 --- a/src/test/java/com/rogeriofrsouza/app/chess/ChessMatchTest.java +++ b/src/test/java/com/rogeriofrsouza/app/chess/ChessMatchTest.java @@ -52,7 +52,7 @@ void chessMatchInitialSetup() { ChessMatch chessMatch = new ChessMatch(); assertEquals(1, chessMatch.getTurn()); - assertEquals(Color.WHITE, chessMatch.getCurrentPlayer()); + assertEquals(ChessPiece.Color.WHITE, chessMatch.getCurrentPlayer()); assertEquals(32, chessMatch.getPiecesOnTheBoard().size()); } @@ -62,7 +62,7 @@ void possibleMoves_validatePosition_returnPossibleMoves() { ChessPosition chessPosition = new ChessPosition('a', 4); Position position = new Position(4, 0); - Rook chessPiece = new Rook(new Board(3, 3), Color.WHITE); + Rook chessPiece = new Rook(new Board(3, 3), ChessPiece.Color.WHITE); boolean[][] possibleMovesExpected = new boolean[][] {{true, true, false}}; doReturn(true).when(boardMock).thereIsAPiece(position); @@ -71,13 +71,13 @@ void possibleMoves_validatePosition_returnPossibleMoves() { .when(boardMock).piece(position); doReturn(true).when(pieceMock).isThereAnyPossibleMove(); - doReturn(possibleMovesExpected).when(pieceMock).possibleMoves(); + doReturn(possibleMovesExpected).when(pieceMock).computePossibleMoves(); assertEquals( possibleMovesExpected, chessMatchMock.computePossibleMoves(chessPosition)); - verify(pieceMock).possibleMoves(); + verify(pieceMock).computePossibleMoves(); } @Test @@ -85,7 +85,7 @@ void possibleMoves_validatePosition_returnPossibleMoves() { void possibleMoves_noPossibleMoves_throwChessException() { ChessPosition chessPosition = new ChessPosition('a', 4); Position position = new Position(4, 0); - Rook chessPiece = new Rook(new Board(3, 3), Color.WHITE); + Rook chessPiece = new Rook(new Board(3, 3), ChessPiece.Color.WHITE); doReturn(true).when(boardMock).thereIsAPiece(position); doReturn(chessPiece).doReturn(pieceMock).when(boardMock).piece(position); @@ -101,7 +101,7 @@ void possibleMoves_noPossibleMoves_throwChessException() { void possibleMoves_chosenPieceNotYours_throwChessException() { ChessPosition chessPosition = new ChessPosition('a', 4); Position position = new Position(4, 0); - Rook chessPiece = new Rook(new Board(3, 3), Color.BLACK); + Rook chessPiece = new Rook(new Board(3, 3), ChessPiece.Color.BLACK); doReturn(true).when(boardMock).thereIsAPiece(position); doReturn(chessPiece).when(boardMock).piece(position); @@ -135,15 +135,15 @@ void replacePromotedPiece_promotedPieceIsValid_returnNewPiece(String type) { ChessPiece newPiece = switch (type) { - case "B" -> new Bishop(boardMock, Color.WHITE); - case "N" -> new Knight(boardMock, Color.WHITE); - case "R" -> new Rook(boardMock, Color.WHITE); - default -> new Queen(boardMock, Color.WHITE); + case "B" -> new Bishop(boardMock, ChessPiece.Color.WHITE); + case "N" -> new Knight(boardMock, ChessPiece.Color.WHITE); + case "R" -> new Rook(boardMock, ChessPiece.Color.WHITE); + default -> new Queen(boardMock, ChessPiece.Color.WHITE); }; when(chessPieceMock.getChessPosition()).thenReturn(chessPosition); when(boardMock.removePiece(promotedPosition)).thenReturn(pieceMock); - when(chessPieceMock.getColor()).thenReturn(Color.WHITE); + when(chessPieceMock.getColor()).thenReturn(ChessPiece.Color.WHITE); doNothing().when(boardMock).placePiece(newPiece, promotedPosition); assertEquals(newPiece, chessMatchMock.replacePromotedPiece(type)); @@ -157,7 +157,7 @@ void replacePromotedPiece_promotedPieceIsValid_returnNewPiece(String type) { @Test @DisplayName("should return the current promoted piece if type isn't valid") void replacePromotedPiece_typeNonValid_returnPromotedPiece() { - Pawn promoted = new Pawn(boardMock, Color.BLACK, chessMatchMock); + Pawn promoted = new Pawn(boardMock, ChessPiece.Color.BLACK, chessMatchMock); chessMatchMock.setPromoted(promoted); assertEquals(promoted, chessMatchMock.replacePromotedPiece("A")); @@ -175,8 +175,10 @@ void replacePromotedPiece_typeNonValid_throwIllegalStateException() { @DisplayName("should return the pieces on the board") void getPieces() { ChessPiece[][] piecesExpected = new ChessPiece[][] { - {new Rook(boardMock, Color.BLACK), new Queen(boardMock, Color.BLACK)}, - {new Rook(boardMock, Color.WHITE), new Queen(boardMock, Color.WHITE)}}; + {new Rook(boardMock, ChessPiece.Color.BLACK), + new Queen(boardMock, ChessPiece.Color.BLACK)}, + {new Rook(boardMock, ChessPiece.Color.WHITE), + new Queen(boardMock, ChessPiece.Color.WHITE)}}; when(boardMock.getRows()).thenReturn(2); when(boardMock.getColumns()).thenReturn(2); diff --git a/src/test/java/com/rogeriofrsouza/app/chess/pieces/BishopTest.java b/src/test/java/com/rogeriofrsouza/app/chess/pieces/BishopTest.java new file mode 100644 index 0000000..2d2dfff --- /dev/null +++ b/src/test/java/com/rogeriofrsouza/app/chess/pieces/BishopTest.java @@ -0,0 +1,44 @@ +package com.rogeriofrsouza.app.chess.pieces; + +import com.rogeriofrsouza.app.boardgame.Board; +import com.rogeriofrsouza.app.chess.ChessPiece; +import com.rogeriofrsouza.app.chess.ChessPosition; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +@ExtendWith(MockitoExtension.class) +class BishopTest { + + @Test + @DisplayName("possible moves for a Bishop given specific board setup") + void computePossibleMoves() { + Board board = new Board(8, 8); + Bishop bishop = new Bishop(board, ChessPiece.Color.WHITE); + Rook rook = new Rook(board, ChessPiece.Color.WHITE); + Knight knight = new Knight(board, ChessPiece.Color.BLACK); + + board.placePiece(bishop, new ChessPosition('b', 2).toPosition()); + board.placePiece(rook, new ChessPosition('a', 1).toPosition()); + board.placePiece(knight, new ChessPosition('f', 6).toPosition()); + + boolean[][] possibleMovesExpected = new boolean[8][8]; + for (boolean[] arr : possibleMovesExpected) { + Arrays.fill(arr, false); + } + + possibleMovesExpected[7][2] = true; + possibleMovesExpected[5][0] = true; + possibleMovesExpected[5][2] = true; + possibleMovesExpected[4][3] = true; + possibleMovesExpected[3][4] = true; + possibleMovesExpected[2][5] = true; + + assertArrayEquals(possibleMovesExpected, bishop.computePossibleMoves()); + } +} diff --git a/src/test/java/com/rogeriofrsouza/app/chess/pieces/RookTest.java b/src/test/java/com/rogeriofrsouza/app/chess/pieces/RookTest.java new file mode 100644 index 0000000..f79a101 --- /dev/null +++ b/src/test/java/com/rogeriofrsouza/app/chess/pieces/RookTest.java @@ -0,0 +1,45 @@ +package com.rogeriofrsouza.app.chess.pieces; + +import com.rogeriofrsouza.app.boardgame.Board; +import com.rogeriofrsouza.app.chess.ChessPiece; +import com.rogeriofrsouza.app.chess.ChessPosition; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +@ExtendWith(MockitoExtension.class) +class RookTest { + + @Test + @DisplayName("possible moves for a Rook given specific board setup") + void computePossibleMoves() { + Board board = new Board(8, 8); + Rook rook = new Rook(board, ChessPiece.Color.WHITE); + Knight knight = new Knight(board, ChessPiece.Color.WHITE); + Bishop bishop = new Bishop(board, ChessPiece.Color.BLACK); + + board.placePiece(rook, new ChessPosition('b', 3).toPosition()); + board.placePiece(knight, new ChessPosition('b', 1).toPosition()); + board.placePiece(bishop, new ChessPosition('b', 7).toPosition()); + + boolean[][] possibleMovesExpected = new boolean[8][8]; + for (boolean[] arr : possibleMovesExpected) { + Arrays.fill(arr, false); + } + + Arrays.fill(possibleMovesExpected[5], true); + possibleMovesExpected[5][1] = false; + possibleMovesExpected[6][1] = true; + possibleMovesExpected[4][1] = true; + possibleMovesExpected[3][1] = true; + possibleMovesExpected[2][1] = true; + possibleMovesExpected[1][1] = true; + + assertArrayEquals(possibleMovesExpected, rook.computePossibleMoves()); + } +}