diff --git a/src/main/java/chess/ChessBoard.java b/src/main/java/chess/ChessBoard.java new file mode 100644 index 0000000000..8e821dd02c --- /dev/null +++ b/src/main/java/chess/ChessBoard.java @@ -0,0 +1,102 @@ +package chess; + +import chess.piece.Bishop; +import chess.piece.BlackPawn; +import chess.piece.King; +import chess.piece.Knight; +import chess.piece.Piece; +import chess.piece.Queen; +import chess.piece.Rook; +import chess.piece.WhitePawn; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class ChessBoard { + + private static final List INITIAL_PIECES = List.of( + new Rook(Color.BLACK, new Position(Column.A, Row.EIGHT)), + new Knight(Color.BLACK, new Position(Column.B, Row.EIGHT)), + new Bishop(Color.BLACK, new Position(Column.C, Row.EIGHT)), + new Queen(Color.BLACK, new Position(Column.D, Row.EIGHT)), + new King(Color.BLACK, new Position(Column.E, Row.EIGHT)), + new Bishop(Color.BLACK, new Position(Column.F, Row.EIGHT)), + new Knight(Color.BLACK, new Position(Column.G, Row.EIGHT)), + new Rook(Color.BLACK, new Position(Column.H, Row.EIGHT)), + new BlackPawn(new Position(Column.A, Row.SEVEN)), + new BlackPawn(new Position(Column.B, Row.SEVEN)), + new BlackPawn(new Position(Column.C, Row.SEVEN)), + new BlackPawn(new Position(Column.D, Row.SEVEN)), + new BlackPawn(new Position(Column.E, Row.SEVEN)), + new BlackPawn(new Position(Column.F, Row.SEVEN)), + new BlackPawn(new Position(Column.G, Row.SEVEN)), + new BlackPawn(new Position(Column.H, Row.SEVEN)), + + new Rook(Color.WHITE, new Position(Column.A, Row.ONE)), + new Knight(Color.WHITE, new Position(Column.B, Row.ONE)), + new Bishop(Color.WHITE, new Position(Column.C, Row.ONE)), + new Queen(Color.WHITE, new Position(Column.D, Row.ONE)), + new King(Color.WHITE, new Position(Column.E, Row.ONE)), + new Bishop(Color.WHITE, new Position(Column.F, Row.ONE)), + new Knight(Color.WHITE, new Position(Column.G, Row.ONE)), + new Rook(Color.WHITE, new Position(Column.H, Row.ONE)), + new WhitePawn(new Position(Column.A, Row.TWO)), + new WhitePawn(new Position(Column.B, Row.TWO)), + new WhitePawn(new Position(Column.C, Row.TWO)), + new WhitePawn(new Position(Column.D, Row.TWO)), + new WhitePawn(new Position(Column.E, Row.TWO)), + new WhitePawn(new Position(Column.F, Row.TWO)), + new WhitePawn(new Position(Column.G, Row.TWO)), + new WhitePawn(new Position(Column.H, Row.TWO)) + ); + + private List pieces; + + public ChessBoard(List pieces) { + this.pieces = pieces; + } + + public static ChessBoard initialize() { + return new ChessBoard(new ArrayList<>(INITIAL_PIECES)); + } + + public void move(Color color, Position from, Position to) { + if (isNotExistPiece(from)) { + throw new IllegalArgumentException("출발지에 기물이 없습니다."); + } + findPiece(from).move(this, color, to); + } + + public boolean isExistPiece(Position position) { + return pieces.stream() + .anyMatch(piece -> piece.isPosition(position)); + } + + public boolean isNotExistPiece(Position position) { + return !isExistPiece(position); + } + + public boolean isColorInPosition(Color color, Position position) { + if (isNotExistPiece(position)) { + return false; + } + return findPiece(position).isColor(color); + } + + public Piece findPiece(Position position) { + return pieces.stream() + .filter(piece -> piece.isPosition(position)) + .findFirst() + .orElse(null); + } + + public List getPieces() { + return Collections.unmodifiableList(pieces); + } + + public void remove(Position position) { + pieces = pieces.stream() + .filter(piece -> !piece.isPosition(position)) + .toList(); + } +} diff --git a/src/main/java/chess/ChessGame.java b/src/main/java/chess/ChessGame.java new file mode 100644 index 0000000000..5c41f8d974 --- /dev/null +++ b/src/main/java/chess/ChessGame.java @@ -0,0 +1,65 @@ +package chess; + +import chess.piece.Piece; +import java.util.Scanner; + +public class ChessGame { + + private static final Scanner scanner = new Scanner(System.in); + private static final Color START_COLOR = Color.WHITE; + + public static void main(String[] args) { + ChessGame chessGame = new ChessGame(); + chessGame.play(); + } + + public void play() { + System.out.println("게임을 시작합니다."); + ChessBoard chessBoard = ChessBoard.initialize(); + printChessBoard(chessBoard); + + Color currentTurnColor = START_COLOR; + while (true) { + System.out.println(currentTurnColor + "의 차례입니다. 기물을 이동하세요 ex) a1 a2"); + + String[] commands = readLine().split(" "); + Position from = toPosition(commands[0]); + Position to = toPosition(commands[1]); + chessBoard.move(currentTurnColor, from, to); + printChessBoard(chessBoard); + currentTurnColor = currentTurnColor.opposite(); + } + } + + private void printChessBoard(ChessBoard chessBoard) { + StringBuilder sb = new StringBuilder(); + for (int rowSymbol = 8; rowSymbol > 0; rowSymbol--) { + Row row = Row.fromSymbol(rowSymbol); + sb.append(row.getSymbol()).append(" "); + for (char col = 'A'; col <= 'H'; col++) { + Column column = Column.valueOf(col + ""); + Position position = new Position(row, column); + Piece piece = chessBoard.findPiece(position); + if (piece == null) { + sb.append(". "); + continue; + } + sb.append(piece).append(" "); + } + sb.append("\n"); + } + sb.append(" ").append("a b c d e f g h"); + + System.out.println(sb); + } + + private String readLine() { + return scanner.nextLine().trim(); + } + + private Position toPosition(String command) { + Column column = Column.valueOf(Character.toString(command.charAt(0)).toUpperCase()); + Row row = Row.fromSymbol(command.charAt(1) - '0'); + return new Position(column, row); + } +} diff --git a/src/main/java/chess/Color.java b/src/main/java/chess/Color.java index 55cd020b68..03d6e45e9e 100644 --- a/src/main/java/chess/Color.java +++ b/src/main/java/chess/Color.java @@ -6,6 +6,7 @@ public enum Color { WHITE, EMPTY; + public boolean isWhite() { return this == WHITE; } diff --git a/src/main/java/chess/Position.java b/src/main/java/chess/Position.java index 3ebeb0ea18..cfcd9630a3 100644 --- a/src/main/java/chess/Position.java +++ b/src/main/java/chess/Position.java @@ -167,4 +167,8 @@ public Position moveHorizontal(final int step) { } return this; } + + public boolean isRow(Row row) { + return this.row == row; + } } diff --git a/src/main/java/chess/Row.java b/src/main/java/chess/Row.java index 126ed048da..391a948c4d 100644 --- a/src/main/java/chess/Row.java +++ b/src/main/java/chess/Row.java @@ -1,15 +1,30 @@ package chess; +import java.util.Arrays; + public enum Row { - EIGHT, - SEVEN, - SIX, - FIVE, - FOUR, - THREE, - TWO, - ONE; + EIGHT(8), + SEVEN(7), + SIX(6), + FIVE(5), + FOUR(4), + THREE(3), + TWO(2), + ONE(1); + + private final int symbol; + + Row(int symbol) { + this.symbol = symbol; + } + + public static Row fromSymbol(int symbol) { + return Arrays.stream(values()) + .filter(row -> row.symbol == symbol) + .findFirst() + .orElseThrow(IllegalArgumentException::new); + } public boolean isTop() { return ordinal() == 0; @@ -50,4 +65,8 @@ public Row moveDown(final int step) { throw new IllegalStateException("움직일 수 없는 위치입니다."); } + + public int getSymbol() { + return symbol; + } } diff --git a/src/main/java/chess/piece/Bishop.java b/src/main/java/chess/piece/Bishop.java index b14ab70f98..93bcfcf975 100644 --- a/src/main/java/chess/piece/Bishop.java +++ b/src/main/java/chess/piece/Bishop.java @@ -1,5 +1,46 @@ package chess.piece; -public class Bishop { +import chess.ChessBoard; +import chess.Color; +import chess.Movement; +import chess.Position; +import java.util.List; +public class Bishop extends Piece { + + private static final List MOVEMENTS = List.of( + Movement.LEFT_UP, Movement.LEFT_DOWN, Movement.RIGHT_UP, Movement.RIGHT_DOWN + ); + + public Bishop(Color color, Position position) { + super(color, position); + } + + @Override + protected boolean isMovable(ChessBoard chessBoard, Position to) { + for (Movement movement : MOVEMENTS) { + Position curr = position; + while (!curr.equals(to)) { + if (!curr.canMove(movement)) { + break; + } + curr = curr.move(movement); + if (chessBoard.isExistPiece(curr)) { + break; + } + } + if (curr.equals(to)) { + return true; + } + } + return false; + } + + @Override + public String toString() { + if (isColor(Color.BLACK)) { + return "b"; + } + return "B"; + } } diff --git a/src/main/java/chess/piece/BlackPawn.java b/src/main/java/chess/piece/BlackPawn.java new file mode 100644 index 0000000000..83b5da19e8 --- /dev/null +++ b/src/main/java/chess/piece/BlackPawn.java @@ -0,0 +1,42 @@ +package chess.piece; + +import chess.ChessBoard; +import chess.Color; +import chess.Movement; +import chess.Position; +import chess.Row; +import java.util.Set; + +public class BlackPawn extends Pawn { + + private static final Row INITINAL_ROW = Row.SEVEN; + + public BlackPawn(Position position) { + super(Color.BLACK, position); + } + + @Override + protected boolean isAttack(ChessBoard chessBoard, Position to) { + return chessBoard.isColorInPosition(Color.WHITE, to); + } + + @Override + protected boolean isFirstMovement() { + return position.isRow(INITINAL_ROW); + } + + @Override + protected Set attackMovements() { + return Set.of(Movement.LEFT_DOWN, Movement.RIGHT_DOWN); + } + + @Override + protected Movement movement() { + return Movement.DOWN; + } + + @Override + public String toString() { + return "p"; + } +} diff --git a/src/main/java/chess/piece/King.java b/src/main/java/chess/piece/King.java index d64210cad1..bcd3ca342a 100644 --- a/src/main/java/chess/piece/King.java +++ b/src/main/java/chess/piece/King.java @@ -1,5 +1,42 @@ package chess.piece; -public class King { +import chess.ChessBoard; +import chess.Color; +import chess.Movement; +import chess.Position; +import java.util.Set; +public class King extends Piece { + + private static final Set MOVEMENTS = Set.of( + Movement.UP, Movement.DOWN, Movement.LEFT, Movement.RIGHT, + Movement.LEFT_UP, Movement.LEFT_DOWN, Movement.RIGHT_UP, Movement.RIGHT_DOWN + ); + + public King(Color color, Position position) { + super(color, position); + } + + @Override + protected boolean isMovable(ChessBoard chessBoard, Position to) { + for (Movement movement : MOVEMENTS) { + Position curr = position; + if (!curr.canMove(movement)) { + continue; + } + curr = curr.move(movement); + if (curr.equals(to)) { + return true; + } + } + return false; + } + + @Override + public String toString() { + if (isColor(Color.BLACK)) { + return "k"; + } + return "K"; + } } diff --git a/src/main/java/chess/piece/Knight.java b/src/main/java/chess/piece/Knight.java index 2ee7c47a3b..8adfa62e07 100644 --- a/src/main/java/chess/piece/Knight.java +++ b/src/main/java/chess/piece/Knight.java @@ -1,5 +1,44 @@ package chess.piece; -public class Knight { +import chess.ChessBoard; +import chess.Color; +import chess.Movement; +import chess.Position; +import java.util.Set; +public class Knight extends Piece { + + private static final Set MOVEMENTS = Set.of( + Movement.UP_UP_LEFT, Movement.UP_UP_RIGHT, + Movement.LEFT_LEFT_DOWN, Movement.LEFT_LEFT_UP, + Movement.RIGHT_RIGHT_DOWN, Movement.RIGHT_RIGHT_UP, + Movement.DOWN_DOWN_LEFT, Movement.DOWN_DOWN_RIGHT + ); + + public Knight(Color color, Position position) { + super(color, position); + } + + @Override + protected boolean isMovable(ChessBoard chessBoard, Position to) { + for (Movement movement : MOVEMENTS) { + Position curr = position; + if (!curr.canMove(movement)) { + continue; + } + curr = curr.move(movement); + if (curr.equals(to)) { + return true; + } + } + return false; + } + + @Override + public String toString() { + if (isColor(Color.BLACK)) { + return "n"; + } + return "N"; + } } diff --git a/src/main/java/chess/piece/Pawn.java b/src/main/java/chess/piece/Pawn.java index c8b6cafa51..a135651083 100644 --- a/src/main/java/chess/piece/Pawn.java +++ b/src/main/java/chess/piece/Pawn.java @@ -1,5 +1,59 @@ package chess.piece; -public class Pawn { +import chess.ChessBoard; +import chess.Color; +import chess.Movement; +import chess.Position; +import java.util.Set; +public abstract class Pawn extends Piece { + + public Pawn(Color color, Position position) { + super(color, position); + } + + protected boolean isMovable(ChessBoard chessBoard, Position to) { + if (isAttack(chessBoard, to)) { + for (Movement movement : attackMovements()) { + Position curr = position; + if (!curr.canMove(movement)) { + continue; + } + curr = curr.move(movement); + if (curr.equals(to)) { + return true; + } + } + return false; + } + if (chessBoard.isExistPiece(to)) { + return false; + } + if (isFirstMovement()) { + Position curr = position; + for (int cnt = 0; cnt < 2; cnt++) { + if (!curr.canMove(movement())) { + break; + } + curr = curr.move(movement()); + if (chessBoard.isExistPiece(curr)) { + break; + } + if (curr.equals(to)) { + return true; + } + } + return curr.equals(to); + } + return position.canMove(movement()) && + position.move(movement()).equals(to); + } + + abstract protected boolean isAttack(ChessBoard chessBoard, Position to); + + abstract protected boolean isFirstMovement(); + + abstract protected Set attackMovements(); + + abstract protected Movement movement(); } diff --git a/src/main/java/chess/piece/Piece.java b/src/main/java/chess/piece/Piece.java new file mode 100644 index 0000000000..262e255b0b --- /dev/null +++ b/src/main/java/chess/piece/Piece.java @@ -0,0 +1,63 @@ +package chess.piece; + +import chess.ChessBoard; +import chess.Color; +import chess.Position; +import java.util.Objects; + +public abstract class Piece { + + private final Color color; + protected Position position; + + public Piece(Color color, Position position) { + this.color = color; + this.position = position; + } + + public void move(ChessBoard chessBoard, Color color, Position to) { + if (!isColor(color)) { + throw new IllegalArgumentException("자기팀의 기물이 아닙니다."); + } + if (chessBoard.isColorInPosition(color, to)) { + throw new IllegalArgumentException("목적지에 같은 팀의 기물이 있습니다."); + } + if (!isMovable(chessBoard, to)) { + throw new IllegalArgumentException("해당 목적지로 갈 수 없습니다."); + } + if (chessBoard.isExistPiece(to)) { + chessBoard.remove(to); + } + position = to; + } + + public boolean isColor(Color color) { + return this.color == color; + } + + public boolean isPosition(Position position) { + return this.position.equals(position); + } + + abstract protected boolean isMovable(ChessBoard chessBoard, Position to); + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + + Piece piece = (Piece) object; + return color == piece.color && Objects.equals(position, piece.position); + } + + @Override + public int hashCode() { + int result = Objects.hashCode(color); + result = 31 * result + Objects.hashCode(position); + return result; + } +} diff --git a/src/main/java/chess/piece/Queen.java b/src/main/java/chess/piece/Queen.java index 9b547261c4..d814a37ea1 100644 --- a/src/main/java/chess/piece/Queen.java +++ b/src/main/java/chess/piece/Queen.java @@ -1,5 +1,47 @@ package chess.piece; -public class Queen { +import chess.ChessBoard; +import chess.Color; +import chess.Movement; +import chess.Position; +import java.util.Set; +public class Queen extends Piece { + + private static final Set MOVEMENTS = Set.of( + Movement.UP, Movement.DOWN, Movement.LEFT, Movement.RIGHT, + Movement.LEFT_UP, Movement.LEFT_DOWN, Movement.RIGHT_UP, Movement.RIGHT_DOWN + ); + + public Queen(Color color, Position position) { + super(color, position); + } + + @Override + protected boolean isMovable(ChessBoard chessBoard, Position to) { + for (Movement movement : MOVEMENTS) { + Position curr = position; + while (!curr.equals(to)) { + if (!curr.canMove(movement)) { + break; + } + curr = curr.move(movement); + if (chessBoard.isExistPiece(curr)) { + break; + } + } + if (curr.equals(to)) { + return true; + } + } + return false; + } + + @Override + public String toString() { + if (isColor(Color.BLACK)) { + return "q"; + } + return "Q"; + } } diff --git a/src/main/java/chess/piece/Rook.java b/src/main/java/chess/piece/Rook.java index 7ed4d08bf0..6d93243459 100644 --- a/src/main/java/chess/piece/Rook.java +++ b/src/main/java/chess/piece/Rook.java @@ -1,5 +1,46 @@ package chess.piece; -public class Rook { +import chess.ChessBoard; +import chess.Color; +import chess.Movement; +import chess.Position; +import java.util.Set; +public class Rook extends Piece { + + private static final Set MOVEMENTS = Set.of( + Movement.UP, Movement.DOWN, Movement.LEFT, Movement.RIGHT + ); + + public Rook(Color color, Position position) { + super(color, position); + } + + @Override + protected boolean isMovable(ChessBoard chessBoard, Position to) { + for (Movement movement : MOVEMENTS) { + Position curr = position; + while (!curr.equals(to)) { + if (!curr.canMove(movement)) { + break; + } + curr = curr.move(movement); + if (chessBoard.isExistPiece(curr)) { + break; + } + } + if (curr.equals(to)) { + return true; + } + } + return false; + } + + @Override + public String toString() { + if (isColor(Color.BLACK)) { + return "r"; + } + return "R"; + } } diff --git a/src/main/java/chess/piece/WhitePawn.java b/src/main/java/chess/piece/WhitePawn.java new file mode 100644 index 0000000000..42f563237a --- /dev/null +++ b/src/main/java/chess/piece/WhitePawn.java @@ -0,0 +1,42 @@ +package chess.piece; + +import chess.ChessBoard; +import chess.Color; +import chess.Movement; +import chess.Position; +import chess.Row; +import java.util.Set; + +public class WhitePawn extends Pawn { + + private static final Row INITINAL_ROW = Row.TWO; + + public WhitePawn(Position position) { + super(Color.WHITE, position); + } + + @Override + protected boolean isAttack(ChessBoard chessBoard, Position to) { + return chessBoard.isColorInPosition(Color.BLACK, to); + } + + @Override + protected boolean isFirstMovement() { + return position.isRow(INITINAL_ROW); + } + + @Override + protected Set attackMovements() { + return Set.of(Movement.LEFT_UP, Movement.RIGHT_UP); + } + + @Override + protected Movement movement() { + return Movement.UP; + } + + @Override + public String toString() { + return "P"; + } +} diff --git a/src/test/java/chess/piece/BishopTest.java b/src/test/java/chess/piece/BishopTest.java new file mode 100644 index 0000000000..3982bffb52 --- /dev/null +++ b/src/test/java/chess/piece/BishopTest.java @@ -0,0 +1,58 @@ +package chess.piece; + +import static chess.Fixtures.B1; +import static chess.Fixtures.C2; +import static chess.Fixtures.D3; +import static org.assertj.core.api.Assertions.assertThat; + +import chess.ChessBoard; +import chess.Color; +import chess.Fixtures; +import chess.Position; +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class BishopTest { + + @ParameterizedTest + @MethodSource("provideMovablePosition") + void 비숍은_대각선으로_보드판_끝까지_갈_수_있다(Position from, Position to) { + //given + ChessBoard chessBoard = new ChessBoard(List.of()); + Bishop bishop = new Bishop(Color.BLACK, from); + + //when + boolean movable = bishop.isMovable(chessBoard, to); + + //then + assertThat(movable).isTrue(); + } + + @Test + void 비숍이_기는_방향에_기물이_있다면_갈_수_없다() { + //given + ChessBoard chessBoard = new ChessBoard(List.of( + new BlackPawn(C2) + )); + Bishop bishop = new Bishop(Color.BLACK, B1); + + //when + boolean movable = bishop.isMovable(chessBoard, D3); + + //then + assertThat(movable).isFalse(); + } + + private static Stream provideMovablePosition() { + return Stream.of( + Arguments.of(Fixtures.A1, Fixtures.H8), + Arguments.of(Fixtures.B2, Fixtures.A3), + Arguments.of(Fixtures.D2, Fixtures.C1), + Arguments.of(Fixtures.E7, Fixtures.F6) + ); + } +} diff --git a/src/test/java/chess/piece/BlackPawnTest.java b/src/test/java/chess/piece/BlackPawnTest.java new file mode 100644 index 0000000000..d440f826c5 --- /dev/null +++ b/src/test/java/chess/piece/BlackPawnTest.java @@ -0,0 +1,85 @@ +package chess.piece; + +import static chess.Fixtures.B5; +import static chess.Fixtures.D4; +import static chess.Fixtures.H4; +import static chess.Fixtures.H5; +import static org.assertj.core.api.Assertions.assertThat; + +import chess.ChessBoard; +import chess.Color; +import chess.Fixtures; +import java.util.List; +import org.junit.jupiter.api.Test; + +class BlackPawnTest { + + @Test + void 블랙_폰은_아래로_한칸_이동할_수_있다() { + //given + BlackPawn blackPawn = new BlackPawn(H5); + + //when + boolean movable = blackPawn.isMovable(new ChessBoard(List.of()), H4); + + //then + assertThat(movable).isTrue(); + } + + @Test + void 블랙_폰은_초기에_아래로_두칸_이동할_수_있다() { + //given + BlackPawn blackPawn = new BlackPawn(Fixtures.H7); + + //when + boolean movable = blackPawn.isMovable(new ChessBoard(List.of()), H5); + + //then + assertThat(movable).isTrue(); + } + + @Test + void 블랙_폰은_아래_대각선에_상대_기물이_있다면_대각선으로_이동할_수_있다() { + //given + ChessBoard chessBoard = new ChessBoard(List.of( + new Rook(Color.WHITE, Fixtures.D4) + )); + BlackPawn blackPawn = new BlackPawn(Fixtures.E5); + + //when + boolean movable = blackPawn.isMovable(chessBoard, D4); + + //then + assertThat(movable).isTrue(); + } + + @Test + void 블랙_폰은_공격이_아닌_이동일때_목적지까지_가는데_기물이_있다면_이동할_수_없다() { + //given + ChessBoard chessBoard = new ChessBoard(List.of( + new Rook(Color.WHITE, Fixtures.B6) + )); + BlackPawn blackPawn = new BlackPawn(Fixtures.B7); + + //when + boolean movable = blackPawn.isMovable(chessBoard, B5); + + //then + assertThat(movable).isFalse(); + } + + @Test + void 블랙_폰은_공격이_아닌_이동일때_목적지에_기물이_있다면_이동할_수_없다() { + //given + ChessBoard chessBoard = new ChessBoard(List.of( + new Rook(Color.WHITE, Fixtures.B5) + )); + BlackPawn blackPawn = new BlackPawn(Fixtures.B6); + + //when + boolean movable = blackPawn.isMovable(chessBoard, B5); + + //then + assertThat(movable).isFalse(); + } +} diff --git a/src/test/java/chess/piece/KingTest.java b/src/test/java/chess/piece/KingTest.java new file mode 100644 index 0000000000..84008f9dcf --- /dev/null +++ b/src/test/java/chess/piece/KingTest.java @@ -0,0 +1,58 @@ +package chess.piece; + +import chess.ChessBoard; +import chess.Color; +import chess.Column; +import chess.Fixtures; +import chess.Position; +import chess.Row; +import java.util.List; +import java.util.stream.Stream; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class KingTest { + + @ParameterizedTest + @MethodSource("provideMovablePosition") + void 킹은_상_하_좌_우_대각선_한칸_같은팀의_기물이_없다면_이동할_수_있다(Position from, Position to) { + //given + ChessBoard chessBoard = new ChessBoard(List.of()); + King king = new King(Color.BLACK, from); + + //when + boolean result = king.isMovable(chessBoard, to); + + //then + Assertions.assertThat(result).isTrue(); + } + + @Test + void 킹은_상_하_좌_우_한칸이_아닌_다른곳으로_이동할_수_없다() { + //given + ChessBoard chessBoard = new ChessBoard(List.of()); + King king = new King(Color.BLACK, new Position(Column.B, Row.FIVE)); + + //when + boolean result = king.isMovable(chessBoard, new Position(Column.A, Row.THREE)); + + //then + Assertions.assertThat(result).isFalse(); + } + + private static Stream provideMovablePosition() { + return Stream.of( + Arguments.of(Fixtures.A1, Fixtures.A2), + Arguments.of(Fixtures.B2, Fixtures.B1), + Arguments.of(Fixtures.B1, Fixtures.C1), + Arguments.of(Fixtures.C2, Fixtures.B2), + Arguments.of(Fixtures.C2, Fixtures.D3), + Arguments.of(Fixtures.C2, Fixtures.B2), + Arguments.of(Fixtures.C2, Fixtures.B1), + Arguments.of(Fixtures.C2, Fixtures.D1) + ); + } +} diff --git a/src/test/java/chess/piece/KnightTest.java b/src/test/java/chess/piece/KnightTest.java new file mode 100644 index 0000000000..7ec44a62c7 --- /dev/null +++ b/src/test/java/chess/piece/KnightTest.java @@ -0,0 +1,60 @@ +package chess.piece; + +import static chess.Fixtures.A1; +import static chess.Fixtures.A4; +import static chess.Fixtures.B1; +import static chess.Fixtures.B2; +import static chess.Fixtures.C2; +import static chess.Fixtures.C3; +import static org.assertj.core.api.Assertions.assertThat; + +import chess.ChessBoard; +import chess.Color; +import chess.Position; +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class KnightTest { + + @ParameterizedTest + @MethodSource("provideMovablePosition") + void 나이트는_상하좌우_한칸_후_대각선_모든_방향으로_갈_수_있다(Position from, Position to) { + //given + ChessBoard chessBoard = new ChessBoard(List.of()); + Knight knight = new Knight(Color.BLACK, from); + + //when + boolean movable = knight.isMovable(chessBoard, to); + + //then + assertThat(movable).isTrue(); + } + + @Test + void 나이트가_가는방향에_기물이_있더라도_갈_수_있다() { + //given + ChessBoard chessBoard = new ChessBoard(List.of( + new BlackPawn(C2) + )); + Knight knight = new Knight(Color.BLACK, A1); + + //when + boolean movable = knight.isMovable(chessBoard, C2); + + //then + assertThat(movable).isTrue(); + } + + private static Stream provideMovablePosition() { + return Stream.of( + Arguments.of(A1, C2), + Arguments.of(B2, A4), + Arguments.of(C3, B1), + Arguments.of(B1, C3) + ); + } +} diff --git a/src/test/java/chess/piece/QueenTest.java b/src/test/java/chess/piece/QueenTest.java new file mode 100644 index 0000000000..e208ee990b --- /dev/null +++ b/src/test/java/chess/piece/QueenTest.java @@ -0,0 +1,71 @@ +package chess.piece; + +import static chess.Fixtures.A1; +import static chess.Fixtures.A8; +import static chess.Fixtures.B1; +import static chess.Fixtures.B2; +import static chess.Fixtures.B4; +import static chess.Fixtures.B8; +import static chess.Fixtures.C1; +import static chess.Fixtures.C2; +import static chess.Fixtures.C3; +import static chess.Fixtures.D3; +import static chess.Fixtures.H2; +import static org.assertj.core.api.Assertions.assertThat; + +import chess.ChessBoard; +import chess.Color; +import chess.Fixtures; +import chess.Position; +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class QueenTest { + + @ParameterizedTest + @MethodSource("provideMovablePosition") + void 퀸은_상하좌우_또는_대각선으로_보드판_끝까지_갈_수_있다(Position from, Position to) { + //given + ChessBoard chessBoard = new ChessBoard(List.of()); + Queen queen = new Queen(Color.BLACK, from); + + //when + boolean movable = queen.isMovable(chessBoard, to); + + //then + assertThat(movable).isTrue(); + } + + @Test + void 퀸이_기는_방향에_기물이_있다면_갈_수_없다() { + //given + ChessBoard chessBoard = new ChessBoard(List.of( + new BlackPawn(C2) + )); + Queen queen = new Queen(Color.BLACK, B1); + + //when + boolean movable = queen.isMovable(chessBoard, D3); + + //then + assertThat(movable).isFalse(); + } + + private static Stream provideMovablePosition() { + return Stream.of( + Arguments.of(Fixtures.A1, Fixtures.H8), + Arguments.of(Fixtures.B2, Fixtures.A3), + Arguments.of(Fixtures.D2, Fixtures.C1), + Arguments.of(Fixtures.E7, Fixtures.F6), + Arguments.of(A1, A8), + Arguments.of(B2, H2), + Arguments.of(C3, C1), + Arguments.of(B8, B1), + Arguments.of(B8, B4) + ); + } +} diff --git a/src/test/java/chess/piece/RookTest.java b/src/test/java/chess/piece/RookTest.java new file mode 100644 index 0000000000..e3d9ec4e96 --- /dev/null +++ b/src/test/java/chess/piece/RookTest.java @@ -0,0 +1,64 @@ +package chess.piece; + +import static chess.Fixtures.A1; +import static chess.Fixtures.A8; +import static chess.Fixtures.B1; +import static chess.Fixtures.B2; +import static chess.Fixtures.B4; +import static chess.Fixtures.B8; +import static chess.Fixtures.C1; +import static chess.Fixtures.C3; +import static chess.Fixtures.H2; +import static org.assertj.core.api.Assertions.assertThat; + +import chess.ChessBoard; +import chess.Color; +import chess.Position; +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class RookTest { + + @ParameterizedTest + @MethodSource("provideMovablePosition") + void 룩은_상하좌우_보드_끝까지_갈_수_있다(Position from, Position to) { + //given + ChessBoard chessBoard = new ChessBoard(List.of()); + Rook rook = new Rook(Color.BLACK, from); + + //when + boolean movable = rook.isMovable(chessBoard, to); + + //then + assertThat(movable).isTrue(); + } + + @Test + void 룩이_기는_방향에_기물이_있다면_갈_수_없다() { + //given + ChessBoard chessBoard = new ChessBoard(List.of( + new BlackPawn(B2) + )); + Rook rook = new Rook(Color.BLACK, B1); + + //when + boolean movable = rook.isMovable(chessBoard, B4); + + //then + assertThat(movable).isFalse(); + } + + private static Stream provideMovablePosition() { + return Stream.of( + Arguments.of(A1, A8), + Arguments.of(B2, H2), + Arguments.of(C3, C1), + Arguments.of(B8, B1), + Arguments.of(B8, B4) + ); + } +} diff --git a/src/test/java/chess/piece/WhitePawnTest.java b/src/test/java/chess/piece/WhitePawnTest.java new file mode 100644 index 0000000000..a462a55bcf --- /dev/null +++ b/src/test/java/chess/piece/WhitePawnTest.java @@ -0,0 +1,91 @@ +package chess.piece; + +import static chess.Fixtures.B2; +import static chess.Fixtures.B3; +import static chess.Fixtures.B4; +import static chess.Fixtures.B6; +import static chess.Fixtures.B7; +import static chess.Fixtures.D6; +import static chess.Fixtures.E5; +import static chess.Fixtures.H2; +import static chess.Fixtures.H4; +import static chess.Fixtures.H5; +import static chess.Fixtures.H6; +import static org.assertj.core.api.Assertions.assertThat; + +import chess.ChessBoard; +import chess.Color; +import java.util.List; +import org.junit.jupiter.api.Test; + +class WhitePawnTest { + + @Test + void 화이트_폰은_아래로_한칸_이동할_수_있다() { + //given + WhitePawn whitePawn = new WhitePawn(H5); + + //when + boolean movable = whitePawn.isMovable(new ChessBoard(List.of()), H6); + + //then + assertThat(movable).isTrue(); + } + + @Test + void 화이트_폰은_초기에_아래로_두칸_이동할_수_있다() { + //given + WhitePawn whitePawn = new WhitePawn(H2); + + //when + boolean movable = whitePawn.isMovable(new ChessBoard(List.of()), H4); + + //then + assertThat(movable).isTrue(); + } + + @Test + void 화이트_폰은_아래_대각선에_상대_기물이_있다면_대각선으로_이동할_수_있다() { + //given + ChessBoard chessBoard = new ChessBoard(List.of( + new Rook(Color.BLACK, D6) + )); + WhitePawn whitePawn = new WhitePawn(E5); + + //when + boolean movable = whitePawn.isMovable(chessBoard, D6); + + //then + assertThat(movable).isTrue(); + } + + @Test + void 화이트_폰은_공격이_아닌_이동일때_목적지까지_가는데_기물이_있다면_이동할_수_없다() { + //given + ChessBoard chessBoard = new ChessBoard(List.of( + new Rook(Color.WHITE, B3) + )); + WhitePawn whitePawn = new WhitePawn(B2); + + //when + boolean movable = whitePawn.isMovable(chessBoard, B4); + + //then + assertThat(movable).isFalse(); + } + + @Test + void 화이트_폰은_공격이_아닌_이동일때_목적지에_기물이_있다면_이동할_수_없다() { + //given + ChessBoard chessBoard = new ChessBoard(List.of( + new Rook(Color.WHITE, B7) + )); + WhitePawn whitePawn = new WhitePawn(B6); + + //when + boolean movable = whitePawn.isMovable(chessBoard, B7); + + //then + assertThat(movable).isFalse(); + } +}