From 890389024281b366435f46e4fbda845127768b71 Mon Sep 17 00:00:00 2001 From: HyeonsuLee Date: Sat, 22 Mar 2025 16:20:56 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=EB=AA=A8=EB=93=A0=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/Board.java | 41 +++++++++++ src/main/java/chess/BoardInitializer.java | 61 +++++++++++++++++ src/main/java/chess/ChessApplication.java | 15 ++++ src/main/java/chess/Column.java | 32 ++++++--- src/main/java/chess/Row.java | 36 +++++++--- .../java/chess/controller/Controller.java | 61 +++++++++++++++++ src/main/java/chess/piece/Bishop.java | 43 +++++++++++- src/main/java/chess/piece/King.java | 47 ++++++++++++- src/main/java/chess/piece/Knight.java | 47 ++++++++++++- src/main/java/chess/piece/Pawn.java | 62 ++++++++++++++++- src/main/java/chess/piece/Piece.java | 37 ++++++++++ src/main/java/chess/piece/Queen.java | 47 ++++++++++++- src/main/java/chess/piece/Rook.java | 43 +++++++++++- .../java/chess/view/CustomStringBuilder.java | 21 ++++++ src/main/java/chess/view/InputView.java | 18 +++++ src/main/java/chess/view/OutputView.java | 46 +++++++++++++ src/test/java/chess/BoardInitializerTest.java | 68 +++++++++++++++++++ src/test/java/chess/BoardTest.java | 53 +++++++++++++++ src/test/java/chess/piece/BishopTest.java | 26 +++++++ src/test/java/chess/piece/KingTest.java | 37 ++++++++++ src/test/java/chess/piece/KnightTest.java | 39 +++++++++++ src/test/java/chess/piece/PawnTest.java | 56 +++++++++++++++ src/test/java/chess/piece/PieceTest.java | 29 ++++++++ src/test/java/chess/piece/QueenTest.java | 28 ++++++++ src/test/java/chess/piece/RookTest.java | 26 +++++++ 25 files changed, 997 insertions(+), 22 deletions(-) create mode 100644 src/main/java/chess/Board.java create mode 100644 src/main/java/chess/BoardInitializer.java create mode 100644 src/main/java/chess/ChessApplication.java create mode 100644 src/main/java/chess/controller/Controller.java create mode 100644 src/main/java/chess/piece/Piece.java create mode 100644 src/main/java/chess/view/CustomStringBuilder.java create mode 100644 src/main/java/chess/view/InputView.java create mode 100644 src/main/java/chess/view/OutputView.java create mode 100644 src/test/java/chess/BoardInitializerTest.java create mode 100644 src/test/java/chess/BoardTest.java create mode 100644 src/test/java/chess/piece/BishopTest.java create mode 100644 src/test/java/chess/piece/KingTest.java create mode 100644 src/test/java/chess/piece/KnightTest.java create mode 100644 src/test/java/chess/piece/PawnTest.java create mode 100644 src/test/java/chess/piece/PieceTest.java create mode 100644 src/test/java/chess/piece/QueenTest.java create mode 100644 src/test/java/chess/piece/RookTest.java diff --git a/src/main/java/chess/Board.java b/src/main/java/chess/Board.java new file mode 100644 index 00000000000..5c11d946727 --- /dev/null +++ b/src/main/java/chess/Board.java @@ -0,0 +1,41 @@ +package chess; + +import chess.piece.Piece; +import java.util.ArrayList; +import java.util.List; + +public class Board { + private final List pieces = new ArrayList<>(); + + public void put(Piece piece) { + pieces.add(piece); + } + + public boolean existSameTeam(Position position, Color color) { + return pieces.stream().anyMatch(piece -> + piece.getPosition().equals(position) && + piece.getColor() == color); + } + + public boolean existPiece(Position position) { + return pieces.stream().anyMatch(piece -> piece.getPosition().equals(position)); + } + + public Piece findPiece(Position position, Color color) { + return pieces.stream() + .filter(piece -> piece.getPosition().equals(position) && piece.getColor() == color) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("움직일 수 없는 기물입니다.")); + } + + public Piece findPiece(Position position) { + return pieces.stream() + .filter(piece -> piece.getPosition().equals(position)) + .findFirst() + .get(); + } + + public void removeByPosition(Position position) { + pieces.removeIf(piece -> piece.getPosition().equals(position)); + } +} diff --git a/src/main/java/chess/BoardInitializer.java b/src/main/java/chess/BoardInitializer.java new file mode 100644 index 00000000000..25d03805290 --- /dev/null +++ b/src/main/java/chess/BoardInitializer.java @@ -0,0 +1,61 @@ +package chess; + +import chess.piece.Bishop; +import chess.piece.King; +import chess.piece.Knight; +import chess.piece.Pawn; +import chess.piece.Queen; +import chess.piece.Rook; +import java.util.Arrays; + +public class BoardInitializer { + + public Board generateBoard() { + Board board = new Board(); +// putPawn(board); + putRook(board); + putKnight(board); + putBishop(board); + putQueen(board); + putKing(board); + return board; + } + + private static void putKing(Board board) { + board.put(new King(new Position(Row.EIGHT, Column.D), board, Color.BLACK)); + board.put(new King(new Position(Row.ONE, Column.D), board, Color.WHITE)); + } + + private static void putQueen(Board board) { + board.put(new Queen(new Position(Row.EIGHT, Column.E), board, Color.BLACK)); + board.put(new Queen(new Position(Row.ONE, Column.E), board, Color.WHITE)); + } + + private static void putBishop(Board board) { + board.put(new Bishop(new Position(Row.EIGHT, Column.C), board, Color.BLACK)); + board.put(new Bishop(new Position(Row.ONE, Column.C), board, Color.WHITE)); + board.put(new Bishop(new Position(Row.EIGHT, Column.F), board, Color.BLACK)); + board.put(new Bishop(new Position(Row.ONE, Column.F), board, Color.WHITE)); + } + + private static void putKnight(Board board) { + board.put(new Knight(new Position(Row.EIGHT, Column.B), board, Color.BLACK)); + board.put(new Knight(new Position(Row.ONE, Column.B), board, Color.WHITE)); + board.put(new Knight(new Position(Row.EIGHT, Column.G), board, Color.BLACK)); + board.put(new Knight(new Position(Row.ONE, Column.G), board, Color.WHITE)); + } + + private static void putRook(Board board) { + board.put(new Rook(new Position(Row.EIGHT, Column.A), board, Color.BLACK)); + board.put(new Rook(new Position(Row.ONE, Column.A), board, Color.WHITE)); + board.put(new Rook(new Position(Row.EIGHT, Column.H), board, Color.BLACK)); + board.put(new Rook(new Position(Row.ONE, Column.H), board, Color.WHITE)); + } + + private void putPawn(Board board) { + Arrays.stream(Column.values()).forEach(column -> { + board.put(new Pawn(new Position(Row.SEVEN, column), board, Color.BLACK)); + board.put(new Pawn(new Position(Row.TWO, column), board, Color.WHITE)); + }); + } +} diff --git a/src/main/java/chess/ChessApplication.java b/src/main/java/chess/ChessApplication.java new file mode 100644 index 00000000000..30924edc1b5 --- /dev/null +++ b/src/main/java/chess/ChessApplication.java @@ -0,0 +1,15 @@ +package chess; + +import chess.controller.Controller; +import chess.view.InputView; +import chess.view.OutputView; + +public class ChessApplication { + + public static void main(String[] args) { + InputView inputView = new InputView(); + OutputView outputView = new OutputView(); + Controller controller = new Controller(inputView, outputView); + controller.run(); + } +} diff --git a/src/main/java/chess/Column.java b/src/main/java/chess/Column.java index b64b4dc77a3..3f8e243a31c 100644 --- a/src/main/java/chess/Column.java +++ b/src/main/java/chess/Column.java @@ -1,15 +1,31 @@ package chess; +import java.util.Arrays; +import javax.lang.model.element.NestingKind; + public enum Column { - A, - B, - C, - D, - E, - F, - G, - H; + A("A"), + B("B"), + C("C"), + D("D"), + E("E"), + F("F"), + G("G"), + H("H"); + + private final String index; + + Column(String index) { + this.index = index; + } + + public static Column from(String index) { + return Arrays.stream(Column.values()) + .filter(column -> column.index.equals(index)) + .findFirst() + .get(); + } public boolean isFarLeft() { return ordinal() == 0; diff --git a/src/main/java/chess/Row.java b/src/main/java/chess/Row.java index 126ed048daa..7965474550d 100644 --- a/src/main/java/chess/Row.java +++ b/src/main/java/chess/Row.java @@ -1,15 +1,35 @@ package chess; +import java.lang.module.FindException; +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 index; + + Row(int index) { + this.index = index; + } + + public static Row from(int index) { + return Arrays.stream(Row.values()) + .filter(row -> row.index == index) + .findFirst() + .get(); + } + + public String getRowName() { + return String.valueOf(index); + } public boolean isTop() { return ordinal() == 0; diff --git a/src/main/java/chess/controller/Controller.java b/src/main/java/chess/controller/Controller.java new file mode 100644 index 00000000000..d42563b15dd --- /dev/null +++ b/src/main/java/chess/controller/Controller.java @@ -0,0 +1,61 @@ +package chess.controller; + +import chess.Board; +import chess.BoardInitializer; +import chess.Color; +import chess.Column; +import chess.Position; +import chess.Row; +import chess.piece.Piece; +import chess.view.InputView; +import chess.view.OutputView; + +public class Controller { + private final InputView inputView; + private final OutputView outputView; + Color turn = Color.BLACK; + + public Controller(InputView inputView, OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + } + + public void run() { + BoardInitializer boardInitializer = new BoardInitializer(); + Board board = boardInitializer.generateBoard(); + retry(() -> processe(board, turn)); + } + + private void processe(Board board, Color turn) { + outputView.printBoard(board); + String command = inputView.inputMoveCommand(turn); + if (command.equals("Q")) { + System.exit(0); + } + String[] positions = command.split(", "); + Position movePiecePosition = parsePosition(positions[0]); + Position targetPosition = parsePosition(positions[1]); + Piece piece = board.findPiece(movePiecePosition, turn); + piece.move(targetPosition); + turn = turn.opposite(); + processe(board, turn); + } + + private Position parsePosition(String position) { + String[] splited = position.split(""); + return new Position( + Row.from(Integer.parseInt(splited[0])), + Column.from(splited[1]) + ); + } + + private void retry(Runnable runnable) { + try { + runnable.run(); + } catch (Exception e) { + System.out.println(e.getMessage()); + retry(runnable); + } + } + +} diff --git a/src/main/java/chess/piece/Bishop.java b/src/main/java/chess/piece/Bishop.java index b14ab70f981..2fcd952dfb8 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.Board; +import chess.Color; +import chess.Movement; +import chess.Position; +import java.util.Deque; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Set; +public class Bishop extends Piece { + + public Bishop(Position position, Board board, Color color) { + super(position, board, color); + } + + @Override + protected Set getMovablePositions() { + Set movablePositions = new HashSet<>(); + Deque queue = new LinkedList(); + queue.add(Movement.LEFT_UP); + queue.add(Movement.RIGHT_UP); + queue.add(Movement.LEFT_DOWN); + queue.add(Movement.RIGHT_DOWN); + while(!queue.isEmpty()) { + Movement movement = queue.poll(); + Position currPosition = getPosition(); + while(currPosition.canMove(movement)) { + currPosition = currPosition.move(movement); + if (!board.existSameTeam(currPosition, getColor())) { + movablePositions.add(currPosition); + } + if (board.existPiece(currPosition)) { + break; + } + } + } + return movablePositions; + } + + @Override + public String toString() { + return "BI"; + } } diff --git a/src/main/java/chess/piece/King.java b/src/main/java/chess/piece/King.java index d64210cad13..401b2162a7b 100644 --- a/src/main/java/chess/piece/King.java +++ b/src/main/java/chess/piece/King.java @@ -1,5 +1,50 @@ package chess.piece; -public class King { +import chess.Board; +import chess.Color; +import chess.Movement; +import chess.Position; +import java.util.Deque; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Set; +import java.util.stream.Collectors; +public class King extends Piece { + + public King(Position position, Board board, Color color) { + super(position, board, color); + } + + @Override + public Set getMovablePositions() { + return getKingMoveablePositions().stream() + .filter(position -> !board.existSameTeam(position, getColor())) + .collect(Collectors.toSet()); + } + + private Set getKingMoveablePositions() { + Deque queue = new LinkedList<>(); + queue.add(Movement.UP); + queue.add(Movement.DOWN); + queue.add(Movement.LEFT); + queue.add(Movement.RIGHT); + queue.add(Movement.LEFT_UP); + queue.add(Movement.RIGHT_UP); + queue.add(Movement.LEFT_DOWN); + queue.add(Movement.RIGHT_DOWN); + Set movablePositions = new HashSet<>(); + while(!queue.isEmpty()) { + Movement movement = queue.poll(); + if (getPosition().canMove(movement)) { + movablePositions.add(getPosition().move(movement)); + } + } + return movablePositions; + } + + @Override + public String toString() { + return "KI"; + } } diff --git a/src/main/java/chess/piece/Knight.java b/src/main/java/chess/piece/Knight.java index 2ee7c47a3bc..bc1decff828 100644 --- a/src/main/java/chess/piece/Knight.java +++ b/src/main/java/chess/piece/Knight.java @@ -1,5 +1,50 @@ package chess.piece; -public class Knight { +import chess.Board; +import chess.Color; +import chess.Movement; +import chess.Position; +import java.util.Deque; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Set; +import java.util.stream.Collectors; +public class Knight extends Piece { + + public Knight(Position position, Board board, Color color) { + super(position, board, color); + } + + @Override + public Set getMovablePositions() { + return getKnightMoveablePositions().stream() + .filter(position -> !board.existSameTeam(position, getColor())) + .collect(Collectors.toSet()); + } + + private Set getKnightMoveablePositions() { + Deque queue = new LinkedList<>(); + queue.add(Movement.UP_UP_LEFT); + queue.add(Movement.UP_UP_RIGHT); + queue.add(Movement.DOWN_DOWN_LEFT); + queue.add(Movement.DOWN_DOWN_RIGHT); + queue.add(Movement.LEFT_LEFT_DOWN); + queue.add(Movement.LEFT_LEFT_UP); + queue.add(Movement.RIGHT_RIGHT_DOWN); + queue.add(Movement.RIGHT_RIGHT_UP); + Set movablePositions = new HashSet<>(); + while(!queue.isEmpty()) { + Movement movement = queue.poll(); + if (getPosition().canMove(movement)) { + movablePositions.add(getPosition().move(movement)); + } + } + return movablePositions; + } + + @Override + public String toString() { + return "KN"; + } } diff --git a/src/main/java/chess/piece/Pawn.java b/src/main/java/chess/piece/Pawn.java index c8b6cafa51e..705315a60bb 100644 --- a/src/main/java/chess/piece/Pawn.java +++ b/src/main/java/chess/piece/Pawn.java @@ -1,5 +1,65 @@ package chess.piece; -public class Pawn { +import chess.Board; +import chess.Color; +import chess.Movement; +import chess.Position; +import java.util.HashSet; +import java.util.Set; +public class Pawn extends Piece { + + boolean isFirstMove = true; + + public Pawn(Position position, Board board, Color color) { + super(position, board, color); + } + + @Override + public void move(Position position) { + super.move(position); + isFirstMove = false; + } + + @Override + public Set getMovablePositions() { + Set movablePositions = new HashSet<>(); + Movement movement = getMovableMovement(); + Position currPosition = getPosition(); + for (int i = 0; i < computeMovableCount(); i++) { + if (!currPosition.canMove(movement)) { + continue; + } + currPosition = currPosition.move(movement); + Color otherTeam = getColor().opposite(); + if (board.existSameTeam(currPosition, otherTeam)) { + movablePositions.add(currPosition); + return movablePositions; + } + if (board.existSameTeam(currPosition, getColor())) { + return movablePositions; + } + movablePositions.add(currPosition); + } + return movablePositions; + } + + private int computeMovableCount () { + if (isFirstMove) { + return 2; + } + return 1; + } + + private Movement getMovableMovement() { + if (getColor().isBlack()) { + return Movement.DOWN; + } + return Movement.UP; + } + + @Override + public String toString() { + return "PA"; + } } diff --git a/src/main/java/chess/piece/Piece.java b/src/main/java/chess/piece/Piece.java new file mode 100644 index 00000000000..3a15878472c --- /dev/null +++ b/src/main/java/chess/piece/Piece.java @@ -0,0 +1,37 @@ +package chess.piece; + +import chess.Board; +import chess.Color; +import chess.Position; +import java.util.Set; + +public abstract class Piece { + protected final Board board; + private Position position; + private final Color color; + + protected Piece(Position position, Board board, Color color) { + this.board = board; + this.position = position; + this.color = color; + } + + public Position getPosition() { + return position; + } + + public Color getColor() { + return color; + } + + public void move(Position position) { + Set positions = getMovablePositions(); + if (!positions.contains(position)) { + throw new IllegalArgumentException("이동할 수 없는 위치입니다."); + } + board.removeByPosition(position); + this.position = position; + } + + protected abstract Set getMovablePositions(); +} diff --git a/src/main/java/chess/piece/Queen.java b/src/main/java/chess/piece/Queen.java index 9b547261c4b..f13358a3991 100644 --- a/src/main/java/chess/piece/Queen.java +++ b/src/main/java/chess/piece/Queen.java @@ -1,5 +1,50 @@ package chess.piece; -public class Queen { +import chess.Board; +import chess.Color; +import chess.Movement; +import chess.Position; +import java.util.Deque; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Set; +public class Queen extends Piece { + + public Queen(Position position, Board board, Color color) { + super(position, board, color); + } + + @Override + protected Set getMovablePositions() { + Set movablePositions = new HashSet<>(); + Deque queue = new LinkedList(); + queue.add(Movement.LEFT); + queue.add(Movement.RIGHT); + queue.add(Movement.UP); + queue.add(Movement.DOWN); + queue.add(Movement.LEFT_UP); + queue.add(Movement.RIGHT_UP); + queue.add(Movement.LEFT_DOWN); + queue.add(Movement.RIGHT_DOWN); + while(!queue.isEmpty()) { + Movement movement = queue.poll(); + Position currPosition = getPosition(); + while(currPosition.canMove(movement)) { + currPosition = currPosition.move(movement); + if (!board.existSameTeam(currPosition, getColor())) { + movablePositions.add(currPosition); + } + if (board.existPiece(currPosition)) { + break; + } + } + } + return movablePositions; + } + + @Override + public String toString() { + return "QU"; + } } diff --git a/src/main/java/chess/piece/Rook.java b/src/main/java/chess/piece/Rook.java index 7ed4d08bf03..8e41d03cb18 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.Board; +import chess.Color; +import chess.Movement; +import chess.Position; +import java.util.Deque; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Set; +public class Rook extends Piece { + + public Rook(Position position, Board board, Color color) { + super(position, board, color); + } + + @Override + protected Set getMovablePositions() { + Set movablePositions = new HashSet<>(); + Deque queue = new LinkedList(); + queue.add(Movement.LEFT); + queue.add(Movement.RIGHT); + queue.add(Movement.UP); + queue.add(Movement.DOWN); + while(!queue.isEmpty()) { + Movement movement = queue.poll(); + Position currPosition = getPosition(); + while(currPosition.canMove(movement)) { + currPosition = currPosition.move(movement); + if (!board.existSameTeam(currPosition, getColor())) { + movablePositions.add(currPosition); + } + if (board.existPiece(currPosition)) { + break; + } + } + } + return movablePositions; + } + + @Override + public String toString() { + return "RO"; + } } diff --git a/src/main/java/chess/view/CustomStringBuilder.java b/src/main/java/chess/view/CustomStringBuilder.java new file mode 100644 index 00000000000..de3e543b02f --- /dev/null +++ b/src/main/java/chess/view/CustomStringBuilder.java @@ -0,0 +1,21 @@ +package chess.view; + +public class CustomStringBuilder { + private final StringBuilder stringBuilder = new StringBuilder(); + + public void appendLine(String content) { + stringBuilder.append(content).append('\n'); + } + + public void append(String content) { + stringBuilder.append(content); + } + + public void print() { + System.out.println(stringBuilder); + } + + public void appendCell(String content) { + stringBuilder.append(content).append(" "); + } +} diff --git a/src/main/java/chess/view/InputView.java b/src/main/java/chess/view/InputView.java new file mode 100644 index 00000000000..101558593ed --- /dev/null +++ b/src/main/java/chess/view/InputView.java @@ -0,0 +1,18 @@ +package chess.view; + +import chess.Color; +import java.util.Scanner; + +public class InputView { + + Scanner scanner = new Scanner(System.in); + + public String inputMoveCommand(Color turn) { + System.out.println(String.format(""" + 현재 턴: %s + 이동시킬 기물의 위치와 목표 위치를 입력해 주세요. (종료Q) + ex) 7A, 6A + """, turn.name())); + return scanner.nextLine(); + } +} diff --git a/src/main/java/chess/view/OutputView.java b/src/main/java/chess/view/OutputView.java new file mode 100644 index 00000000000..e05f3e0c298 --- /dev/null +++ b/src/main/java/chess/view/OutputView.java @@ -0,0 +1,46 @@ +package chess.view; + +import chess.Board; +import chess.Color; +import chess.Column; +import chess.Position; +import chess.Row; +import chess.piece.Piece; + +public class OutputView { + + public static final String black = "\u001B[30m"; + public static final String white = "\u001B[37m"; + public static final String exit = "\u001B[0m"; + + public void printBoard(Board board) { + CustomStringBuilder stringBuilder = new CustomStringBuilder(); + stringBuilder.appendCell(" "); + for (Column column : Column.values()) { + stringBuilder.appendCell(column.name()); + stringBuilder.append(" "); + } + stringBuilder.appendLine(""); + for (Row row : Row.values()) { + stringBuilder.appendCell(row.getRowName()); + for (Column column : Column.values()) { + Position position = new Position(row, column); + if (!board.existPiece(position)) { + stringBuilder.appendCell("- "); + continue; + } + Piece piece = board.findPiece(position); + stringBuilder.appendCell(convertContentColor(piece)); + } + stringBuilder.appendLine(""); + } + stringBuilder.print(); + } + + private String convertContentColor(Piece piece) { + if (piece.getColor() == Color.WHITE) { + return String.format("%s%s%s", white, piece.toString(), exit); + } + return String.format("%s%s%s", black, piece.toString(), exit); + } +} diff --git a/src/test/java/chess/BoardInitializerTest.java b/src/test/java/chess/BoardInitializerTest.java new file mode 100644 index 00000000000..4ccc1f4db85 --- /dev/null +++ b/src/test/java/chess/BoardInitializerTest.java @@ -0,0 +1,68 @@ +package chess; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +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 org.junit.jupiter.api.Test; + +class BoardInitializerTest { + + @Test + void 체스판을_초기화_한다() { + BoardInitializer boardInitializer = new BoardInitializer(); + Board board = boardInitializer.generateBoard(); + assertBlack(board); + assertWhite(board); + } + + private void assertBlack(Board board) { + assertThat(board.findPiece(new Position(Row.EIGHT, Column.A), Color.BLACK)).isInstanceOf(Rook.class); + assertThat(board.findPiece(new Position(Row.EIGHT, Column.B), Color.BLACK)).isInstanceOf(Knight.class); + assertThat(board.findPiece(new Position(Row.EIGHT, Column.C), Color.BLACK)).isInstanceOf(Bishop.class); + assertThat(board.findPiece(new Position(Row.EIGHT, Column.D), Color.BLACK)).isInstanceOf(King.class); + assertThat(board.findPiece(new Position(Row.EIGHT, Column.E), Color.BLACK)).isInstanceOf(Queen.class); + assertThat(board.findPiece(new Position(Row.EIGHT, Column.F), Color.BLACK)).isInstanceOf(Bishop.class); + assertThat(board.findPiece(new Position(Row.EIGHT, Column.G), Color.BLACK)).isInstanceOf(Knight.class); + assertThat(board.findPiece(new Position(Row.EIGHT, Column.H), Color.BLACK)).isInstanceOf(Rook.class); + assertThat(board.findPiece(new Position(Row.EIGHT, Column.H), Color.BLACK)).isInstanceOf(Rook.class); + + assertThat(board.findPiece(new Position(Row.SEVEN, Column.A), Color.BLACK)).isInstanceOf(Pawn.class); + assertThat(board.findPiece(new Position(Row.SEVEN, Column.B), Color.BLACK)).isInstanceOf(Pawn.class); + assertThat(board.findPiece(new Position(Row.SEVEN, Column.C), Color.BLACK)).isInstanceOf(Pawn.class); + assertThat(board.findPiece(new Position(Row.SEVEN, Column.D), Color.BLACK)).isInstanceOf(Pawn.class); + assertThat(board.findPiece(new Position(Row.SEVEN, Column.E), Color.BLACK)).isInstanceOf(Pawn.class); + assertThat(board.findPiece(new Position(Row.SEVEN, Column.F), Color.BLACK)).isInstanceOf(Pawn.class); + assertThat(board.findPiece(new Position(Row.SEVEN, Column.G), Color.BLACK)).isInstanceOf(Pawn.class); + assertThat(board.findPiece(new Position(Row.SEVEN, Column.H), Color.BLACK)).isInstanceOf(Pawn.class); + assertThat(board.findPiece(new Position(Row.SEVEN, Column.H), Color.BLACK)).isInstanceOf(Pawn.class); + } + + private void assertWhite(Board board) { + assertThat(board.findPiece(new Position(Row.ONE, Column.A), Color.WHITE)).isInstanceOf(Rook.class); + assertThat(board.findPiece(new Position(Row.ONE, Column.B), Color.WHITE)).isInstanceOf(Knight.class); + assertThat(board.findPiece(new Position(Row.ONE, Column.C), Color.WHITE)).isInstanceOf(Bishop.class); + assertThat(board.findPiece(new Position(Row.ONE, Column.D), Color.WHITE)).isInstanceOf(King.class); + assertThat(board.findPiece(new Position(Row.ONE, Column.E), Color.WHITE)).isInstanceOf(Queen.class); + assertThat(board.findPiece(new Position(Row.ONE, Column.F), Color.WHITE)).isInstanceOf(Bishop.class); + assertThat(board.findPiece(new Position(Row.ONE, Column.G), Color.WHITE)).isInstanceOf(Knight.class); + assertThat(board.findPiece(new Position(Row.ONE, Column.H), Color.WHITE)).isInstanceOf(Rook.class); + assertThat(board.findPiece(new Position(Row.ONE, Column.H), Color.WHITE)).isInstanceOf(Rook.class); + + assertThat(board.findPiece(new Position(Row.TWO, Column.A), Color.WHITE)).isInstanceOf(Pawn.class); + assertThat(board.findPiece(new Position(Row.TWO, Column.B), Color.WHITE)).isInstanceOf(Pawn.class); + assertThat(board.findPiece(new Position(Row.TWO, Column.C), Color.WHITE)).isInstanceOf(Pawn.class); + assertThat(board.findPiece(new Position(Row.TWO, Column.D), Color.WHITE)).isInstanceOf(Pawn.class); + assertThat(board.findPiece(new Position(Row.TWO, Column.E), Color.WHITE)).isInstanceOf(Pawn.class); + assertThat(board.findPiece(new Position(Row.TWO, Column.F), Color.WHITE)).isInstanceOf(Pawn.class); + assertThat(board.findPiece(new Position(Row.TWO, Column.G), Color.WHITE)).isInstanceOf(Pawn.class); + assertThat(board.findPiece(new Position(Row.TWO, Column.H), Color.WHITE)).isInstanceOf(Pawn.class); + assertThat(board.findPiece(new Position(Row.TWO, Column.H), Color.WHITE)).isInstanceOf(Pawn.class); + } +} diff --git a/src/test/java/chess/BoardTest.java b/src/test/java/chess/BoardTest.java new file mode 100644 index 00000000000..efda798d5e8 --- /dev/null +++ b/src/test/java/chess/BoardTest.java @@ -0,0 +1,53 @@ +package chess; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import chess.piece.Knight; +import chess.piece.Piece; +import org.junit.jupiter.api.Test; + +class BoardTest { + + @Test + void 체스판의_특정_위치에_아군_말이_존재하는지_확인한다() { + Board board = new Board(); + Position position = new Position(Row.SEVEN, Column.C); + board.put(new Knight(position, board, Color.BLACK)); + + assertThat(board.existSameTeam(position, Color.BLACK)).isTrue(); + } + + @Test + void 체스판에서_특정_위치에_있는_특정_팀의_기물을_찾는다() { + Board board = new Board(); + Position position = new Position(Row.SEVEN, Column.C); + board.put(new Knight(position, board, Color.BLACK)); + + Piece piece = board.findPiece(position, Color.BLACK); + + assertThat(piece.getPosition()).isEqualTo(position); + assertThat(piece.getColor()).isEqualTo(Color.BLACK); + } + + @Test + void 자신의_기물이_아닌_것을_움직이면_예외가_발생한다() { + Board board = new Board(); + Position position = new Position(Row.SEVEN, Column.C); + board.put(new Knight(position, board, Color.BLACK)); + + assertThatThrownBy(() -> board.findPiece(position, Color.WHITE)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 특정_위치에_있는_기물을_제거한다() { + Board board = new Board(); + Position position = new Position(Row.SEVEN, Column.C); + board.put(new Knight(position, board, Color.WHITE)); + + board.removeByPosition(position); + + assertThat(board.existPiece(position)).isFalse(); + } +} diff --git a/src/test/java/chess/piece/BishopTest.java b/src/test/java/chess/piece/BishopTest.java new file mode 100644 index 00000000000..6d61ea78d77 --- /dev/null +++ b/src/test/java/chess/piece/BishopTest.java @@ -0,0 +1,26 @@ +package chess.piece; + +import static org.assertj.core.api.Assertions.assertThat; + +import chess.Board; +import chess.Color; +import chess.Column; +import chess.Position; +import chess.Row; +import java.util.Set; +import org.junit.jupiter.api.Test; + +class BishopTest { + + @Test + void 비숍이_이동할_수_있는_위치를_계산한다() { + Board board = new Board(); + board.put(new Knight(new Position(Row.SIX, Column.B), board, Color.WHITE)); + board.put(new Knight(new Position(Row.TWO, Column.F), board, Color.BLACK)); + Piece rook = new Bishop(new Position(Row.FOUR, Column.D), board, Color.WHITE); + + Set positions = rook.getMovablePositions(); + + assertThat(positions).hasSize(10); + } +} diff --git a/src/test/java/chess/piece/KingTest.java b/src/test/java/chess/piece/KingTest.java new file mode 100644 index 00000000000..3f603103b60 --- /dev/null +++ b/src/test/java/chess/piece/KingTest.java @@ -0,0 +1,37 @@ +package chess.piece; + +import static org.assertj.core.api.Assertions.assertThat; + +import chess.Board; +import chess.Color; +import chess.Column; +import chess.Position; +import chess.Row; +import java.util.Set; +import org.junit.jupiter.api.Test; + +class KingTest { + + @Test + void 킹이_이동할_수_있는_위치를_계산한다() { + Board board = new Board(); + board.put(new Knight(new Position(Row.SIX, Column.E), board, Color.WHITE)); + board.put(new Knight(new Position(Row.SIX, Column.F), board, Color.WHITE)); + board.put(new Knight(new Position(Row.SIX, Column.G), board, Color.BLACK)); + Piece king = new King(new Position(Row.FIVE, Column.F), board, Color.WHITE); + + Set positions = king.getMovablePositions(); + + assertThat(positions).hasSize(6); + } + + @Test + void 킹이_뒤로_이동할_수_없는_위치에_있는_경우_이동할_수_있는_위치를_계산한다() { + Board board = new Board(); + Piece king = new King(new Position(Row.ONE, Column.D), board, Color.WHITE); + + Set positions = king.getMovablePositions(); + + assertThat(positions).hasSize(5); + } +} diff --git a/src/test/java/chess/piece/KnightTest.java b/src/test/java/chess/piece/KnightTest.java new file mode 100644 index 00000000000..3b386795cc0 --- /dev/null +++ b/src/test/java/chess/piece/KnightTest.java @@ -0,0 +1,39 @@ +package chess.piece; + +import static org.assertj.core.api.Assertions.assertThat; + +import chess.Board; +import chess.Color; +import chess.Column; +import chess.Position; +import chess.Row; +import java.util.Set; +import org.junit.jupiter.api.Test; + +class KnightTest { + + @Test + void 나이트가_이동할_수_있는_위치를_계산한다() { + Board board = new Board(); + board.put(new Knight(new Position(Row.SEVEN, Column.C), board, Color.WHITE)); + board.put(new Knight(new Position(Row.SEVEN, Column.E), board, Color.WHITE)); + board.put(new Knight(new Position(Row.FOUR, Column.B), board, Color.BLACK)); + Piece knight = new Knight(new Position(Row.FIVE, Column.D), board, Color.WHITE); + + Set positions = knight.getMovablePositions(); + + assertThat(positions).hasSize(6); + } + + @Test + void 나이트가_앞으로_이동할_수_없는_위치에_있는_경우_이동할_수_있는_위치를_계산한다() { + Board board = new Board(); + board.put(new Knight(new Position(Row.SIX, Column.B), board, Color.WHITE)); + board.put(new Knight(new Position(Row.SIX, Column.B), board, Color.BLACK)); + Piece knight = new Knight(new Position(Row.SEVEN, Column.D), board, Color.WHITE); + + Set positions = knight.getMovablePositions(); + + assertThat(positions).hasSize(5); + } +} diff --git a/src/test/java/chess/piece/PawnTest.java b/src/test/java/chess/piece/PawnTest.java new file mode 100644 index 00000000000..07fda3fdb1f --- /dev/null +++ b/src/test/java/chess/piece/PawnTest.java @@ -0,0 +1,56 @@ +package chess.piece; + +import static org.assertj.core.api.Assertions.assertThat; + +import chess.Board; +import chess.Color; +import chess.Column; +import chess.Position; +import chess.Row; +import java.util.Set; +import org.junit.jupiter.api.Test; + +class PawnTest { + + @Test + void 폰이_처음_이동할_수_있는_위치를_계산한다() { + Board board = new Board(); + Piece pawn = new Pawn(new Position(Row.SEVEN, Column.G), board, Color.BLACK); + + Set positions = pawn.getMovablePositions(); + + assertThat(positions).hasSize(2); + } + + @Test + void 폰의_이동이_처음이_아니면_한_칸만_이동할_수_있다() { + Board board = new Board(); + Piece pawn = new Pawn(new Position(Row.SEVEN, Column.G), board, Color.BLACK); + pawn.move(new Position(Row.EIGHT, Column.G)); + + Set positions = pawn.getMovablePositions(); + + assertThat(positions).hasSize(1); + } + + @Test + void 폰_앞에_우리팀_기물이_있으면_두_칸을_움직일_수_없다() { + Board board = new Board(); + board.put(new Knight(new Position(Row.SIX, Column.G), board, Color.WHITE)); + Piece pawn = new Pawn(new Position(Row.SEVEN, Column.G), board, Color.BLACK); + + Set positions = pawn.getMovablePositions(); + + assertThat(positions).hasSize(1); + } + + @Test + void 폰이_끝까지_가면_갈_곳이_없다() { + Board board = new Board(); + Piece pawn = new Pawn(new Position(Row.ONE, Column.D), board, Color.BLACK); + + Set positions = pawn.getMovablePositions(); + + assertThat(positions).isEmpty(); + } +} diff --git a/src/test/java/chess/piece/PieceTest.java b/src/test/java/chess/piece/PieceTest.java new file mode 100644 index 00000000000..4bb5e1e595c --- /dev/null +++ b/src/test/java/chess/piece/PieceTest.java @@ -0,0 +1,29 @@ +package chess.piece; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import chess.Board; +import chess.Color; +import chess.Column; +import chess.Position; +import chess.Row; +import java.util.Set; +import org.junit.jupiter.api.Test; + +class PieceTest { + + @Test + void 기물을_특정_위치로_움직인다() { + Board board = new Board(); + Position position = new Position(Row.FIVE, Column.D); + board.put(new Knight(position, board, Color.BLACK)); + + Piece piece = board.findPiece(position, Color.BLACK); + Position targetPosition = new Position(Row.SEVEN, Column.C); + piece.move(targetPosition); + + assertThat(piece.getPosition()).isEqualTo(targetPosition); + } +} diff --git a/src/test/java/chess/piece/QueenTest.java b/src/test/java/chess/piece/QueenTest.java new file mode 100644 index 00000000000..0dc02cb7a64 --- /dev/null +++ b/src/test/java/chess/piece/QueenTest.java @@ -0,0 +1,28 @@ +package chess.piece; + +import static org.assertj.core.api.Assertions.assertThat; + +import chess.Board; +import chess.Color; +import chess.Column; +import chess.Position; +import chess.Row; +import java.util.Set; +import org.junit.jupiter.api.Test; + +class QueenTest { + + @Test + void 퀸이_이동할_수_있는_위치를_계산한다() { + Board board = new Board(); + board.put(new Knight(new Position(Row.SIX, Column.B), board, Color.WHITE)); + board.put(new Knight(new Position(Row.TWO, Column.F), board, Color.BLACK)); + board.put(new Knight(new Position(Row.FOUR, Column.G), board, Color.WHITE)); + board.put(new Knight(new Position(Row.FOUR, Column.B), board, Color.BLACK)); + Piece rook = new Queen(new Position(Row.FOUR, Column.D), board, Color.WHITE); + + Set positions = rook.getMovablePositions(); + + assertThat(positions).hasSize(21); + } +} diff --git a/src/test/java/chess/piece/RookTest.java b/src/test/java/chess/piece/RookTest.java new file mode 100644 index 00000000000..4e707f8f026 --- /dev/null +++ b/src/test/java/chess/piece/RookTest.java @@ -0,0 +1,26 @@ +package chess.piece; + +import static org.assertj.core.api.Assertions.assertThat; + +import chess.Board; +import chess.Color; +import chess.Column; +import chess.Position; +import chess.Row; +import java.util.Set; +import org.junit.jupiter.api.Test; + +class RookTest { + + @Test + void 룩이_이동할_수_있는_위치를_계산한다() { + Board board = new Board(); + board.put(new Knight(new Position(Row.FIVE, Column.G), board, Color.WHITE)); + board.put(new Knight(new Position(Row.FIVE, Column.B), board, Color.BLACK)); + Piece rook = new Rook(new Position(Row.FIVE, Column.D), board, Color.WHITE); + + Set positions = rook.getMovablePositions(); + + assertThat(positions).hasSize(11); + } +} From 9ebc56c379b859e6590b5a8d9c32470f8358440d Mon Sep 17 00:00:00 2001 From: HyeonsuLee Date: Sat, 22 Mar 2025 17:26:44 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=EA=B8=B0=EB=AC=BC=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=84=B0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/BoardInitializer.java | 2 +- src/main/java/chess/Movement.java | 8 +++++ src/main/java/chess/piece/Bishop.java | 35 +++++++++----------- src/main/java/chess/piece/King.java | 34 +++++++------------- src/main/java/chess/piece/Pawn.java | 30 +++++++++++------ src/main/java/chess/piece/Queen.java | 39 +++++++++-------------- src/main/java/chess/piece/Rook.java | 35 +++++++++----------- src/test/java/chess/piece/PawnTest.java | 14 +++++++- 8 files changed, 98 insertions(+), 99 deletions(-) diff --git a/src/main/java/chess/BoardInitializer.java b/src/main/java/chess/BoardInitializer.java index 25d03805290..7704b7910ba 100644 --- a/src/main/java/chess/BoardInitializer.java +++ b/src/main/java/chess/BoardInitializer.java @@ -12,7 +12,7 @@ public class BoardInitializer { public Board generateBoard() { Board board = new Board(); -// putPawn(board); + putPawn(board); putRook(board); putKnight(board); putBishop(board); diff --git a/src/main/java/chess/Movement.java b/src/main/java/chess/Movement.java index e57c6e91bb9..abc92c6fb77 100644 --- a/src/main/java/chess/Movement.java +++ b/src/main/java/chess/Movement.java @@ -45,4 +45,12 @@ public boolean isVertical() { public boolean isDiagonal() { return x != 0 && y != 0 && Math.abs(x) == Math.abs(y); } + + public boolean isStraightOneStep() { + return (x == 0 && Math.abs(y) == 1) || (y == 0 && Math.abs(x) == 1); + } + + public boolean isCrossOneStep() { + return Math.abs(x) + Math.abs(y) == 2 && Math.abs(x) == 1 && Math.abs(y) == 1; + } } diff --git a/src/main/java/chess/piece/Bishop.java b/src/main/java/chess/piece/Bishop.java index 2fcd952dfb8..a10f38c912e 100644 --- a/src/main/java/chess/piece/Bishop.java +++ b/src/main/java/chess/piece/Bishop.java @@ -4,9 +4,8 @@ import chess.Color; import chess.Movement; import chess.Position; -import java.util.Deque; +import java.util.Arrays; import java.util.HashSet; -import java.util.LinkedList; import java.util.Set; public class Bishop extends Piece { @@ -18,24 +17,20 @@ public Bishop(Position position, Board board, Color color) { @Override protected Set getMovablePositions() { Set movablePositions = new HashSet<>(); - Deque queue = new LinkedList(); - queue.add(Movement.LEFT_UP); - queue.add(Movement.RIGHT_UP); - queue.add(Movement.LEFT_DOWN); - queue.add(Movement.RIGHT_DOWN); - while(!queue.isEmpty()) { - Movement movement = queue.poll(); - Position currPosition = getPosition(); - while(currPosition.canMove(movement)) { - currPosition = currPosition.move(movement); - if (!board.existSameTeam(currPosition, getColor())) { - movablePositions.add(currPosition); - } - if (board.existPiece(currPosition)) { - break; - } - } - } + Arrays.stream(Movement.values()) + .filter(Movement::isCrossOneStep) + .forEach(movement -> { + Position currPosition = getPosition(); + while(currPosition.canMove(movement)) { + currPosition = currPosition.move(movement); + if (!board.existSameTeam(currPosition, getColor())) { + movablePositions.add(currPosition); + } + if (board.existPiece(currPosition)) { + break; + } + } + }); return movablePositions; } diff --git a/src/main/java/chess/piece/King.java b/src/main/java/chess/piece/King.java index 401b2162a7b..58472a83e90 100644 --- a/src/main/java/chess/piece/King.java +++ b/src/main/java/chess/piece/King.java @@ -4,9 +4,7 @@ import chess.Color; import chess.Movement; import chess.Position; -import java.util.Deque; -import java.util.HashSet; -import java.util.LinkedList; +import java.util.Arrays; import java.util.Set; import java.util.stream.Collectors; @@ -18,29 +16,19 @@ public King(Position position, Board board, Color color) { @Override public Set getMovablePositions() { - return getKingMoveablePositions().stream() - .filter(position -> !board.existSameTeam(position, getColor())) + return Arrays.stream(Movement.values()) + .filter(this::isOneStepMovement) + .filter(movement -> canMove(movement, getPosition())) + .map(getPosition()::move) .collect(Collectors.toSet()); } - private Set getKingMoveablePositions() { - Deque queue = new LinkedList<>(); - queue.add(Movement.UP); - queue.add(Movement.DOWN); - queue.add(Movement.LEFT); - queue.add(Movement.RIGHT); - queue.add(Movement.LEFT_UP); - queue.add(Movement.RIGHT_UP); - queue.add(Movement.LEFT_DOWN); - queue.add(Movement.RIGHT_DOWN); - Set movablePositions = new HashSet<>(); - while(!queue.isEmpty()) { - Movement movement = queue.poll(); - if (getPosition().canMove(movement)) { - movablePositions.add(getPosition().move(movement)); - } - } - return movablePositions; + private boolean canMove(Movement movement, Position currentPosition) { + return currentPosition.canMove(movement) && !board.existSameTeam(currentPosition.move(movement), getColor()); + } + + private boolean isOneStepMovement(Movement movement) { + return movement.isCrossOneStep() || movement.isStraightOneStep(); } @Override diff --git a/src/main/java/chess/piece/Pawn.java b/src/main/java/chess/piece/Pawn.java index 705315a60bb..589feae03ab 100644 --- a/src/main/java/chess/piece/Pawn.java +++ b/src/main/java/chess/piece/Pawn.java @@ -25,26 +25,36 @@ public void move(Position position) { public Set getMovablePositions() { Set movablePositions = new HashSet<>(); Movement movement = getMovableMovement(); - Position currPosition = getPosition(); + Position currPosition = getPosition(); for (int i = 0; i < computeMovableCount(); i++) { if (!currPosition.canMove(movement)) { continue; } currPosition = currPosition.move(movement); - Color otherTeam = getColor().opposite(); - if (board.existSameTeam(currPosition, otherTeam)) { - movablePositions.add(currPosition); - return movablePositions; - } - if (board.existSameTeam(currPosition, getColor())) { - return movablePositions; - } + if (currPosition.canMove(Movement.LEFT) && i == 0 && + board.existSameTeam(currPosition.move(Movement.LEFT), getColor().opposite()) + ) { + movablePositions.add(currPosition.move(Movement.LEFT)); + } + if (currPosition.canMove(Movement.RIGHT) && i == 0 && + board.existSameTeam(currPosition.move(Movement.LEFT), getColor().opposite()) + ) { + movablePositions.add(currPosition.move(Movement.LEFT)); + } + Color otherTeam = getColor().opposite(); + if (board.existSameTeam(currPosition, otherTeam)) { + movablePositions.add(currPosition); + return movablePositions; + } + if (board.existSameTeam(currPosition, getColor())) { + return movablePositions; + } movablePositions.add(currPosition); } return movablePositions; } - private int computeMovableCount () { + private int computeMovableCount() { if (isFirstMove) { return 2; } diff --git a/src/main/java/chess/piece/Queen.java b/src/main/java/chess/piece/Queen.java index f13358a3991..88705bdfe8b 100644 --- a/src/main/java/chess/piece/Queen.java +++ b/src/main/java/chess/piece/Queen.java @@ -4,9 +4,8 @@ import chess.Color; import chess.Movement; import chess.Position; -import java.util.Deque; +import java.util.Arrays; import java.util.HashSet; -import java.util.LinkedList; import java.util.Set; public class Queen extends Piece { @@ -18,28 +17,20 @@ public Queen(Position position, Board board, Color color) { @Override protected Set getMovablePositions() { Set movablePositions = new HashSet<>(); - Deque queue = new LinkedList(); - queue.add(Movement.LEFT); - queue.add(Movement.RIGHT); - queue.add(Movement.UP); - queue.add(Movement.DOWN); - queue.add(Movement.LEFT_UP); - queue.add(Movement.RIGHT_UP); - queue.add(Movement.LEFT_DOWN); - queue.add(Movement.RIGHT_DOWN); - while(!queue.isEmpty()) { - Movement movement = queue.poll(); - Position currPosition = getPosition(); - while(currPosition.canMove(movement)) { - currPosition = currPosition.move(movement); - if (!board.existSameTeam(currPosition, getColor())) { - movablePositions.add(currPosition); - } - if (board.existPiece(currPosition)) { - break; - } - } - } + Arrays.stream(Movement.values()) + .filter(movement -> movement.isCrossOneStep() || movement.isStraightOneStep()) + .forEach(movement -> { + Position currPosition = getPosition(); + while(currPosition.canMove(movement)) { + currPosition = currPosition.move(movement); + if (!board.existSameTeam(currPosition, getColor())) { + movablePositions.add(currPosition); + } + if (board.existPiece(currPosition)) { + break; + } + } + }); return movablePositions; } diff --git a/src/main/java/chess/piece/Rook.java b/src/main/java/chess/piece/Rook.java index 8e41d03cb18..be5590f5856 100644 --- a/src/main/java/chess/piece/Rook.java +++ b/src/main/java/chess/piece/Rook.java @@ -4,9 +4,8 @@ import chess.Color; import chess.Movement; import chess.Position; -import java.util.Deque; +import java.util.Arrays; import java.util.HashSet; -import java.util.LinkedList; import java.util.Set; public class Rook extends Piece { @@ -18,24 +17,20 @@ public Rook(Position position, Board board, Color color) { @Override protected Set getMovablePositions() { Set movablePositions = new HashSet<>(); - Deque queue = new LinkedList(); - queue.add(Movement.LEFT); - queue.add(Movement.RIGHT); - queue.add(Movement.UP); - queue.add(Movement.DOWN); - while(!queue.isEmpty()) { - Movement movement = queue.poll(); - Position currPosition = getPosition(); - while(currPosition.canMove(movement)) { - currPosition = currPosition.move(movement); - if (!board.existSameTeam(currPosition, getColor())) { - movablePositions.add(currPosition); - } - if (board.existPiece(currPosition)) { - break; - } - } - } + Arrays.stream(Movement.values()) + .filter(Movement::isStraightOneStep) + .forEach(movement -> { + Position currPosition = getPosition(); + while(currPosition.canMove(movement)) { + currPosition = currPosition.move(movement); + if (!board.existSameTeam(currPosition, getColor())) { + movablePositions.add(currPosition); + } + if (board.existPiece(currPosition)) { + break; + } + } + }); return movablePositions; } diff --git a/src/test/java/chess/piece/PawnTest.java b/src/test/java/chess/piece/PawnTest.java index 07fda3fdb1f..d65feccc046 100644 --- a/src/test/java/chess/piece/PawnTest.java +++ b/src/test/java/chess/piece/PawnTest.java @@ -26,7 +26,7 @@ class PawnTest { void 폰의_이동이_처음이_아니면_한_칸만_이동할_수_있다() { Board board = new Board(); Piece pawn = new Pawn(new Position(Row.SEVEN, Column.G), board, Color.BLACK); - pawn.move(new Position(Row.EIGHT, Column.G)); + pawn.move(new Position(Row.SIX, Column.G)); Set positions = pawn.getMovablePositions(); @@ -44,6 +44,18 @@ class PawnTest { assertThat(positions).hasSize(1); } + @Test + void 폰의_대각선에_상대_기물이_있으면_이동할_수_있다() { + Board board = new Board(); + board.put(new Knight(new Position(Row.FOUR, Column.F), board, Color.WHITE)); + Piece pawn = new Pawn(new Position(Row.FIVE, Column.G), board, Color.BLACK); + + Set positions = pawn.getMovablePositions(); + + assertThat(positions).hasSize(3); + } + + @Test void 폰이_끝까지_가면_갈_곳이_없다() { Board board = new Board(); From 311bae3668a8cb88ec444d2bdfa2ab1b029537cd Mon Sep 17 00:00:00 2001 From: HyeonsuLee Date: Sat, 22 Mar 2025 17:30:29 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20=EB=82=98=EC=9D=B4=ED=8A=B8=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=84=B0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/Movement.java | 4 ++++ src/main/java/chess/piece/Knight.java | 30 +++++++-------------------- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/src/main/java/chess/Movement.java b/src/main/java/chess/Movement.java index abc92c6fb77..f8362daf328 100644 --- a/src/main/java/chess/Movement.java +++ b/src/main/java/chess/Movement.java @@ -53,4 +53,8 @@ public boolean isStraightOneStep() { public boolean isCrossOneStep() { return Math.abs(x) + Math.abs(y) == 2 && Math.abs(x) == 1 && Math.abs(y) == 1; } + + public boolean isMoveThreeStep() { + return Math.abs(x) + Math.abs(y) == 3; + } } diff --git a/src/main/java/chess/piece/Knight.java b/src/main/java/chess/piece/Knight.java index bc1decff828..faf38e49f8d 100644 --- a/src/main/java/chess/piece/Knight.java +++ b/src/main/java/chess/piece/Knight.java @@ -4,9 +4,7 @@ import chess.Color; import chess.Movement; import chess.Position; -import java.util.Deque; -import java.util.HashSet; -import java.util.LinkedList; +import java.util.Arrays; import java.util.Set; import java.util.stream.Collectors; @@ -18,29 +16,15 @@ public Knight(Position position, Board board, Color color) { @Override public Set getMovablePositions() { - return getKnightMoveablePositions().stream() - .filter(position -> !board.existSameTeam(position, getColor())) + return Arrays.stream(Movement.values()) + .filter(Movement::isMoveThreeStep) + .filter(movement -> canMove(movement, getPosition())) + .map(getPosition()::move) .collect(Collectors.toSet()); } - private Set getKnightMoveablePositions() { - Deque queue = new LinkedList<>(); - queue.add(Movement.UP_UP_LEFT); - queue.add(Movement.UP_UP_RIGHT); - queue.add(Movement.DOWN_DOWN_LEFT); - queue.add(Movement.DOWN_DOWN_RIGHT); - queue.add(Movement.LEFT_LEFT_DOWN); - queue.add(Movement.LEFT_LEFT_UP); - queue.add(Movement.RIGHT_RIGHT_DOWN); - queue.add(Movement.RIGHT_RIGHT_UP); - Set movablePositions = new HashSet<>(); - while(!queue.isEmpty()) { - Movement movement = queue.poll(); - if (getPosition().canMove(movement)) { - movablePositions.add(getPosition().move(movement)); - } - } - return movablePositions; + private boolean canMove(Movement movement, Position currentPosition) { + return currentPosition.canMove(movement) && !board.existSameTeam(currentPosition.move(movement), getColor()); } @Override