diff --git a/README.md b/README.md index 8102f91c870..bb80e164182 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,27 @@ # java-chess -체스 미션 저장소 +기능 요구 사항 -## 우아한테크코스 코드리뷰 - -- [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md) +## 기물 이동 +- [x] 비숍 이동 + - [x] 비숍이 이동 가능한 좌표를 찾는다. + - [x] 대각선 방향으로 체스판의 끝까지 선택해 이동할 수 있어야 한다. +- [x] 킹 이동 + - [x] 킹이 이동 가능한 좌표를 찾는다. + - [x] 상, 하, 좌, 우, 대각 한 칸씩만 이동할 수 있어야 한다. +- [x] 나이트 이동 + - [x] 나이트가 이동 가능한 좌표를 찾는다. + - [x] 상 + 대각 우측/ 상 + 대각 좌측/ 하 + 대각 우측/ 하 + 대각 좌측으로 이동할 수 있어야 한다. + - [x] 나이트는 다른 기물을 뛰어넘을 수 있어야 한다. +- [ ] 폰 이동 + - [ ] 폰이 이동 가능한 좌표를 찾는다. + - [ ] 폰의 기본적인 움직임은 앞으로 한 칸 전진이다. + - [ ] 최초로 움직일 때에 한해 2칸 전진이 가능하다. + - [ ] 뒤로 갈 수 없다. + - [ ] 상대편의 기물을 잡으려고 할 때, 폰의 진행방향의 대각 방향에 있어야 한다. +- [x] 퀸 이동 + - [x] 퀸이 이동 가능한 좌표를 찾는다. + - [x] 상, 하, 좌, 우 + 대각 방향으로 체스판의 끝까지 선택해 이동할 수 있어야 한다. +- [x] 룩 이동 + - [x] 룩이 이동 가능한 좌표를 찾는다. + - [x] 현재 Position으로 부터 상, 하, 좌, 우 체스판의 끝까지 선택해 이동할 수 있어야 한다. \ No newline at end of file diff --git a/build.gradle b/build.gradle index 3697236c6fb..ce846f70cc6 100644 --- a/build.gradle +++ b/build.gradle @@ -9,15 +9,15 @@ repositories { } dependencies { - testImplementation platform('org.junit:junit-bom:5.9.1') - testImplementation platform('org.assertj:assertj-bom:3.25.1') + testImplementation platform('org.junit:junit-bom:5.11.4') + testImplementation platform('org.assertj:assertj-bom:3.27.3') testImplementation('org.junit.jupiter:junit-jupiter') testImplementation('org.assertj:assertj-core') } java { toolchain { - languageVersion = JavaLanguageVersion.of(17) + languageVersion = JavaLanguageVersion.of(21) } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7f93135c49b..e6441136f3d 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 80187ac3043..b82aa23a4f0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew.bat b/gradlew.bat index 6689b85beec..7101f8e4676 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/src/main/java/.gitkeep b/src/main/java/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 00000000000..b6b40f52dd9 --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,52 @@ +import chess.Board; +import chess.BoardCreator; +import chess.Column; +import chess.Position; +import chess.Row; +import chess.piece.Piece; +import java.util.Map; +import java.util.Optional; +import java.util.Scanner; + +public class Application { + + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + Map generatePieces = BoardCreator.generate(); + Board board = new Board(generatePieces); + + while (true) { + for (Row row : Row.values()) { + for (Column column : Column.values()) { + Optional piece = board.getPieceOfOptional(column, row); + if (piece.isEmpty()) { + System.out.print("-"); + } else { + System.out.print(piece.get()); + } + + } + System.out.println(); + } + + System.out.println("출발 좌표를 입력해주세요. ex) 1,2"); + String userInputOfDeparture = sc.nextLine(); + String[] split1 = userInputOfDeparture.split(","); + Column column1 = Column.isSameName(split1[0]); + Row row1 = Row.isSameName(split1[1]); + + Position departure = new Position(column1, row1); + Piece piece = board.getPiece(departure); + + System.out.println("%s를 선택하셨습니다. 도착 좌표를 입력해주세요".formatted(piece)); + + String userInputOfArrival = sc.nextLine(); + String[] split2 = userInputOfArrival.split(","); + Column column2 = Column.isSameName(split2[0]); + Row row2 = Row.isSameName(split2[1]); + Position arrival = new Position(column2, row2); + + board.move(departure, arrival); + } + } +} diff --git a/src/main/java/chess/Board.java b/src/main/java/chess/Board.java new file mode 100644 index 00000000000..116914427f3 --- /dev/null +++ b/src/main/java/chess/Board.java @@ -0,0 +1,56 @@ +package chess; + +import chess.piece.Knight; +import chess.piece.Piece; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class Board { + + private final Map pieces; + + public Board(Map pieces) { + this.pieces = pieces; + } + + public void move(Position departure, Position arrival) { + Piece piece = pieces.get(departure); + + List canMovePositions = piece.calculateCanMovePosition(departure, arrival); + + if (!piece.isSameType(new Knight(Color.WHITE))) { + Optional isAlreadyExistAnotherPiece = canMovePositions.stream() + .filter(position -> !position.equals(arrival)) // 도착지 탐색 제외 + .filter(position -> pieces.get(position) != null) + .findAny(); + if (isAlreadyExistAnotherPiece.isPresent()) { + throw new IllegalArgumentException("해당 위치로는 이동할 수 없습니다."); + } + } + // 해당 위치에 아무것도 존재하지 않는다면 이동한다 + if (pieces.get(arrival) == null) { + pieces.put(arrival, piece); + pieces.remove(departure); + return; + } + Piece currentPieceOfArrivalPosition = pieces.get(arrival); + + // 같은 팀 일 경우 해당 위치로 이동할 수 없다. + if (piece.getColor() == currentPieceOfArrivalPosition.getColor()) { + throw new IllegalArgumentException("해당 위치로는 이동할 수 없습니다."); + } + // 해당 위치의 기물을 제거 후 이동한다. + pieces.remove(arrival); + pieces.put(arrival, piece); + pieces.remove(departure); + } + + public Optional getPieceOfOptional(Column column, Row row) { + return Optional.ofNullable(pieces.get(new Position(column, row))); + } + + public Piece getPiece(Position position) { + return pieces.get(position); + } +} diff --git a/src/main/java/chess/BoardCreator.java b/src/main/java/chess/BoardCreator.java new file mode 100644 index 00000000000..96dedcdd18b --- /dev/null +++ b/src/main/java/chess/BoardCreator.java @@ -0,0 +1,69 @@ +package chess; + +import chess.piece.Bishop; +import chess.piece.King; +import chess.piece.Knight; +import chess.piece.Pawn; +import chess.piece.Piece; +import chess.piece.Queen; +import chess.piece.Rook; +import java.util.HashMap; +import java.util.Map; + +public class BoardCreator { + + private BoardCreator() {} + + public static Map generate() { + Map tmpPieces = new HashMap<>(); + tmpPieces.put(new Position(Column.A, Row.ONE), new Rook(Color.WHITE)); + tmpPieces.put(new Position(Column.H, Row.ONE), new Rook(Color.WHITE)); + + tmpPieces.put(new Position(Column.B, Row.ONE), new Knight(Color.WHITE)); + tmpPieces.put(new Position(Column.G, Row.ONE), new Knight(Color.WHITE)); + + tmpPieces.put(new Position(Column.C, Row.ONE), new Bishop(Color.WHITE)); + tmpPieces.put(new Position(Column.F, Row.ONE), new Bishop(Color.WHITE)); + + tmpPieces.put(new Position(Column.D, Row.ONE), new Queen(Color.WHITE)); + + tmpPieces.put(new Position(Column.E, Row.ONE), new King(Color.WHITE)); + + + tmpPieces.put(new Position(Column.A, Row.TWO), new Pawn(Color.WHITE)); + + tmpPieces.put(new Position(Column.A, Row.TWO), new Pawn(Color.WHITE)); + tmpPieces.put(new Position(Column.B, Row.TWO), new Pawn(Color.WHITE)); + tmpPieces.put(new Position(Column.C, Row.TWO), new Pawn(Color.WHITE)); + tmpPieces.put(new Position(Column.D, Row.TWO), new Pawn(Color.WHITE)); + tmpPieces.put(new Position(Column.E, Row.TWO), new Pawn(Color.WHITE)); + tmpPieces.put(new Position(Column.F, Row.TWO), new Pawn(Color.WHITE)); + tmpPieces.put(new Position(Column.G, Row.TWO), new Pawn(Color.WHITE)); + tmpPieces.put(new Position(Column.H, Row.TWO), new Pawn(Color.WHITE)); + + // black + tmpPieces.put(new Position(Column.A, Row.EIGHT), new Rook(Color.BLACK)); + tmpPieces.put(new Position(Column.H, Row.EIGHT), new Rook(Color.BLACK)); + + tmpPieces.put(new Position(Column.B, Row.EIGHT), new Knight(Color.BLACK)); + tmpPieces.put(new Position(Column.G, Row.EIGHT), new Knight(Color.BLACK)); + + tmpPieces.put(new Position(Column.C, Row.EIGHT), new Bishop(Color.BLACK)); + tmpPieces.put(new Position(Column.F, Row.EIGHT), new Bishop(Color.BLACK)); + + tmpPieces.put(new Position(Column.D, Row.EIGHT), new Queen(Color.BLACK)); + + tmpPieces.put(new Position(Column.E, Row.EIGHT), new King(Color.BLACK)); + + tmpPieces.put(new Position(Column.A, Row.SEVEN), new Pawn(Color.BLACK)); + tmpPieces.put(new Position(Column.B, Row.SEVEN), new Pawn(Color.BLACK)); + tmpPieces.put(new Position(Column.C, Row.SEVEN), new Pawn(Color.BLACK)); + tmpPieces.put(new Position(Column.D, Row.SEVEN), new Pawn(Color.BLACK)); + tmpPieces.put(new Position(Column.E, Row.SEVEN), new Pawn(Color.BLACK)); + tmpPieces.put(new Position(Column.F, Row.SEVEN), new Pawn(Color.BLACK)); + tmpPieces.put(new Position(Column.G, Row.SEVEN), new Pawn(Color.BLACK)); + tmpPieces.put(new Position(Column.H, Row.SEVEN), new Pawn(Color.BLACK)); + return tmpPieces; + } + +} diff --git a/src/main/java/chess/Color.java b/src/main/java/chess/Color.java new file mode 100644 index 00000000000..55cd020b681 --- /dev/null +++ b/src/main/java/chess/Color.java @@ -0,0 +1,28 @@ +package chess; + +public enum Color { + + BLACK, + WHITE, + EMPTY; + + public boolean isWhite() { + return this == WHITE; + } + + public boolean isBlack() { + return this == BLACK; + } + + public boolean isEmpty() { + return this == EMPTY; + } + + public Color opposite() { + return switch (this) { + case BLACK -> WHITE; + case WHITE -> BLACK; + default -> EMPTY; + }; + } +} diff --git a/src/main/java/chess/Column.java b/src/main/java/chess/Column.java new file mode 100644 index 00000000000..42ef04ca5b2 --- /dev/null +++ b/src/main/java/chess/Column.java @@ -0,0 +1,72 @@ +package chess; + +import java.util.Arrays; + +public enum Column { + + A("A"), + B("B"), + C("C"), + D("D"), + E("E"), + F("F"), + G("G"), + H("H"); + + private final String name; + + Column(String name) { + this.name = name; + } + + public boolean isFarLeft() { + return ordinal() == 0; + } + + public boolean isFarRight() { + return ordinal() + 1 == values().length; + } + + public boolean canMoveLeft(final int step) { + return ordinal() - step >= 0; + } + + public Column moveLeft() { + return moveLeft(1); + } + + public Column moveLeft(final int step) { + if (canMoveLeft(step)) { + return values()[ordinal() - step]; + } + + throw new IllegalStateException("움직일 수 없는 위치입니다."); + } + + public boolean canMoveRight(final int step) { + return ordinal() + step < values().length; + } + + public Column moveRight() { + return moveRight(1); + } + + public Column moveRight(final int step) { + if (canMoveRight(step)) { + return values()[ordinal() + step]; + } + + throw new IllegalStateException("움직일 수 없는 위치입니다."); + } + + public static Column isSameName(String name) { + return Arrays.stream(Column.values()) + .filter(column -> column.getName().equals(name)) + .findAny() + .orElseThrow(() -> new IllegalArgumentException("없음 그딴거")); + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/chess/Movement.java b/src/main/java/chess/Movement.java new file mode 100644 index 00000000000..e57c6e91bb9 --- /dev/null +++ b/src/main/java/chess/Movement.java @@ -0,0 +1,48 @@ +package chess; + +public enum Movement { + UP(0, 1), + UP_UP(UP.x * 2, UP.y * 2), + DOWN(0, -1), + DOWN_DOWN(DOWN.x * 2, DOWN.y * 2), + LEFT(-1, 0), + RIGHT(1, 0), + LEFT_UP(LEFT.x, UP.y), + RIGHT_UP(RIGHT.x, UP.y), + LEFT_DOWN(LEFT.x, DOWN.y), + RIGHT_DOWN(RIGHT.x, DOWN.y), + UP_UP_LEFT(LEFT_DOWN.x, UP_UP.y), + UP_UP_RIGHT(RIGHT_DOWN.x, UP_UP.y), + LEFT_LEFT_UP(LEFT.x * 2, UP.y), + LEFT_LEFT_DOWN(LEFT.x * 2, DOWN.y), + RIGHT_RIGHT_UP(RIGHT.x * 2, UP.y), + RIGHT_RIGHT_DOWN(RIGHT.x * 2, DOWN.y), + DOWN_DOWN_LEFT(LEFT_DOWN.x, DOWN_DOWN.y), + DOWN_DOWN_RIGHT(RIGHT_DOWN.x, DOWN_DOWN.y), + ; + + private final int x; + + private final int y; + + Movement(final int x, final int y) { + this.x = x; + this.y = y; + } + + public int x() { + return x; + } + + public int y() { + return y; + } + + public boolean isVertical() { + return x == 0 && y != 0; + } + + public boolean isDiagonal() { + return x != 0 && y != 0 && Math.abs(x) == Math.abs(y); + } +} diff --git a/src/main/java/chess/Position.java b/src/main/java/chess/Position.java new file mode 100644 index 00000000000..7de24ddf98d --- /dev/null +++ b/src/main/java/chess/Position.java @@ -0,0 +1,174 @@ +package chess; + +public record Position( + Column column, + Row row +) { + public Position(final Row row, final Column column) { + this(column, row); + } + + public Position copyOf() { + return new Position(this.column, this.row); + } + + public boolean canMoveUp() { + return row.canMoveUp(1); + } + + public boolean canMoveUp(final int step) { + return row.canMoveUp(step); + } + + public Position moveUp() { + return moveUp(1); + } + + public Position moveUp(final int step) { + return new Position(row.moveUp(step), column); + } + + public boolean canMoveDown() { + return canMoveDown(1); + } + + public boolean canMoveDown(final int step) { + return row.canMoveDown(step); + } + + public Position moveDown() { + return moveDown(1); + } + + public Position moveDown(final int step) { + return new Position(row.moveDown(step), column); + } + + public boolean canMoveLeft() { + return canMoveLeft(1); + } + + public boolean canMoveLeft(final int step) { + return column.canMoveLeft(step); + } + + public Position moveLeft() { + return moveLeft(1); + } + + public Position moveLeft(final int step) { + return new Position(row, column.moveLeft(step)); + } + + public boolean canMoveRight() { + return canMoveRight(1); + } + + public boolean canMoveRight(final int step) { + return column.canMoveRight(step); + } + + public Position moveRight() { + return moveRight(1); + } + + public Position moveRight(final int step) { + return new Position(row, column.moveRight(step)); + } + + public boolean canMoveLeftUp() { + return canMoveLeft() && canMoveUp(); + } + + public Position moveLeftUp() { + return moveLeft().moveUp(); + } + + public boolean canMoveLeftDown() { + return canMoveLeft() && canMoveDown(); + } + + public Position moveLeftDown() { + return moveLeft().moveDown(); + } + + public boolean canMoveRightUp() { + return canMoveUp() && canMoveRight(); + } + + public Position moveRightUp() { + return moveRight().moveUp(); + } + + public boolean canMoveRightDown() { + return canMoveRight() && canMoveDown(); + } + + public Position moveRightDown() { + return moveRight().moveDown(); + } + + public boolean isTop() { + return row.isTop(); + } + + public boolean isBottom() { + return row.isBottom(); + } + + public boolean isFarLeft() { + return column.isFarLeft(); + } + + public boolean isFarRight() { + return column.isFarRight(); + } + + public boolean canMove(final Movement movement) { + return canMoveVertical(movement.y()) && canMoveHorizontal(movement.x()); + } + + public boolean canMoveVertical(final int step) { + if (step > 0) { + return canMoveUp(step); + } + if (step < 0) { + return canMoveDown(-step); + } + return true; + } + + public boolean canMoveHorizontal(final int step) { + if (step > 0) { + return canMoveRight(step); + } + if (step < 0) { + return canMoveLeft(-step); + } + return true; + } + + public Position move(final Movement movement) { + return moveVertical(movement.y()).moveHorizontal(movement.x()); + } + + public Position moveVertical(final int step) { + if (step > 0) { + return moveUp(step); + } + if (step < 0) { + return moveDown(-step); + } + return this; + } + + public Position moveHorizontal(final int step) { + if (step > 0) { + return moveRight(step); + } + if (step < 0) { + return moveLeft(-step); + } + return this; + } +} diff --git a/src/main/java/chess/Row.java b/src/main/java/chess/Row.java new file mode 100644 index 00000000000..3f6152f4547 --- /dev/null +++ b/src/main/java/chess/Row.java @@ -0,0 +1,73 @@ +package chess; + +import java.util.Arrays; + +public enum Row { + + EIGHT(8), + SEVEN(7), + SIX(6), + FIVE(5), + FOUR(4), + THREE(3), + TWO(2), + ONE(1); + + private final int name; + + Row(int name) { + this.name = name; + } + + public boolean isTop() { + return ordinal() == 0; + } + + public boolean isBottom() { + return ordinal() + 1 == values().length; + } + + public boolean canMoveUp(final int step) { + return ordinal() - step >= 0; + } + + public Row moveUp() { + return moveUp(1); + } + + public Row moveUp(final int step) { + if (canMoveUp(step)) { + return values()[ordinal() - step]; + } + + throw new IllegalStateException("움직일 수 없는 위치입니다."); + } + + public boolean canMoveDown(final int step) { + return ordinal() + step < values().length; + } + + public Row moveDown() { + return moveDown(1); + } + + public Row moveDown(final int step) { + if (canMoveDown(step)) { + return values()[ordinal() + step]; + } + + throw new IllegalStateException("움직일 수 없는 위치입니다."); + } + + public static Row isSameName(String name) { + int compareValue = Integer.parseInt(name); + return Arrays.stream(Row.values()) + .filter(row -> row.getName() == compareValue) + .findAny() + .orElseThrow(() -> new IllegalArgumentException("없음 그딴거")); + } + + public int getName() { + return name; + } +} diff --git a/src/main/java/chess/piece/Bishop.java b/src/main/java/chess/piece/Bishop.java new file mode 100644 index 00000000000..c2757bb74c6 --- /dev/null +++ b/src/main/java/chess/piece/Bishop.java @@ -0,0 +1,99 @@ +package chess.piece; + +import chess.Color; +import chess.Position; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Bishop extends Piece{ + + public Bishop(Color color) { + super(color); + } + + @Override + public List calculateCanMovePosition(Position departure, Position arrival) { + + List rightUpResult = calculateRightUp(departure, arrival); + List leftDownResult = calculateLeftDown(departure, arrival); + List leftUpResult = calculateLeftUp(departure, arrival); + List rightDownResult = calculateRightDown(departure, arrival); + + if (!rightUpResult.isEmpty()) { + return rightUpResult; + } + if (!leftDownResult.isEmpty()) { + return leftDownResult; + } + if (!leftUpResult.isEmpty()) { + return leftUpResult; + } + if (!rightDownResult.isEmpty()) { + return rightDownResult; + } + throw new IllegalArgumentException("해당 기물이 갈 수 없는 위치입니다."); + } + + private List calculateRightUp(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + Position movedDeparture = departure.copyOf(); + while (movedDeparture.canMoveRightUp()) { + Position movedPosition = movedDeparture.moveRightUp(); + tmpPosition.add(movedPosition); + if (movedPosition.equals(arrival)) { + return tmpPosition; + } + movedDeparture = movedPosition; + } + return Collections.emptyList(); + } + + private List calculateLeftDown(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + Position movedDeparture = departure.copyOf(); + while (movedDeparture.canMoveLeftDown()) { + Position movedPosition = movedDeparture.moveLeftDown(); + tmpPosition.add(movedPosition); + if (movedPosition.equals(arrival)) { + return tmpPosition; + } + movedDeparture = movedPosition; + } + return Collections.emptyList(); + } + private List calculateLeftUp(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + Position movedDeparture = departure.copyOf(); + while (movedDeparture.canMoveLeftUp()) { + Position movedPosition = movedDeparture.moveLeftUp(); + tmpPosition.add(movedPosition); + if (movedPosition.equals(arrival)) { + return tmpPosition; + } + movedDeparture = movedPosition; + } + return Collections.emptyList(); + } + private List calculateRightDown(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + Position movedDeparture = departure.copyOf(); + while (movedDeparture.canMoveRightDown()) { + Position movedPosition = movedDeparture.moveRightDown(); + tmpPosition.add(movedPosition); + if (movedPosition.equals(arrival)) { + return tmpPosition; + } + movedDeparture = movedPosition; + } + return Collections.emptyList(); + } + + @Override + public String toString() { + if (getColor().isBlack()) { + return "B"; + } + return "b"; + } +} diff --git a/src/main/java/chess/piece/King.java b/src/main/java/chess/piece/King.java new file mode 100644 index 00000000000..b875b5eefdd --- /dev/null +++ b/src/main/java/chess/piece/King.java @@ -0,0 +1,81 @@ +package chess.piece; + +import chess.Color; +import chess.Position; +import java.util.ArrayList; +import java.util.List; + +public class King extends Piece{ + + public King(Color color) { + super(color); + } + + @Override + public List calculateCanMovePosition(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + if (departure.canMoveUp()) { + Position movedPosition = departure.moveUp(); + if (arrival.equals(movedPosition)) { + return List.of(movedPosition); + } + } + if (departure.canMoveDown()) { + Position movedPosition = departure.moveDown(); + if (arrival.equals(movedPosition)) { + return List.of(movedPosition); + } + } + + if (departure.canMoveLeft()) { + Position movedPosition = departure.moveLeft(); + if (arrival.equals(movedPosition)) { + return List.of(movedPosition); + } + } + + if (departure.canMoveRight()) { + Position movedPosition = departure.moveRight(); + if (arrival.equals(movedPosition)) { + return List.of(movedPosition); + } + } + + if (departure.canMoveRightUp()) { + Position movedPosition = departure.moveRightUp(); + if (arrival.equals(movedPosition)) { + return List.of(movedPosition); + } + } + + if (departure.canMoveRightDown()) { + Position movedPosition = departure.moveRightDown(); + if (arrival.equals(movedPosition)) { + return List.of(movedPosition); + } + } + + if (departure.canMoveLeftUp()) { + Position movedPosition = departure.moveLeftUp(); + if (arrival.equals(movedPosition)) { + return List.of(movedPosition); + } + } + + if (departure.canMoveLeftDown()) { + Position movedPosition = departure.moveLeftDown(); + if (arrival.equals(movedPosition)) { + return List.of(movedPosition); + } + } + throw new IllegalArgumentException("해당 기물이 갈 수 없는 위치입니다."); + } + + @Override + public String toString() { + if (getColor().isBlack()) { + return "K"; + } + return "k"; + } +} diff --git a/src/main/java/chess/piece/Knight.java b/src/main/java/chess/piece/Knight.java new file mode 100644 index 00000000000..3e577f89465 --- /dev/null +++ b/src/main/java/chess/piece/Knight.java @@ -0,0 +1,167 @@ +package chess.piece; + +import chess.Color; +import chess.Position; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Knight extends Piece{ + + public Knight(Color color) { + super(color); + } + + @Override + public List calculateCanMovePosition(Position departure, Position arrival) { + + List upAndLeftUpResult = upAndLeftUp(departure); + List upAndRightUpResult = upAndRightUp(departure); + List downAndLeftDownResult = downAndLeftDown(departure); + List downAndRightDownResult = downAndRightDown(departure); + List leftAndLeftDownResult = leftAndLeftDown(departure); + List leftAndLeftUpResult = leftAndLeftUp(departure); + List rightAndRightUpResult = rightAndRightUp(departure); + List rightAndRightDownResult = rightAndRightDown(departure); + + + if (!upAndLeftUpResult.isEmpty() && upAndLeftUpResult.getLast().equals(arrival)) { + return upAndLeftUpResult; + } + if (!upAndRightUpResult.isEmpty() && upAndRightUpResult.getLast().equals(arrival)) { + return upAndRightUpResult; + } + if (!downAndLeftDownResult.isEmpty() &&downAndLeftDownResult.getLast().equals(arrival)) { + return downAndLeftDownResult; + } + if (!downAndRightDownResult.isEmpty() &&downAndRightDownResult.getLast().equals(arrival)) { + return downAndRightDownResult; + } + if (!leftAndLeftDownResult.isEmpty() &&leftAndLeftDownResult.getLast().equals(arrival)) { + return leftAndLeftDownResult; + } + if (!leftAndLeftUpResult.isEmpty() &&leftAndLeftUpResult.getLast().equals(arrival)) { + return leftAndLeftUpResult; + } + if (!rightAndRightUpResult.isEmpty() &&rightAndRightUpResult.getLast().equals(arrival)) { + return rightAndRightUpResult; + } + if (!rightAndRightDownResult.isEmpty() &&rightAndRightDownResult.getLast().equals(arrival)) { + return rightAndRightDownResult; + } + + throw new IllegalArgumentException("해당 기물이 갈 수 없는 위치입니다."); + } + + private List upAndLeftUp(Position departure) { + Position movedPosition; + if (departure.canMoveUp()) { + movedPosition = departure.moveUp(); + } else { + return Collections.emptyList(); + } + if (movedPosition.canMoveLeftUp()) { + return List.of(departure.moveUp(), movedPosition.moveLeftUp()); + } + return Collections.emptyList(); + } + + private List upAndRightUp(Position departure) { + Position movedPosition; + if (departure.canMoveUp()) { + movedPosition = departure.moveUp(); + } else { + return Collections.emptyList(); + } + if (movedPosition.canMoveRightUp()) { + return List.of(departure.moveUp(), movedPosition.moveRightUp()); + } + return Collections.emptyList(); + } + + private List downAndLeftDown(Position departure) { + Position movedPosition; + if (departure.canMoveDown()) { + movedPosition = departure.moveDown(); + } else { + return Collections.emptyList(); + } + if (movedPosition.canMoveLeftDown()) { + return List.of(departure.moveDown(), movedPosition.moveLeftDown()); + } + return Collections.emptyList(); + } + + private List downAndRightDown(Position departure) { + Position movedPosition; + if (departure.canMoveDown()) { + movedPosition = departure.moveDown(); + } else { + return Collections.emptyList(); + } + if (movedPosition.canMoveRightDown()) { + return List.of(departure.moveDown(), movedPosition.moveRightDown()); + } + return Collections.emptyList(); + } + + private List leftAndLeftDown(Position departure) { + Position movedPosition; + if (departure.canMoveLeft()) { + movedPosition = departure.moveLeft(); + } else{ + return Collections.emptyList(); + } + if (movedPosition.canMoveLeftDown()) { + return List.of(departure.moveLeft(), movedPosition.moveLeftDown()); + } + return Collections.emptyList(); + } + + private List leftAndLeftUp(Position departure) { + Position movedPosition; + if (departure.canMoveLeft()) { + movedPosition = departure.moveLeft(); + } else{ + return Collections.emptyList(); + } + if (movedPosition.canMoveLeftUp()) { + return List.of(departure.moveLeft(), movedPosition.moveLeftUp()); + } + return Collections.emptyList(); + } + + private List rightAndRightUp(Position departure) { + Position movedPosition; + if (departure.canMoveRight()) { + movedPosition = departure.moveRight(); + } else{ + return Collections.emptyList(); + } + if (movedPosition.canMoveRightUp()) { + return List.of(departure.moveRight(), movedPosition.moveRightUp()); + } + return Collections.emptyList(); + } + + private List rightAndRightDown(Position departure) { + Position movedPosition; + if (departure.canMoveRight()) { + movedPosition = departure.moveRight(); + } else{ + return Collections.emptyList(); + } + if (movedPosition.canMoveRightDown()) { + return List.of(departure.moveRight(), movedPosition.moveRightDown()); + } + return Collections.emptyList(); + } + + @Override + public String toString() { + if (getColor().isBlack()) { + return "N"; + } + return "n"; + } +} diff --git a/src/main/java/chess/piece/Pawn.java b/src/main/java/chess/piece/Pawn.java new file mode 100644 index 00000000000..f80033d48d6 --- /dev/null +++ b/src/main/java/chess/piece/Pawn.java @@ -0,0 +1,25 @@ +package chess.piece; + +import chess.Color; +import chess.Position; +import java.util.List; + +public class Pawn extends Piece{ + + public Pawn(Color color) { + super(color); + } + + @Override + public List calculateCanMovePosition(Position departure, Position arrival) { + return List.of(); + } + + @Override + public String toString() { + if (getColor().isBlack()) { + return "A"; + } + return "a"; + } +} diff --git a/src/main/java/chess/piece/Piece.java b/src/main/java/chess/piece/Piece.java new file mode 100644 index 00000000000..ced09700678 --- /dev/null +++ b/src/main/java/chess/piece/Piece.java @@ -0,0 +1,24 @@ +package chess.piece; + +import chess.Color; +import chess.Position; +import java.util.List; + +public abstract class Piece { + + private final Color color; + + public Piece(Color color) { + this.color = color; + } + + public abstract List calculateCanMovePosition(Position departure, Position arrival); + + public Color getColor() { + return this.color; + } + + public boolean isSameType(Piece piece) { + return this.getClass() == piece.getClass(); + } +} diff --git a/src/main/java/chess/piece/Queen.java b/src/main/java/chess/piece/Queen.java new file mode 100644 index 00000000000..c3c6ce18a6e --- /dev/null +++ b/src/main/java/chess/piece/Queen.java @@ -0,0 +1,171 @@ +package chess.piece; + +import chess.Color; +import chess.Position; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Queen extends Piece{ + + public Queen(Color color) { + super(color); + } + + @Override + public List calculateCanMovePosition(Position departure, Position arrival) { + + List upResult = calculateUp(departure, arrival); + List downResult = calculateDown(departure, arrival); + List leftResult = calculateLeft(departure, arrival); + List rightResult = calculateRight(departure, arrival); + List rightUpResult = calculateRightUp(departure, arrival); + List leftDownResult = calculateLeftDown(departure, arrival); + List leftUpResult = calculateLeftUp(departure, arrival); + List rightDownResult = calculateRightDown(departure, arrival); + + if (!rightUpResult.isEmpty()) { + return rightUpResult; + } + if (!leftDownResult.isEmpty()) { + return leftDownResult; + } + if (!leftUpResult.isEmpty()) { + return leftUpResult; + } + if (!rightDownResult.isEmpty()) { + return rightDownResult; + } + + if (!upResult.isEmpty()) { + return upResult; + } + if (!downResult.isEmpty()) { + return downResult; + } + if (!leftResult.isEmpty()) { + return leftResult; + } + if (!rightResult.isEmpty()) { + return rightResult; + } + + throw new IllegalArgumentException("해당 기물이 갈 수 없는 위치입니다."); + } + + private List calculateRightUp(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + Position movedDeparture = departure.copyOf(); + while (movedDeparture.canMoveRightUp()) { + Position movedPosition = movedDeparture.moveRightUp(); + tmpPosition.add(movedPosition); + if (movedPosition.equals(arrival)) { + return tmpPosition; + } + movedDeparture = movedPosition; + } + return Collections.emptyList(); + } + + private List calculateLeftDown(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + Position movedDeparture = departure.copyOf(); + while (movedDeparture.canMoveLeftDown()) { + Position movedPosition = movedDeparture.moveLeftDown(); + tmpPosition.add(movedPosition); + if (movedPosition.equals(arrival)) { + return tmpPosition; + } + movedDeparture = movedPosition; + } + return Collections.emptyList(); + } + private List calculateLeftUp(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + Position movedDeparture = departure.copyOf(); + while (movedDeparture.canMoveLeftUp()) { + Position movedPosition = movedDeparture.moveLeftUp(); + tmpPosition.add(movedPosition); + if (movedPosition.equals(arrival)) { + return tmpPosition; + } + movedDeparture = movedPosition; + } + return Collections.emptyList(); + } + private List calculateRightDown(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + Position movedDeparture = departure.copyOf(); + while (movedDeparture.canMoveRightDown()) { + Position movedPosition = movedDeparture.moveRightDown(); + tmpPosition.add(movedPosition); + if (movedPosition.equals(arrival)) { + return tmpPosition; + } + movedDeparture = movedPosition; + } + return Collections.emptyList(); + } + + private List calculateUp(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + Position movedDeparture = departure.copyOf(); + while (movedDeparture.canMoveUp()) { + Position movedPosition = movedDeparture.moveUp(); + tmpPosition.add(movedPosition); + if (movedPosition.equals(arrival)) { + return tmpPosition; + } + movedDeparture = movedPosition; + } + return Collections.emptyList(); + } + + private List calculateDown(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + Position movedDeparture = departure.copyOf(); + while (movedDeparture.canMoveDown()) { + Position movedPosition = movedDeparture.moveDown(); + tmpPosition.add(movedPosition); + if (movedPosition.equals(arrival)) { + return tmpPosition; + } + movedDeparture = movedPosition; + } + return Collections.emptyList(); + } + private List calculateLeft(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + Position movedDeparture = departure.copyOf(); + while (movedDeparture.canMoveLeft()) { + Position movedPosition = movedDeparture.moveLeft(); + tmpPosition.add(movedPosition); + if (movedPosition.equals(arrival)) { + return tmpPosition; + } + movedDeparture = movedPosition; + } + return Collections.emptyList(); + } + private List calculateRight(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + Position movedDeparture = departure.copyOf(); + while (movedDeparture.canMoveRight()) { + Position movedPosition = movedDeparture.moveRight(); + tmpPosition.add(movedPosition); + if (movedPosition.equals(arrival)) { + return tmpPosition; + } + movedDeparture = movedPosition; + } + return Collections.emptyList(); + } + + @Override + public String toString() { + if (getColor().isBlack()) { + return "Q"; + } + return "q"; + } +} diff --git a/src/main/java/chess/piece/Rook.java b/src/main/java/chess/piece/Rook.java new file mode 100644 index 00000000000..24c892e4471 --- /dev/null +++ b/src/main/java/chess/piece/Rook.java @@ -0,0 +1,99 @@ +package chess.piece; + +import chess.Color; +import chess.Position; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Rook extends Piece{ + + public Rook(Color color) { + super(color); + } + + @Override + public List calculateCanMovePosition(Position departure, Position arrival) { + List upResult = calculateUp(departure, arrival); + List downResult = calculateDown(departure, arrival); + List leftResult = calculateLeft(departure, arrival); + List rightResult = calculateRight(departure, arrival); + + if (!upResult.isEmpty()) { + return upResult; + } + if (!downResult.isEmpty()) { + return downResult; + } + if (!leftResult.isEmpty()) { + return leftResult; + } + if (!rightResult.isEmpty()) { + return rightResult; + } + throw new IllegalArgumentException("해당 기물이 갈 수 없는 위치입니다."); + } + + private List calculateUp(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + Position movedDeparture = departure.copyOf(); + while (movedDeparture.canMoveUp()) { + Position movedPosition = movedDeparture.moveUp(); + tmpPosition.add(movedPosition); + if (movedPosition.equals(arrival)) { + return tmpPosition; + } + movedDeparture = movedPosition; + } + return Collections.emptyList(); + } + + private List calculateDown(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + Position movedDeparture = departure.copyOf(); + while (movedDeparture.canMoveDown()) { + Position movedPosition = movedDeparture.moveDown(); + tmpPosition.add(movedPosition); + if (movedPosition.equals(arrival)) { + return tmpPosition; + } + movedDeparture = movedPosition; + } + return Collections.emptyList(); + } + private List calculateLeft(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + Position movedDeparture = departure.copyOf(); + while (movedDeparture.canMoveLeft()) { + Position movedPosition = movedDeparture.moveLeft(); + tmpPosition.add(movedPosition); + if (movedPosition.equals(arrival)) { + return tmpPosition; + } + movedDeparture = movedPosition; + } + return Collections.emptyList(); + } + private List calculateRight(Position departure, Position arrival) { + List tmpPosition = new ArrayList<>(); + Position movedDeparture = departure.copyOf(); + while (movedDeparture.canMoveRight()) { + Position movedPosition = movedDeparture.moveRight(); + tmpPosition.add(movedPosition); + if (movedPosition.equals(arrival)) { + return tmpPosition; + } + movedDeparture = movedPosition; + } + return Collections.emptyList(); + } + + @Override + public String toString() { + if (getColor().isBlack()) { + return "R"; + } + return "r"; + } + +} diff --git a/src/test/java/.gitkeep b/src/test/java/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/test/java/chess/ColumnTest.java b/src/test/java/chess/ColumnTest.java new file mode 100644 index 00000000000..e43523240f7 --- /dev/null +++ b/src/test/java/chess/ColumnTest.java @@ -0,0 +1,95 @@ +package chess; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@DisplayName("열") +class ColumnTest { + + @DisplayName("A는 맨 왼쪽이다.") + @Test + void isFarLeft_A() { + assertThat(Column.A.isFarLeft()).isTrue(); + } + + @DisplayName("B는 맨 왼쪽이 아니다.") + @Test + void isFarLeft_B() { + assertThat(Column.B.isFarLeft()).isFalse(); + } + + @DisplayName("H는 맨 오른쪽이다.") + @Test + void isFarRight_H() { + assertThat(Column.H.isFarRight()).isTrue(); + } + + @DisplayName("F는 맨 오른쪽이 아니다.") + @Test + void isFarRight_F() { + assertThat(Column.F.isFarRight()).isFalse(); + } + + @DisplayName("A는 왼쪽으로 이동할 수 없다.") + @Test + void moveLeft_A() { + assertThatThrownBy(Column.A::moveLeft) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("B는 왼쪽으로 이동하면 A다.") + @Test + void moveLeft_B() { + final var moved = Column.B.moveLeft(); + + assertThat(moved).isEqualTo(Column.A); + } + + @DisplayName("B는 왼쪽으로 2번 이동할 수 없다.") + @Test + void moveLeft_2_B() { + assertThatThrownBy(() -> Column.B.moveLeft(2)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("C는 왼쪽으로 2번 이동하면 A다.") + @Test + void moveLeft_2_C() { + final var moved = Column.C.moveLeft(2); + + assertThat(moved).isEqualTo(Column.A); + } + + @DisplayName("H는 오른쪽으로 이동할 수 없다.") + @Test + void moveRight_H() { + assertThatThrownBy(Column.H::moveRight) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("G는 오른쪽으로 이동하면 H다.") + @Test + void moveRight_G() { + final var moved = Column.G.moveRight(); + + assertThat(moved).isEqualTo(Column.H); + } + + @DisplayName("G는 오른쪽으로 2번 이동할 수 없다.") + @Test + void moveRight_2_G() { + assertThatThrownBy(() -> Column.G.moveRight(2)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("F는 오른쪽으로 2번 이동하면 H다.") + @Test + void moveRight_2_F() { + final var moved = Column.F.moveRight(2); + + assertThat(moved).isEqualTo(Column.H); + } +} diff --git a/src/test/java/chess/Fixtures.java b/src/test/java/chess/Fixtures.java new file mode 100644 index 00000000000..f940ab37137 --- /dev/null +++ b/src/test/java/chess/Fixtures.java @@ -0,0 +1,80 @@ +package chess; + +@SuppressWarnings("unused") +public final class Fixtures { + + public static final Position A1 = new Position(Column.A, Row.ONE); + public static final Position A2 = new Position(Column.A, Row.TWO); + public static final Position A3 = new Position(Column.A, Row.THREE); + public static final Position A4 = new Position(Column.A, Row.FOUR); + public static final Position A5 = new Position(Column.A, Row.FIVE); + public static final Position A6 = new Position(Column.A, Row.SIX); + public static final Position A7 = new Position(Column.A, Row.SEVEN); + public static final Position A8 = new Position(Column.A, Row.EIGHT); + + public static final Position B1 = new Position(Column.B, Row.ONE); + public static final Position B2 = new Position(Column.B, Row.TWO); + public static final Position B3 = new Position(Column.B, Row.THREE); + public static final Position B4 = new Position(Column.B, Row.FOUR); + public static final Position B5 = new Position(Column.B, Row.FIVE); + public static final Position B6 = new Position(Column.B, Row.SIX); + public static final Position B7 = new Position(Column.B, Row.SEVEN); + public static final Position B8 = new Position(Column.B, Row.EIGHT); + + public static final Position C1 = new Position(Column.C, Row.ONE); + public static final Position C2 = new Position(Column.C, Row.TWO); + public static final Position C3 = new Position(Column.C, Row.THREE); + public static final Position C4 = new Position(Column.C, Row.FOUR); + public static final Position C5 = new Position(Column.C, Row.FIVE); + public static final Position C6 = new Position(Column.C, Row.SIX); + public static final Position C7 = new Position(Column.C, Row.SEVEN); + public static final Position C8 = new Position(Column.C, Row.EIGHT); + + public static final Position D1 = new Position(Column.D, Row.ONE); + public static final Position D2 = new Position(Column.D, Row.TWO); + public static final Position D3 = new Position(Column.D, Row.THREE); + public static final Position D4 = new Position(Column.D, Row.FOUR); + public static final Position D5 = new Position(Column.D, Row.FIVE); + public static final Position D6 = new Position(Column.D, Row.SIX); + public static final Position D7 = new Position(Column.D, Row.SEVEN); + public static final Position D8 = new Position(Column.D, Row.EIGHT); + + public static final Position E1 = new Position(Column.E, Row.ONE); + public static final Position E2 = new Position(Column.E, Row.TWO); + public static final Position E3 = new Position(Column.E, Row.THREE); + public static final Position E4 = new Position(Column.E, Row.FOUR); + public static final Position E5 = new Position(Column.E, Row.FIVE); + public static final Position E6 = new Position(Column.E, Row.SIX); + public static final Position E7 = new Position(Column.E, Row.SEVEN); + public static final Position E8 = new Position(Column.E, Row.EIGHT); + + public static final Position F1 = new Position(Column.F, Row.ONE); + public static final Position F2 = new Position(Column.F, Row.TWO); + public static final Position F3 = new Position(Column.F, Row.THREE); + public static final Position F4 = new Position(Column.F, Row.FOUR); + public static final Position F5 = new Position(Column.F, Row.FIVE); + public static final Position F6 = new Position(Column.F, Row.SIX); + public static final Position F7 = new Position(Column.F, Row.SEVEN); + public static final Position F8 = new Position(Column.F, Row.EIGHT); + + public static final Position G1 = new Position(Column.G, Row.ONE); + public static final Position G2 = new Position(Column.G, Row.TWO); + public static final Position G3 = new Position(Column.G, Row.THREE); + public static final Position G4 = new Position(Column.G, Row.FOUR); + public static final Position G5 = new Position(Column.G, Row.FIVE); + public static final Position G6 = new Position(Column.G, Row.SIX); + public static final Position G7 = new Position(Column.G, Row.SEVEN); + public static final Position G8 = new Position(Column.G, Row.EIGHT); + + public static final Position H1 = new Position(Column.H, Row.ONE); + public static final Position H2 = new Position(Column.H, Row.TWO); + public static final Position H3 = new Position(Column.H, Row.THREE); + public static final Position H4 = new Position(Column.H, Row.FOUR); + public static final Position H5 = new Position(Column.H, Row.FIVE); + public static final Position H6 = new Position(Column.H, Row.SIX); + public static final Position H7 = new Position(Column.H, Row.SEVEN); + public static final Position H8 = new Position(Column.H, Row.EIGHT); + + private Fixtures() { + } +} diff --git a/src/test/java/chess/PositionTest.java b/src/test/java/chess/PositionTest.java new file mode 100644 index 00000000000..3ad7cc64084 --- /dev/null +++ b/src/test/java/chess/PositionTest.java @@ -0,0 +1,392 @@ +package chess; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static chess.Fixtures.A1; +import static chess.Fixtures.A2; +import static chess.Fixtures.A3; +import static chess.Fixtures.A6; +import static chess.Fixtures.A7; +import static chess.Fixtures.A8; +import static chess.Fixtures.B1; +import static chess.Fixtures.B2; +import static chess.Fixtures.B3; +import static chess.Fixtures.B7; +import static chess.Fixtures.B8; +import static chess.Fixtures.C1; +import static chess.Fixtures.F1; +import static chess.Fixtures.F8; +import static chess.Fixtures.G1; +import static chess.Fixtures.G2; +import static chess.Fixtures.G6; +import static chess.Fixtures.G7; +import static chess.Fixtures.G8; +import static chess.Fixtures.H1; +import static chess.Fixtures.H2; +import static chess.Fixtures.H7; +import static chess.Fixtures.H8; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@DisplayName("위치") +class PositionTest { + + + @DisplayName("A1은 맨 왼쪽이다.") + @Test + void nonFarLeft_A1() { + assertThat(A1.isFarLeft()).isTrue(); + } + + @DisplayName("B1은 맨 왼쪽이 아니다.") + @Test + void nonFarLeft_B1() { + assertThat(B1.isFarLeft()).isFalse(); + } + + @DisplayName("H1은 맨 오른쪽이다.") + @Test + void nonFarRight_H1() { + assertThat(H1.isFarRight()).isTrue(); + } + + @DisplayName("F1은 맨 오른쪽이 아니다.") + @Test + void nonFarRight_F1() { + assertThat(F1.isFarRight()).isFalse(); + } + + @DisplayName("A1은 왼쪽으로 이동할 수 없다.") + @Test + void canMoveLeft_A1() { + assertThat(A1.canMoveLeft()).isFalse(); + } + + @DisplayName("A1은 왼쪽으로 이동할 수 없다.") + @Test + void canMoveLeft_Movement_A1() { + assertThat(A1.canMove(Movement.LEFT)).isFalse(); + } + + @DisplayName("B1은 왼쪽으로 이동할 수 있다.") + @Test + void canMoveLeft_B1() { + assertThat(B1.canMoveLeft()).isTrue(); + } + + @DisplayName("A1은 왼쪽으로 이동하면 예외가 발생한다.") + @Test + void moveLeft_A1() { + assertThatThrownBy(A1::moveLeft) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("B1은 왼쪽으로 이동하면 A1이다.") + @Test + void moveLeft_B1() { + final var moved = B1.moveLeft(); + + assertThat(moved).isEqualTo(A1); + } + + @DisplayName("B1은 왼쪽으로 2번 이동할 수 없다.") + @Test + void canMoveLeft_2_B1() { + assertThat(B1.canMoveLeft(2)).isFalse(); + } + + @DisplayName("B1은 왼쪽으로 2번 이동하면 예외가 발생한다.") + @Test + void moveLeft_2_B1() { + assertThatThrownBy(() -> B1.moveLeft(2)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("C1은 왼쪽으로 2번 이동하면 A1이다.") + @Test + void moveLeft_C2() { + final var moved = C1.moveLeft(2); + + assertThat(moved).isEqualTo(A1); + } + + @DisplayName("H1은 오른쪽으로 이동할 수 없다.") + @Test + void canMoveRight_H1() { + assertThat(H1.canMoveRight()).isFalse(); + } + + @DisplayName("H1은 오른쪽으로 이동할 수 없다.") + @Test + void canMoveRight_Movement_H1() { + assertThat(H1.canMove(Movement.RIGHT)).isFalse(); + } + + @DisplayName("H1은 오른쪽으로 이동하면 예외가 발생한다.") + @Test + void moveRight_H1() { + assertThatThrownBy(H1::moveRight) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("G1은 오른쪽으로 이동하면 H1다.") + @Test + void moveRight_G1() { + final var moved = G1.moveRight(); + + assertThat(moved).isEqualTo(H1); + } + + @DisplayName("G1은 오른쪽으로 2번 이동할 수 없다.") + @Test + void canMoveRight_2_G1() { + assertThat(G1.canMoveRight(2)).isFalse(); + } + + @DisplayName("G1은 오른쪽으로 2번 이동하면 예외가 발생한다.") + @Test + void moveRight_2_G1() { + assertThatThrownBy(() -> G1.moveRight(2)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("F1은 오른쪽으로 2번 이동하면 H1이다.") + @Test + void moveRight_2_F1() { + final var moved = F1.moveRight(2); + + assertThat(moved).isEqualTo(H1); + } + + ///// + + @DisplayName("A8은 맨 위다.") + @Test + void nonTop_A8() { + assertThat(A8.isTop()).isTrue(); + } + + @DisplayName("A7은 맨 위가 아니다.") + @Test + void nonTop_7() { + assertThat(A7.isTop()).isFalse(); + } + + @DisplayName("A1은 맨 아래다.") + @Test + void nonBottom_A1() { + assertThat(A1.isBottom()).isTrue(); + } + + @DisplayName("A2는 맨 아래가 아니다.") + @Test + void nonBottom_A2() { + assertThat(A2.isBottom()).isFalse(); + } + + @DisplayName("A8은 위로 이동할 수 없다.") + @Test + void canMoveUp_A8() { + assertThat(A8.canMoveUp()).isFalse(); + } + + @DisplayName("A8은 위로 이동하면 예외가 발생한다.") + @Test + void moveUp_A8() { + assertThatThrownBy(A8::moveUp) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("A7은 위로 이동하면 A8이다.") + @Test + void moveUp_A7() { + final var moved = A7.moveUp(); + + assertThat(moved).isEqualTo(A8); + } + + @DisplayName("A7은 위로 이동하면 A8이다.") + @Test + void moveUp_Movement_A7() { + final var moved = A7.move(Movement.UP); + + assertThat(moved).isEqualTo(A8); + } + + @DisplayName("A7은 위로 2번 이동할 수 없다.") + @Test + void canMoveUp_2_A7() { + assertThat(A7.canMoveUp(2)).isFalse(); + } + + @DisplayName("A7은 위로 2번 이동하면 예외가 발생한다.") + @Test + void moveUp_2_A7() { + assertThatThrownBy(() -> A7.moveUp(2)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("A6은 위로 2번 이동하면 A8이다.") + @Test + void moveUp_2_A6() { + final var moved = A6.moveUp(2); + + assertThat(moved).isEqualTo(A8); + } + + @DisplayName("A1은 아래로 이동할 수 없다.") + @Test + void canMoveDown_A1() { + assertThat(A1.canMoveDown()).isFalse(); + } + + @DisplayName("A1은 아래로 이동하면 예외가 발생한다.") + @Test + void moveDown_A1() { + assertThatThrownBy(A1::moveDown) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("A2는 아래로 이동하면 A1이다.") + @Test + void moveDown_A2() { + final var moved = A2.moveDown(); + + assertThat(moved).isEqualTo(A1); + } + + @DisplayName("A2는 아래로 2번 이동할 수 없다.") + @Test + void canMoveDown_2_A2() { + assertThat(A2.canMoveDown(2)).isFalse(); + } + + @DisplayName("A2는 아래로 2번 이동하면 예외가 발생한다.") + @Test + void moveDown_2_A2() { + assertThatThrownBy(() -> A2.moveDown(2)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("A3는 아래로 2번 이동하면 A1이다.") + @Test + void moveDown_2_A3() { + final var moved = A3.moveDown(2); + + assertThat(moved).isEqualTo(A1); + } + + @DisplayName("왼쪽 위 대각선으로 움직이면 예외가 발생한다.") + @MethodSource("immovableLeftUpSource") + @ParameterizedTest(name = "{0}은 왼쪽 위 대각선으로 움직이면 예외가 발생한다.") + void moveLeftUp_immovable(final Position position) { + assertThatThrownBy(position::moveLeftUp) + .isInstanceOf(IllegalStateException.class); + } + + static Stream immovableLeftUpSource() { + final var canMoveLeftPositions = Stream.of(A1, A2, A7, A8); + final var canMoveUpPositions = Stream.of(A8, B8, F8, H8); + + return Stream.concat(canMoveLeftPositions, canMoveUpPositions); + } + + @DisplayName("왼쪽 위 대각선으로 움직인다.") + @MethodSource("movableLeftUpSource") + @ParameterizedTest(name = "{0}을 왼쪽 위 대각선으로 움직인다.") + void moveLeftUp_movable(final Position position) { + assertThatCode(position::moveLeftUp) + .doesNotThrowAnyException(); + } + + static Stream movableLeftUpSource() { + return Stream.of(B2, B3, B7, G1, G2, G6, G7); + } + + @DisplayName("오른쪽 위 대각선으로 움직이면 예외가 발생한다.") + @MethodSource("immovableRightUpSource") + @ParameterizedTest(name = "{0}은 오른쪽 위 대각선으로 움직이면 예외가 발생한다.") + void moveRightUp_immovable(final Position position) { + assertThatThrownBy(position::moveRightUp) + .isInstanceOf(IllegalStateException.class); + } + + static Stream immovableRightUpSource() { + final var canMoveRightPositions = Stream.of(H1, H2, H7, H8); + final var canMoveUpPositions = Stream.of(A8, B8, F8, H8); + + return Stream.concat(canMoveRightPositions, canMoveUpPositions); + } + + @DisplayName("오른쪽 위 대각선으로 움직인다.") + @MethodSource("movableRightUpSource") + @ParameterizedTest(name = "{0}을 왼쪽 위 대각선으로 움직인다.") + void moveRightUp_movable(final Position position) { + assertThatCode(position::moveRightUp) + .doesNotThrowAnyException(); + } + + static Stream movableRightUpSource() { + return Stream.of(B1, B2, B3, B7, A2, A6, A7, G1, G2, G7); + } + + @DisplayName("왼쪽 아래 대각선으로 움직이면 예외가 발생한다.") + @MethodSource("immovableLeftDownSource") + @ParameterizedTest(name = "{0}은 왼쪽 아래 대각선으로 움직이면 예외가 발생한다.") + void moveLeftDown_immovable(final Position position) { + assertThatThrownBy(position::moveLeftDown) + .isInstanceOf(IllegalStateException.class); + } + + static Stream immovableLeftDownSource() { + final var canMoveLeftPositions = Stream.of(A1, A2, A7, A8); + final var canMoveDownPositions = Stream.of(A1, B1, F1, H1); + + return Stream.concat(canMoveLeftPositions, canMoveDownPositions); + } + + @DisplayName("왼쪽 아래 대각선으로 움직인다.") + @MethodSource("movableLeftDownSource") + @ParameterizedTest(name = "{0}을 왼쪽 아래 대각선으로 움직인다.") + void moveLeftDown_movable(final Position position) { + assertThatCode(position::moveLeftDown) + .doesNotThrowAnyException(); + } + + static Stream movableLeftDownSource() { + return Stream.of(B2, B3, B7, G8, G2, G6, G7); + } + + @DisplayName("오른쪽 아래 대각선으로 움직이면 예외가 발생한다.") + @MethodSource("immovableRightDownSource") + @ParameterizedTest(name = "{0}은 오른쪽 아래 대각선으로 움직이면 예외가 발생한다.") + void moveRightDown_immovable(final Position position) { + assertThatThrownBy(position::moveRightDown) + .isInstanceOf(IllegalStateException.class); + } + + static Stream immovableRightDownSource() { + final var canMoveRightPositions = Stream.of(H1, H2, H7, H8); + final var canMoveDownPositions = Stream.of(A1, B1, F1, H1); + + return Stream.concat(canMoveRightPositions, canMoveDownPositions); + } + + @DisplayName("오른쪽 아래 대각선으로 움직인다.") + @MethodSource("movableRightDownSource") + @ParameterizedTest(name = "{0}을 왼쪽 아래 대각선으로 움직인다.") + void moveRightDown_movable(final Position position) { + assertThatCode(position::moveRightDown) + .doesNotThrowAnyException(); + } + + static Stream movableRightDownSource() { + return Stream.of(B8, B2, B3, B7, A2, A6, A7, G8, G2, G7); + } +} diff --git a/src/test/java/chess/RowTest.java b/src/test/java/chess/RowTest.java new file mode 100644 index 00000000000..fcb65485410 --- /dev/null +++ b/src/test/java/chess/RowTest.java @@ -0,0 +1,95 @@ +package chess; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@DisplayName("행") +class RowTest { + + @DisplayName("8은 맨 위다.") + @Test + void isTop_8() { + assertThat(Row.EIGHT.isTop()).isTrue(); + } + + @DisplayName("7은 맨 위가 아니다.") + @Test + void isTop_7() { + assertThat(Row.SEVEN.isTop()).isFalse(); + } + + @DisplayName("1은 맨 아래다.") + @Test + void isBottom_1() { + assertThat(Row.ONE.isBottom()).isTrue(); + } + + @DisplayName("2는 맨 아래가 아니다.") + @Test + void isBottom_2() { + assertThat(Row.TWO.isBottom()).isFalse(); + } + + @DisplayName("8은 위로 이동할 수 없다.") + @Test + void moveUp_8() { + assertThatThrownBy(Row.EIGHT::moveUp) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("7은 위로 이동하면 8이다.") + @Test + void moveUp_7() { + final var moved = Row.SEVEN.moveUp(); + + assertThat(moved).isEqualTo(Row.EIGHT); + } + + @DisplayName("7은 위로 2번 이동할 수 없다.") + @Test + void moveUp_2_7() { + assertThatThrownBy(() -> Row.SEVEN.moveUp(2)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("6은 위로 2번 이동하면 8이다.") + @Test + void moveUp_2_6() { + final var moved = Row.SIX.moveUp(2); + + assertThat(moved).isEqualTo(Row.EIGHT); + } + + @DisplayName("1은 아래로 이동할 수 없다.") + @Test + void moveDown_1() { + assertThatThrownBy(Row.ONE::moveDown) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("2는 아래로 이동하면 1이다.") + @Test + void moveDown_2() { + final var moved = Row.TWO.moveDown(); + + assertThat(moved).isEqualTo(Row.ONE); + } + + @DisplayName("2는 아래로 2번 이동할 수 없다.") + @Test + void moveDown_2_2() { + assertThatThrownBy(() -> Row.TWO.moveDown(2)) + .isInstanceOf(IllegalStateException.class); + } + + @DisplayName("3은 아래로 2번 이동하면 1이다.") + @Test + void moveDown_2_3() { + final var moved = Row.THREE.moveDown(2); + + assertThat(moved).isEqualTo(Row.ONE); + } +} diff --git a/src/test/java/chess/piece/BishopTest.java b/src/test/java/chess/piece/BishopTest.java new file mode 100644 index 00000000000..c66e131a215 --- /dev/null +++ b/src/test/java/chess/piece/BishopTest.java @@ -0,0 +1,38 @@ +package chess.piece; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import chess.Color; +import chess.Column; +import chess.Position; +import chess.Row; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class BishopTest { + + @DisplayName("비숍이 이동가능한 경로를 구한다.") + @Test + void calculate_king_can_move_direction() { + Position departure = new Position(Column.A, Row.ONE); + Bishop bishop = new Bishop(Color.BLACK); + Position arrival = new Position(Column.C, Row.THREE); + List canAblePositions = bishop.calculateCanMovePosition(departure, arrival); + + List expectedPosition = List.of( + new Position(Column.B, Row.TWO), + new Position(Column.C, Row.THREE)); + assertThat(canAblePositions).containsExactlyInAnyOrderElementsOf(expectedPosition); + } + + @DisplayName("비숍이 갈 수 없는 위치라면, 예외를 던져야 한다.") + @Test + void if_bishop_cannot_go_position_then_throw_exception() { + Position departure = new Position(Column.A, Row.ONE); + Bishop bishop = new Bishop(Color.BLACK); + Position arrival = new Position(Column.A, Row.TWO); + assertThatThrownBy(() -> bishop.calculateCanMovePosition(departure, arrival)); + } +} diff --git a/src/test/java/chess/piece/KingTest.java b/src/test/java/chess/piece/KingTest.java new file mode 100644 index 00000000000..66d7393edb1 --- /dev/null +++ b/src/test/java/chess/piece/KingTest.java @@ -0,0 +1,82 @@ +package chess.piece; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import chess.Color; +import chess.Column; +import chess.Position; +import chess.Row; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +public class KingTest { + + @Nested + @DisplayName("킹이 이동가능한 경로를 구한다.") + class FindKingDirection { + + @Test + @DisplayName("up") + void up_case() { + Position departure = new Position(Column.A, Row.ONE); + King king = new King(Color.BLACK); + Position arrival = new Position(Column.A, Row.TWO); + List canAblePositions = king.calculateCanMovePosition(departure, arrival); + + List expectedPosition = List.of( + new Position(Column.A, Row.TWO)); + assertThat(canAblePositions).isEqualTo(expectedPosition); + } + + @Test + @DisplayName("down") + void down_case() { + Position departure = new Position(Column.D, Row.FOUR); + King king = new King(Color.BLACK); + Position arrival = new Position(Column.D, Row.THREE); + List canAblePositions = king.calculateCanMovePosition(departure, arrival); + + List expectedPosition = List.of( + new Position(Column.D, Row.THREE)); + assertThat(canAblePositions).isEqualTo(expectedPosition); + } + + @Test + @DisplayName("left") + void left_case() { + Position departure = new Position(Column.D, Row.FOUR); + King king = new King(Color.BLACK); + Position arrival = new Position(Column.C, Row.FOUR); + List canAblePositions = king.calculateCanMovePosition(departure, arrival); + + List expectedPosition = List.of( + new Position(Column.C, Row.FOUR)); + assertThat(canAblePositions).isEqualTo(expectedPosition); + } + + @Test + @DisplayName("right") + void right_case() { + Position departure = new Position(Column.D, Row.FOUR); + King king = new King(Color.BLACK); + Position arrival = new Position(Column.E, Row.FOUR); + List canAblePositions = king.calculateCanMovePosition(departure, arrival); + + List expectedPosition = List.of( + new Position(Column.E, Row.FOUR)); + assertThat(canAblePositions).isEqualTo(expectedPosition); + } + } + + @Test + @DisplayName("킹이 이동 못 하는 경로일 경우 예외가 발생해야 한다") + void right_case() { + Position departure = new Position(Column.A, Row.ONE); + King king = new King(Color.BLACK); + Position arrival = new Position(Column.C, Row.SIX); + assertThatThrownBy(() -> king.calculateCanMovePosition(departure, arrival)); + } +} diff --git a/src/test/java/chess/piece/KnightTest.java b/src/test/java/chess/piece/KnightTest.java new file mode 100644 index 00000000000..69bb215eb67 --- /dev/null +++ b/src/test/java/chess/piece/KnightTest.java @@ -0,0 +1,37 @@ +package chess.piece; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import chess.Color; +import chess.Column; +import chess.Position; +import chess.Row; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class KnightTest { + + @DisplayName("나이트가 이동가능한 경로를 구한다.") + @Test + void calculate_knight_can_move_direction() { + Position departure = new Position(Column.A, Row.ONE); + Knight knight = new Knight(Color.BLACK); + Position arrival = new Position(Column.B, Row.THREE); + List canAblePositions = knight.calculateCanMovePosition(departure, arrival); + List expectedPosition = List.of( + new Position(Column.A, Row.TWO), + new Position(Column.B, Row.THREE)); + assertThat(canAblePositions).containsExactlyInAnyOrderElementsOf(expectedPosition); + } + + @DisplayName("나이트가 갈 수 없는 위치라면, 예외를 발생시켜야 한다") + @Test + void when_knight_cannot_go_then_throw_exception() { + Position departure = new Position(Column.A, Row.ONE); + Knight knight = new Knight(Color.BLACK); + Position arrival = new Position(Column.B, Row.ONE); + assertThatThrownBy(() -> knight.calculateCanMovePosition(departure, arrival)); + } +} diff --git a/src/test/java/chess/piece/QueenTest.java b/src/test/java/chess/piece/QueenTest.java new file mode 100644 index 00000000000..6cb6653a834 --- /dev/null +++ b/src/test/java/chess/piece/QueenTest.java @@ -0,0 +1,55 @@ +package chess.piece; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import chess.Color; +import chess.Column; +import chess.Position; +import chess.Row; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class QueenTest { + + @DisplayName("퀸이 이동가능한 경로를 구한다. (상향)") + @Test + void calculate_queen_can_move_direction() { + Position departure = new Position(Column.D, Row.TWO); + Queen queen = new Queen(Color.BLACK); + Position arrival = new Position(Column.D, Row.EIGHT); + List canAblePositions = queen.calculateCanMovePosition(departure, arrival); + + List expectedPosition = List.of( + new Position(Column.D, Row.THREE), + new Position(Column.D, Row.FOUR), + new Position(Column.D, Row.FIVE), + new Position(Column.D, Row.SIX), + new Position(Column.D, Row.SEVEN), + new Position(Column.D, Row.EIGHT)); + assertThat(canAblePositions).containsExactlyInAnyOrderElementsOf(expectedPosition); + } + + @DisplayName("퀸이 이동가능한 경로를 구한다. (우상향)") + @Test + void calculate_king_can_move_direction() { + Position departure = new Position(Column.A, Row.ONE); + Queen queen = new Queen(Color.BLACK); + Position arrival = new Position(Column.C, Row.THREE); + List canAblePositions = queen.calculateCanMovePosition(departure, arrival); + List expectedPosition = List.of( + new Position(Column.B, Row.TWO), + new Position(Column.C, Row.THREE)); + assertThat(canAblePositions).containsExactlyInAnyOrderElementsOf(expectedPosition); + } + + @DisplayName("퀸이 이동 불가능한 좌표라면, 예외를 발생시킨다") + @Test + void when_queen_cannot_move_then_throw_exception() { + Position departure = new Position(Column.D, Row.FOUR); + Queen queen = new Queen(Color.BLACK); + Position arrival = new Position(Column.F, Row.FIVE); + assertThatThrownBy(() -> queen.calculateCanMovePosition(departure, arrival)); + } +} diff --git a/src/test/java/chess/piece/RookTest.java b/src/test/java/chess/piece/RookTest.java new file mode 100644 index 00000000000..ed07389cd69 --- /dev/null +++ b/src/test/java/chess/piece/RookTest.java @@ -0,0 +1,43 @@ +package chess.piece; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import chess.Color; +import chess.Column; +import chess.Position; +import chess.Row; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class RookTest { + + @DisplayName("룩이 이동가능한 경로를 구한다.") + @Test + void calculate_rook_can_move_direction() { + Position departure = new Position(Column.D, Row.TWO); + Rook rook = new Rook(Color.BLACK); + Position arrival = new Position(Column.D, Row.EIGHT); + List canAblePositions = rook.calculateCanMovePosition(departure, arrival); + + List expectedPosition = List.of( + new Position(Column.D, Row.THREE), + new Position(Column.D, Row.FOUR), + new Position(Column.D, Row.FIVE), + new Position(Column.D, Row.SIX), + new Position(Column.D, Row.SEVEN), + new Position(Column.D, Row.EIGHT)); + assertThat(canAblePositions).containsExactlyInAnyOrderElementsOf(expectedPosition); + } + + + @DisplayName("룩이 갈 수 없는 위치라면, 예외를 던져야 한다.") + @Test + void if_bishop_cannot_go_position_then_throw_exception() { + Position departure = new Position(Column.A, Row.ONE); + Rook rook = new Rook(Color.BLACK); + Position arrival = new Position(Column.B, Row.TWO); + assertThatThrownBy(() -> rook.calculateCanMovePosition(departure, arrival)); + } +}