From 094ce51f8cd0df314b48c224e0d041753450ba62 Mon Sep 17 00:00:00 2001 From: CheChe903 Date: Sat, 22 Mar 2025 19:29:35 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat=20:=20=EC=B2=B4=EC=8A=A4=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/Application.java | 17 ++ src/main/java/chess/ChessInitializer.java | 73 +++++++++ .../chess/Controller/ChessController.java | 37 +++++ .../MoveStrategy/DefaultMoveStrategy.java | 27 ++++ .../java/chess/MoveStrategy/MoveStrategy.java | 11 ++ .../chess/MoveStrategy/PawnMoveStrategy.java | 39 +++++ .../MoveStrategy/SpecialMoveStrategy.java | 29 ++++ src/main/java/chess/domain/Board.java | 44 +++++ .../java/chess/{ => domain}/Movement.java | 2 +- src/main/java/chess/domain/Pieces.java | 73 +++++++++ src/main/java/chess/domain/Turn.java | 30 ++++ src/main/java/chess/domain/piece/Bishop.java | 41 +++++ .../java/chess/{ => domain/piece}/Color.java | 2 +- .../java/chess/{ => domain/piece}/Column.java | 33 +++- src/main/java/chess/domain/piece/King.java | 38 +++++ src/main/java/chess/domain/piece/Knight.java | 48 ++++++ src/main/java/chess/domain/piece/Pawn.java | 63 ++++++++ src/main/java/chess/domain/piece/Piece.java | 52 ++++++ .../chess/{ => domain/piece}/Position.java | 19 ++- src/main/java/chess/domain/piece/Queen.java | 43 +++++ src/main/java/chess/domain/piece/Rook.java | 43 +++++ .../java/chess/{ => domain/piece}/Row.java | 31 +++- src/main/java/chess/piece/Bishop.java | 5 - src/main/java/chess/piece/King.java | 5 - src/main/java/chess/piece/Knight.java | 5 - src/main/java/chess/piece/Pawn.java | 5 - src/main/java/chess/piece/Queen.java | 5 - src/main/java/chess/piece/Rook.java | 5 - src/main/java/chess/view/InputView.java | 24 +++ src/main/java/chess/view/OutputView.java | 150 ++++++++++++++++++ src/test/java/chess/ColumnTest.java | 1 + src/test/java/chess/Fixtures.java | 4 + src/test/java/chess/PositionTest.java | 4 +- src/test/java/chess/RowTest.java | 1 + .../java/chess/domain/piece/BishopTest.java | 43 +++++ 35 files changed, 1016 insertions(+), 36 deletions(-) create mode 100644 src/main/java/chess/Application.java create mode 100644 src/main/java/chess/ChessInitializer.java create mode 100644 src/main/java/chess/Controller/ChessController.java create mode 100644 src/main/java/chess/MoveStrategy/DefaultMoveStrategy.java create mode 100644 src/main/java/chess/MoveStrategy/MoveStrategy.java create mode 100644 src/main/java/chess/MoveStrategy/PawnMoveStrategy.java create mode 100644 src/main/java/chess/MoveStrategy/SpecialMoveStrategy.java create mode 100644 src/main/java/chess/domain/Board.java rename src/main/java/chess/{ => domain}/Movement.java (97%) create mode 100644 src/main/java/chess/domain/Pieces.java create mode 100644 src/main/java/chess/domain/Turn.java create mode 100644 src/main/java/chess/domain/piece/Bishop.java rename src/main/java/chess/{ => domain/piece}/Color.java (93%) rename src/main/java/chess/{ => domain/piece}/Column.java (59%) create mode 100644 src/main/java/chess/domain/piece/King.java create mode 100644 src/main/java/chess/domain/piece/Knight.java create mode 100644 src/main/java/chess/domain/piece/Pawn.java create mode 100644 src/main/java/chess/domain/piece/Piece.java rename src/main/java/chess/{ => domain/piece}/Position.java (89%) create mode 100644 src/main/java/chess/domain/piece/Queen.java create mode 100644 src/main/java/chess/domain/piece/Rook.java rename src/main/java/chess/{ => domain/piece}/Row.java (58%) delete mode 100644 src/main/java/chess/piece/Bishop.java delete mode 100644 src/main/java/chess/piece/King.java delete mode 100644 src/main/java/chess/piece/Knight.java delete mode 100644 src/main/java/chess/piece/Pawn.java delete mode 100644 src/main/java/chess/piece/Queen.java delete mode 100644 src/main/java/chess/piece/Rook.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/domain/piece/BishopTest.java diff --git a/src/main/java/chess/Application.java b/src/main/java/chess/Application.java new file mode 100644 index 00000000000..7466b062b2b --- /dev/null +++ b/src/main/java/chess/Application.java @@ -0,0 +1,17 @@ +package chess; + +import chess.Controller.ChessController; +import chess.view.InputView; +import chess.view.OutputView; + +public class Application { + + public static void main(String[] args) { + + InputView inputView = new InputView(); + OutputView outputView = new OutputView(); + + ChessController chessController = new ChessController(inputView, outputView); + chessController.run(); + } +} diff --git a/src/main/java/chess/ChessInitializer.java b/src/main/java/chess/ChessInitializer.java new file mode 100644 index 00000000000..78f69213d44 --- /dev/null +++ b/src/main/java/chess/ChessInitializer.java @@ -0,0 +1,73 @@ +package chess; + +import static chess.domain.piece.Color.BLACK; +import static chess.domain.piece.Color.WHITE; +import static chess.domain.piece.Column.A; +import static chess.domain.piece.Column.B; +import static chess.domain.piece.Column.C; +import static chess.domain.piece.Column.D; +import static chess.domain.piece.Column.E; +import static chess.domain.piece.Column.F; +import static chess.domain.piece.Column.G; +import static chess.domain.piece.Column.H; +import static chess.domain.piece.Row.EIGHT; +import static chess.domain.piece.Row.ONE; +import static chess.domain.piece.Row.SEVEN; +import static chess.domain.piece.Row.TWO; + +import chess.domain.piece.Bishop; +import chess.domain.piece.King; +import chess.domain.piece.Knight; +import chess.domain.piece.Pawn; +import chess.domain.piece.Piece; +import chess.domain.piece.Position; +import chess.domain.piece.Queen; +import chess.domain.piece.Rook; +import java.util.HashSet; +import java.util.Set; + +public class ChessInitializer { + + public static Set initialize() { + Set pieces = new HashSet<>(); + + pieces.add(new Rook(WHITE, new Position(A, ONE))); + pieces.add(new Knight(WHITE, new Position(B, ONE))); + pieces.add(new Bishop(WHITE, new Position(C, ONE))); + pieces.add(new Queen(WHITE, new Position(D, ONE))); + pieces.add(new King(WHITE, new Position(E, ONE))); + pieces.add(new Bishop(WHITE, new Position(F, ONE))); + pieces.add(new Knight(WHITE, new Position(G, ONE))); + pieces.add(new Rook(WHITE, new Position(H, ONE))); + + pieces.add(new Pawn(WHITE, new Position(A, TWO))); + pieces.add(new Pawn(WHITE, new Position(B, TWO))); + pieces.add(new Pawn(WHITE, new Position(C, TWO))); + pieces.add(new Pawn(WHITE, new Position(D, TWO))); + pieces.add(new Pawn(WHITE, new Position(E, TWO))); + pieces.add(new Pawn(WHITE, new Position(F, TWO))); + pieces.add(new Pawn(WHITE, new Position(G, TWO))); + pieces.add(new Pawn(WHITE, new Position(H, TWO))); + + pieces.add(new Rook(BLACK, new Position(A, EIGHT))); + pieces.add(new Knight(BLACK, new Position(B, EIGHT))); + pieces.add(new Bishop(BLACK, new Position(C, EIGHT))); + pieces.add(new Queen(BLACK, new Position(D, EIGHT))); + pieces.add(new King(BLACK, new Position(E, EIGHT))); + pieces.add(new Bishop(BLACK, new Position(F, EIGHT))); + pieces.add(new Knight(BLACK, new Position(G, EIGHT))); + pieces.add(new Rook(BLACK, new Position(H, EIGHT))); + + pieces.add(new Pawn(BLACK, new Position(A, SEVEN))); + pieces.add(new Pawn(BLACK, new Position(B, SEVEN))); + pieces.add(new Pawn(BLACK, new Position(C, SEVEN))); + pieces.add(new Pawn(BLACK, new Position(D, SEVEN))); + pieces.add(new Pawn(BLACK, new Position(E, SEVEN))); + pieces.add(new Pawn(BLACK, new Position(F, SEVEN))); + pieces.add(new Pawn(BLACK, new Position(G, SEVEN))); + pieces.add(new Pawn(BLACK, new Position(H, SEVEN))); + + return pieces; + } + +} diff --git a/src/main/java/chess/Controller/ChessController.java b/src/main/java/chess/Controller/ChessController.java new file mode 100644 index 00000000000..ff2c26399cc --- /dev/null +++ b/src/main/java/chess/Controller/ChessController.java @@ -0,0 +1,37 @@ +package chess.Controller; + +import chess.domain.Board; +import chess.view.InputView; +import chess.view.OutputView; +import java.util.List; + +public class ChessController { + + private final InputView inputView; + private final OutputView outputView; + + public ChessController(final InputView inputView, final OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + } + + public void run() { + Board board = new Board(); + + while (true) { + try { + outputView.printChessBoard(board); + outputView.printTurn(board.getTurn()); + + List pieceInput = inputView.inputMovePiece(); + List positionInput = inputView.inputMovePosition(); + board.movePiece(pieceInput, positionInput); + + board.changeTurn(); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + + } + } +} diff --git a/src/main/java/chess/MoveStrategy/DefaultMoveStrategy.java b/src/main/java/chess/MoveStrategy/DefaultMoveStrategy.java new file mode 100644 index 00000000000..ffb307ae615 --- /dev/null +++ b/src/main/java/chess/MoveStrategy/DefaultMoveStrategy.java @@ -0,0 +1,27 @@ +package chess.MoveStrategy; + +import chess.domain.Movement; +import chess.domain.piece.Position; +import java.util.ArrayList; +import java.util.List; + +public class DefaultMoveStrategy implements MoveStrategy { + + @Override + public List canMove(final Position startPosition, final Position endPosition, List canMove, + final boolean firstMove) { + + List positions = new ArrayList<>(); + for (Movement movement : canMove) { + positions.clear(); + if (startPosition.canMove(movement)) { + Position nextPosition = startPosition.move(movement); + positions.add(nextPosition); + if (nextPosition.equals(endPosition)) { + return positions; + } + } + } + throw new IllegalArgumentException("갈 수 없는 위치입니다."); + } +} diff --git a/src/main/java/chess/MoveStrategy/MoveStrategy.java b/src/main/java/chess/MoveStrategy/MoveStrategy.java new file mode 100644 index 00000000000..6a635c5e9fd --- /dev/null +++ b/src/main/java/chess/MoveStrategy/MoveStrategy.java @@ -0,0 +1,11 @@ +package chess.MoveStrategy; + +import chess.domain.Movement; +import chess.domain.piece.Position; +import java.util.List; + +public interface MoveStrategy { + + List canMove(Position startPosition, Position endPosition, List canMove, + final boolean firstMove); +} diff --git a/src/main/java/chess/MoveStrategy/PawnMoveStrategy.java b/src/main/java/chess/MoveStrategy/PawnMoveStrategy.java new file mode 100644 index 00000000000..527e551ed1e --- /dev/null +++ b/src/main/java/chess/MoveStrategy/PawnMoveStrategy.java @@ -0,0 +1,39 @@ +package chess.MoveStrategy; + +import static chess.domain.Movement.UP_UP; + +import chess.domain.Movement; +import chess.domain.piece.Position; +import java.util.ArrayList; +import java.util.List; + +public class PawnMoveStrategy implements MoveStrategy { + + @Override + public List canMove(final Position startPosition, final Position endPosition, + final List canMove, + final boolean firstMove) { + + List positions = new ArrayList<>(); + for (Movement movement : canMove) { + positions.clear(); + if (movement == UP_UP && firstMove) { + if (startPosition.canMove(movement)) { + Position nextPosition = startPosition.move(movement); + positions.add(nextPosition); + if (nextPosition.equals(endPosition)) { + return positions; + } + } + } else if (startPosition.canMove(movement)) { + Position nextPosition = startPosition.move(movement); + positions.add(nextPosition); + if (nextPosition.equals(endPosition)) { + return positions; + } + } + } + + throw new IllegalArgumentException("갈 수 없는 곳입니다."); + } +} diff --git a/src/main/java/chess/MoveStrategy/SpecialMoveStrategy.java b/src/main/java/chess/MoveStrategy/SpecialMoveStrategy.java new file mode 100644 index 00000000000..897656bc5ef --- /dev/null +++ b/src/main/java/chess/MoveStrategy/SpecialMoveStrategy.java @@ -0,0 +1,29 @@ +package chess.MoveStrategy; + +import chess.domain.Movement; +import chess.domain.piece.Position; +import java.util.ArrayList; +import java.util.List; + +public class SpecialMoveStrategy implements MoveStrategy { + + @Override + public List canMove(final Position startPosition, final Position endPosition, + final List canMove, + final boolean firstMove) { + List positions = new ArrayList<>(); + Position currentPosition = startPosition; + for (Movement movement : canMove) { + positions.clear(); + while (currentPosition.canMove(movement)) { + Position nextPosition = currentPosition.move(movement); + positions.add(nextPosition); + if (nextPosition.equals(endPosition)) { + return positions; + } + currentPosition = nextPosition; + } + } + throw new IllegalArgumentException("갈 수 없는 곳입니다."); + } +} diff --git a/src/main/java/chess/domain/Board.java b/src/main/java/chess/domain/Board.java new file mode 100644 index 00000000000..b9888395fc6 --- /dev/null +++ b/src/main/java/chess/domain/Board.java @@ -0,0 +1,44 @@ +package chess.domain; + +import chess.ChessInitializer; +import chess.domain.piece.Column; +import chess.domain.piece.Piece; +import chess.domain.piece.Position; +import chess.domain.piece.Row; +import java.util.List; +import java.util.Set; + +public class Board { + + private final Pieces pieces; + private final Turn turn; + + public Board() { + this.pieces = new Pieces(ChessInitializer.initialize()); + this.turn = new Turn(); + } + + public void movePiece(final List inputMovePiece, final List inputMovePosition) { + Position wantMovePiecePosition = new Position(Row.findRowByNumber(inputMovePiece.get(1)), + Column.findColumnByAlphabet(inputMovePiece.get(0))); + Position wantMovePosition = new Position(Row.findRowByNumber(inputMovePosition.get(1)), + Column.findColumnByAlphabet(inputMovePosition.get(0))); + Piece piece = pieces.findPieceByPositionAndColor(wantMovePiecePosition, turn.getTurn()); + + pieces.validateMove(piece, wantMovePosition); + pieces.move(piece, wantMovePosition); + } + + public Set getPieces() { + return pieces.getPieces(); + } + + public Turn getTurn() { + return turn; + } + + public void changeTurn() { + turn.changeTurn(); + } + +} diff --git a/src/main/java/chess/Movement.java b/src/main/java/chess/domain/Movement.java similarity index 97% rename from src/main/java/chess/Movement.java rename to src/main/java/chess/domain/Movement.java index e57c6e91bb9..07b5d153f67 100644 --- a/src/main/java/chess/Movement.java +++ b/src/main/java/chess/domain/Movement.java @@ -1,4 +1,4 @@ -package chess; +package chess.domain; public enum Movement { UP(0, 1), diff --git a/src/main/java/chess/domain/Pieces.java b/src/main/java/chess/domain/Pieces.java new file mode 100644 index 00000000000..9de9f210be7 --- /dev/null +++ b/src/main/java/chess/domain/Pieces.java @@ -0,0 +1,73 @@ +package chess.domain; + +import chess.domain.piece.Color; +import chess.domain.piece.Knight; +import chess.domain.piece.Piece; +import chess.domain.piece.Position; +import java.util.List; +import java.util.Set; + +public class Pieces { + + private final Set pieces; + + public Pieces(final Set pieces) { + this.pieces = pieces; + } + + public Set getPieces() { + return pieces; + } + + public void validateMove(Piece piece, Position endPosition) { + if (piece.getClass() == Knight.class) { + return; + } + List route = piece.canMove(endPosition); + route.removeLast(); + for (Position position : route) { + if (findPieceByPosition(position).samePosition(endPosition)) { + throw new IllegalArgumentException("경로에 기물이 존재합니다."); + } + } + } + + public Piece findPieceByPosition(Position position) { + for (Piece piece : pieces) { + if (piece.samePosition(position)) { + return piece; + } + } + throw new IllegalArgumentException("기물이 해당 위치에 존재하지 않습니다."); + } + + public Piece findPieceByPositionAndColor(Position position, Color color) { + for (Piece piece : pieces) { + if (piece.samePosition(position) && piece.isSameTeam(color)) { + return piece; + } + } + throw new IllegalArgumentException("기물이 해당 위치에 존재하지 않습니다."); + } + + public boolean hasPieceInPosition(final Position position) { + for (Piece piece : pieces) { + if (piece.samePosition(position)) { + return true; + } + } + return false; + } + + public void move(final Piece piece, final Position wantMovePosition) { + if (hasPieceInPosition(wantMovePosition)) { + Piece findPiece = findPieceByPosition(wantMovePosition); + if (piece.isOtherTeam(findPiece)) { + pieces.remove(findPiece); + } else { + throw new IllegalArgumentException("같은 팀의 말은 잡지 못합니다."); + } + } + piece.move(wantMovePosition); + } +} diff --git a/src/main/java/chess/domain/Turn.java b/src/main/java/chess/domain/Turn.java new file mode 100644 index 00000000000..99c881c59f7 --- /dev/null +++ b/src/main/java/chess/domain/Turn.java @@ -0,0 +1,30 @@ +package chess.domain; + +import static chess.domain.piece.Color.BLACK; +import static chess.domain.piece.Color.WHITE; + +import chess.domain.piece.Color; + +public class Turn { + + private static final Color initialTurn = WHITE; + + private Color turn; + + public Turn() { + this.turn = initialTurn; + } + + public Color getTurn() { + return turn; + } + + public void changeTurn() { + if (turn == WHITE) { + turn = BLACK; + return; + } + turn = WHITE; + + } +} diff --git a/src/main/java/chess/domain/piece/Bishop.java b/src/main/java/chess/domain/piece/Bishop.java new file mode 100644 index 00000000000..ff5da8c7a12 --- /dev/null +++ b/src/main/java/chess/domain/piece/Bishop.java @@ -0,0 +1,41 @@ +package chess.domain.piece; + +import static chess.domain.Movement.LEFT_DOWN; +import static chess.domain.Movement.LEFT_UP; +import static chess.domain.Movement.RIGHT_DOWN; +import static chess.domain.Movement.RIGHT_UP; + +import chess.domain.Movement; +import java.util.ArrayList; +import java.util.List; + +public class Bishop extends Piece { + + private final static List canMove = List.of( + RIGHT_UP, RIGHT_DOWN, LEFT_DOWN, LEFT_UP + ); + + public Bishop(final Color color, final Position position) { + super(color, position); + } + + @Override + public List canMove(final Position endPosition) { + List positions = new ArrayList<>(); + Position currentPosition = this.position; + for (Movement movement : canMove) { + positions.clear(); + while (currentPosition.canMove(movement)) { + Position nextPosition = currentPosition.move(movement); + positions.add(nextPosition); + if (nextPosition.equals(endPosition)) { + return positions; + } + currentPosition = nextPosition; + } + } + throw new IllegalArgumentException("갈 수 없는 곳입니다."); + } + +} + diff --git a/src/main/java/chess/Color.java b/src/main/java/chess/domain/piece/Color.java similarity index 93% rename from src/main/java/chess/Color.java rename to src/main/java/chess/domain/piece/Color.java index 55cd020b681..d599dbed3fb 100644 --- a/src/main/java/chess/Color.java +++ b/src/main/java/chess/domain/piece/Color.java @@ -1,4 +1,4 @@ -package chess; +package chess.domain.piece; public enum Color { diff --git a/src/main/java/chess/Column.java b/src/main/java/chess/domain/piece/Column.java similarity index 59% rename from src/main/java/chess/Column.java rename to src/main/java/chess/domain/piece/Column.java index b64b4dc77a3..0d2585bb99f 100644 --- a/src/main/java/chess/Column.java +++ b/src/main/java/chess/domain/piece/Column.java @@ -1,4 +1,4 @@ -package chess; +package chess.domain.piece; public enum Column { @@ -50,4 +50,35 @@ public Column moveRight(final int step) { throw new IllegalStateException("움직일 수 없는 위치입니다."); } + + public static Column findColumnByAlphabet(String input) { + + if (input.equals("A")) { + return A; + } + if (input.equals("B")) { + return B; + } + if (input.equals("C")) { + return C; + } + if (input.equals("D")) { + return D; + } + if (input.equals("E")) { + return E; + } + if (input.equals("F")) { + return F; + } + if (input.equals("G")) { + return G; + } + if (input.equals("H")) { + return H; + } + + throw new IllegalArgumentException("위치가 올바르지 않습니다."); + + } } diff --git a/src/main/java/chess/domain/piece/King.java b/src/main/java/chess/domain/piece/King.java new file mode 100644 index 00000000000..e03b1c70b09 --- /dev/null +++ b/src/main/java/chess/domain/piece/King.java @@ -0,0 +1,38 @@ +package chess.domain.piece; + +import static chess.domain.Movement.DOWN; +import static chess.domain.Movement.LEFT; +import static chess.domain.Movement.RIGHT; +import static chess.domain.Movement.UP; + +import chess.domain.Movement; +import java.util.ArrayList; +import java.util.List; + +public class King extends Piece { + + private final static List canMove = List.of( + RIGHT, LEFT, UP, DOWN + ); + + public King(final Color color, final Position position) { + super(color, position); + } + + + @Override + public List canMove(final Position endPosition) { + List positions = new ArrayList<>(); + for (Movement movement : canMove) { + positions.clear(); + if (this.position.canMove(movement)) { + Position nextPosition = this.position.move(movement); + positions.add(nextPosition); + if (nextPosition.equals(endPosition)) { + return positions; + } + } + } + throw new IllegalArgumentException("갈 수 없는 위치입니다."); + } +} diff --git a/src/main/java/chess/domain/piece/Knight.java b/src/main/java/chess/domain/piece/Knight.java new file mode 100644 index 00000000000..69f85d1f929 --- /dev/null +++ b/src/main/java/chess/domain/piece/Knight.java @@ -0,0 +1,48 @@ +package chess.domain.piece; + +import static chess.domain.Movement.DOWN_DOWN_LEFT; +import static chess.domain.Movement.DOWN_DOWN_RIGHT; +import static chess.domain.Movement.LEFT_LEFT_DOWN; +import static chess.domain.Movement.LEFT_LEFT_UP; +import static chess.domain.Movement.RIGHT_RIGHT_DOWN; +import static chess.domain.Movement.RIGHT_RIGHT_UP; +import static chess.domain.Movement.UP_UP_LEFT; +import static chess.domain.Movement.UP_UP_RIGHT; + +import chess.domain.Movement; +import java.util.ArrayList; +import java.util.List; + +public class Knight extends Piece { + + private final static List canMove = List.of( + UP_UP_LEFT, + UP_UP_RIGHT, + LEFT_LEFT_UP, + LEFT_LEFT_DOWN, + DOWN_DOWN_LEFT, + DOWN_DOWN_RIGHT, + RIGHT_RIGHT_UP, + RIGHT_RIGHT_DOWN + ); + + public Knight(final Color color, final Position position) { + super(color, position); + } + + @Override + public List canMove(final Position endPosition) { + List positions = new ArrayList<>(); + for (Movement movement : canMove) { + positions.clear(); + if (this.position.canMove(movement)) { + Position nextPosition = this.position.move(movement); + positions.add(nextPosition); + if (nextPosition.equals(endPosition)) { + return positions; + } + } + } + throw new IllegalArgumentException("갈 수 없는 위치입니다."); + } +} diff --git a/src/main/java/chess/domain/piece/Pawn.java b/src/main/java/chess/domain/piece/Pawn.java new file mode 100644 index 00000000000..89578bbc37c --- /dev/null +++ b/src/main/java/chess/domain/piece/Pawn.java @@ -0,0 +1,63 @@ +package chess.domain.piece; + +import static chess.domain.Movement.DOWN; +import static chess.domain.Movement.DOWN_DOWN; +import static chess.domain.Movement.LEFT_DOWN; +import static chess.domain.Movement.LEFT_UP; +import static chess.domain.Movement.RIGHT_DOWN; +import static chess.domain.Movement.RIGHT_UP; +import static chess.domain.Movement.UP; +import static chess.domain.Movement.UP_UP; + +import chess.domain.Movement; +import java.util.ArrayList; +import java.util.List; + +public class Pawn extends Piece { + + private boolean firstMove = true; + + private static final List canMoveWhite = List.of( + UP, RIGHT_UP, LEFT_UP, UP_UP + ); + + private static final List canMoveBlack = List.of( + DOWN, RIGHT_DOWN, LEFT_DOWN, DOWN_DOWN + ); + + public Pawn(final Color color, final Position position) { + super(color, position); + } + + @Override + public List canMove(final Position endPosition) { + if (color == Color.WHITE) { + return calculateRoute(endPosition, canMoveWhite); + } + return calculateRoute(endPosition, canMoveBlack); + } + + private List calculateRoute(Position endPosition, List movements) { + List positions = new ArrayList<>(); + for (Movement movement : movements) { + positions.clear(); + if (movement == UP_UP && firstMove) { + if (this.position.canMove(movement)) { + Position nextPosition = this.position.move(movement); + positions.add(nextPosition); + if (nextPosition.equals(endPosition)) { + return positions; + } + } + } else if (this.position.canMove(movement)) { + Position nextPosition = this.position.move(movement); + positions.add(nextPosition); + if (nextPosition.equals(endPosition)) { + return positions; + } + } + } + + throw new IllegalArgumentException("갈 수 없는 곳입니다."); + } +} diff --git a/src/main/java/chess/domain/piece/Piece.java b/src/main/java/chess/domain/piece/Piece.java new file mode 100644 index 00000000000..ff0f0196e81 --- /dev/null +++ b/src/main/java/chess/domain/piece/Piece.java @@ -0,0 +1,52 @@ +package chess.domain.piece; + +import java.util.List; +import java.util.Objects; + +public abstract class Piece { + + protected final Color color; + protected Position position; + + protected Piece(final Color color, final Position position) { + this.color = color; + this.position = position; + } + + public abstract List canMove(Position position); + + public boolean samePosition(final Position position) { + return this.position.equals(position); + } + + + public Color getColor() { + return color; + } + + @Override + public boolean equals(final Object o) { + if (o == null || getClass() != o.getClass()) { + return false; + } + final Piece piece = (Piece) o; + return color == piece.color && Objects.equals(position, piece.position); + } + + @Override + public int hashCode() { + return Objects.hash(color, position); + } + + public void move(final Position wantMovePosition) { + this.position = wantMovePosition; + } + + public boolean isOtherTeam(final Piece findPiece) { + return this.color != findPiece.color; + } + + public boolean isSameTeam(Color color) { + return this.color == color; + } +} diff --git a/src/main/java/chess/Position.java b/src/main/java/chess/domain/piece/Position.java similarity index 89% rename from src/main/java/chess/Position.java rename to src/main/java/chess/domain/piece/Position.java index 3ebeb0ea185..d31ff3209e4 100644 --- a/src/main/java/chess/Position.java +++ b/src/main/java/chess/domain/piece/Position.java @@ -1,4 +1,7 @@ -package chess; +package chess.domain.piece; + +import chess.domain.Movement; +import java.util.Objects; public record Position( Column column, @@ -167,4 +170,18 @@ public Position moveHorizontal(final int step) { } return this; } + + @Override + public boolean equals(final Object o) { + if (o == null || getClass() != o.getClass()) { + return false; + } + final Position position = (Position) o; + return row == position.row && column == position.column; + } + + @Override + public int hashCode() { + return Objects.hash(column, row); + } } diff --git a/src/main/java/chess/domain/piece/Queen.java b/src/main/java/chess/domain/piece/Queen.java new file mode 100644 index 00000000000..7a7aeb8479e --- /dev/null +++ b/src/main/java/chess/domain/piece/Queen.java @@ -0,0 +1,43 @@ +package chess.domain.piece; + +import static chess.domain.Movement.DOWN; +import static chess.domain.Movement.LEFT; +import static chess.domain.Movement.LEFT_DOWN; +import static chess.domain.Movement.LEFT_UP; +import static chess.domain.Movement.RIGHT; +import static chess.domain.Movement.RIGHT_DOWN; +import static chess.domain.Movement.RIGHT_UP; +import static chess.domain.Movement.UP; + +import chess.domain.Movement; +import java.util.ArrayList; +import java.util.List; + +public class Queen extends Piece { + + private final static List canMove = List.of( + RIGHT_UP, RIGHT_DOWN, LEFT_DOWN, LEFT_UP, UP, DOWN, LEFT, RIGHT + ); + + public Queen(final Color color, final Position position) { + super(color, position); + } + + @Override + public List canMove(final Position endPosition) { + List positions = new ArrayList<>(); + Position currentPosition = this.position; + for (Movement movement : canMove) { + positions.clear(); + while (currentPosition.canMove(movement)) { + Position nextPosition = currentPosition.move(movement); + positions.add(nextPosition); + if (nextPosition.equals(endPosition)) { + return positions; + } + currentPosition = nextPosition; + } + } + throw new IllegalArgumentException("갈 수 없는 곳입니다."); + } +} diff --git a/src/main/java/chess/domain/piece/Rook.java b/src/main/java/chess/domain/piece/Rook.java new file mode 100644 index 00000000000..204806293a5 --- /dev/null +++ b/src/main/java/chess/domain/piece/Rook.java @@ -0,0 +1,43 @@ +package chess.domain.piece; + +import static chess.domain.Movement.DOWN; +import static chess.domain.Movement.LEFT; +import static chess.domain.Movement.LEFT_DOWN; +import static chess.domain.Movement.LEFT_UP; +import static chess.domain.Movement.RIGHT; +import static chess.domain.Movement.RIGHT_DOWN; +import static chess.domain.Movement.RIGHT_UP; +import static chess.domain.Movement.UP; + +import chess.domain.Movement; +import java.util.ArrayList; +import java.util.List; + +public class Rook extends Piece { + + private final static List canMove = List.of( + RIGHT_UP, RIGHT_DOWN, LEFT_DOWN, LEFT_UP, UP, DOWN, LEFT, RIGHT + ); + + public Rook(final Color color, final Position position) { + super(color, position); + } + + @Override + public List canMove(final Position endPosition) { + List positions = new ArrayList<>(); + Position currentPosition = this.position; + for (Movement movement : canMove) { + positions.clear(); + while (currentPosition.canMove(movement)) { + Position nextPosition = currentPosition.move(movement); + positions.add(nextPosition); + if (nextPosition.equals(endPosition)) { + return positions; + } + currentPosition = nextPosition; + } + } + throw new IllegalArgumentException("갈 수 없는 곳입니다."); + } +} diff --git a/src/main/java/chess/Row.java b/src/main/java/chess/domain/piece/Row.java similarity index 58% rename from src/main/java/chess/Row.java rename to src/main/java/chess/domain/piece/Row.java index 126ed048daa..c35f93cef1d 100644 --- a/src/main/java/chess/Row.java +++ b/src/main/java/chess/domain/piece/Row.java @@ -1,4 +1,4 @@ -package chess; +package chess.domain.piece; public enum Row { @@ -50,4 +50,33 @@ public Row moveDown(final int step) { throw new IllegalStateException("움직일 수 없는 위치입니다."); } + + public static Row findRowByNumber(String input) { + + if (input.equals("8")) { + return EIGHT; + } + if (input.equals("7")) { + return SEVEN; + } + if (input.equals("6")) { + return SIX; + } + if (input.equals("5")) { + return FIVE; + } + if (input.equals("4")) { + return FOUR; + } + if (input.equals("3")) { + return THREE; + } + if (input.equals("2")) { + return TWO; + } + if (input.equals("1")) { + return ONE; + } + throw new IllegalArgumentException("위치가 올바르지 않습니다."); + } } diff --git a/src/main/java/chess/piece/Bishop.java b/src/main/java/chess/piece/Bishop.java deleted file mode 100644 index b14ab70f981..00000000000 --- a/src/main/java/chess/piece/Bishop.java +++ /dev/null @@ -1,5 +0,0 @@ -package chess.piece; - -public class Bishop { - -} diff --git a/src/main/java/chess/piece/King.java b/src/main/java/chess/piece/King.java deleted file mode 100644 index d64210cad13..00000000000 --- a/src/main/java/chess/piece/King.java +++ /dev/null @@ -1,5 +0,0 @@ -package chess.piece; - -public class King { - -} diff --git a/src/main/java/chess/piece/Knight.java b/src/main/java/chess/piece/Knight.java deleted file mode 100644 index 2ee7c47a3bc..00000000000 --- a/src/main/java/chess/piece/Knight.java +++ /dev/null @@ -1,5 +0,0 @@ -package chess.piece; - -public class Knight { - -} diff --git a/src/main/java/chess/piece/Pawn.java b/src/main/java/chess/piece/Pawn.java deleted file mode 100644 index c8b6cafa51e..00000000000 --- a/src/main/java/chess/piece/Pawn.java +++ /dev/null @@ -1,5 +0,0 @@ -package chess.piece; - -public class Pawn { - -} diff --git a/src/main/java/chess/piece/Queen.java b/src/main/java/chess/piece/Queen.java deleted file mode 100644 index 9b547261c4b..00000000000 --- a/src/main/java/chess/piece/Queen.java +++ /dev/null @@ -1,5 +0,0 @@ -package chess.piece; - -public class Queen { - -} diff --git a/src/main/java/chess/piece/Rook.java b/src/main/java/chess/piece/Rook.java deleted file mode 100644 index 7ed4d08bf03..00000000000 --- a/src/main/java/chess/piece/Rook.java +++ /dev/null @@ -1,5 +0,0 @@ -package chess.piece; - -public class Rook { - -} diff --git a/src/main/java/chess/view/InputView.java b/src/main/java/chess/view/InputView.java new file mode 100644 index 00000000000..9a29fec6e1a --- /dev/null +++ b/src/main/java/chess/view/InputView.java @@ -0,0 +1,24 @@ +package chess.view; + +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; + +public class InputView { + + private final Scanner scanner = new Scanner(System.in); + + + public List inputMovePosition() { + System.out.println("원하는 위치를 입력해주세요."); + String input = scanner.nextLine(); + return Arrays.stream(input.split(" ")).toList(); + } + + public List inputMovePiece() { + System.out.println("원하는 말의 위치를 입력해주세요."); + String input = scanner.nextLine(); + + return Arrays.stream(input.split(" ")).toList(); + } +} diff --git a/src/main/java/chess/view/OutputView.java b/src/main/java/chess/view/OutputView.java new file mode 100644 index 00000000000..e786b9d47c2 --- /dev/null +++ b/src/main/java/chess/view/OutputView.java @@ -0,0 +1,150 @@ +package chess.view; + +import static chess.domain.piece.Column.A; +import static chess.domain.piece.Column.B; +import static chess.domain.piece.Column.C; +import static chess.domain.piece.Column.D; +import static chess.domain.piece.Column.E; +import static chess.domain.piece.Column.F; +import static chess.domain.piece.Column.G; +import static chess.domain.piece.Row.EIGHT; +import static chess.domain.piece.Row.FIVE; +import static chess.domain.piece.Row.FOUR; +import static chess.domain.piece.Row.SEVEN; +import static chess.domain.piece.Row.SIX; +import static chess.domain.piece.Row.THREE; +import static chess.domain.piece.Row.TWO; + +import chess.domain.Board; +import chess.domain.piece.Color; +import chess.domain.piece.Column; +import chess.domain.piece.Position; +import chess.domain.piece.Row; +import chess.domain.Turn; +import chess.domain.piece.Bishop; +import chess.domain.piece.King; +import chess.domain.piece.Knight; +import chess.domain.piece.Piece; +import chess.domain.piece.Queen; +import chess.domain.piece.Rook; +import java.util.Set; + +public class OutputView { + + private static final String ANSI_RESET = "\u001B[0m"; + public static final String ANSI_WHITE = "\u001B[37m"; + private static final String ANSI_BLACK = "\u001B[30m"; + + public void printChessBoard(final Board board) { + + Set pieces = board.getPieces(); + for (Row row : Row.values()) { + System.out.print(getRowName(row) + " "); + for (Column column : Column.values()) { + boolean check = true; + for (Piece piece : pieces) { + if (piece.samePosition(new Position(column, row))) { + System.out.print(getColorPieceName(piece) + " "); + check = false; + break; + } + } + if (check) { + System.out.print(". "); + } + } + System.out.println(); + } + System.out.print(" "); + for (Column column : Column.values()) { + System.out.print(getColumnName(column) + " "); + } + System.out.println(); + } + + private String getColorPieceName(Piece piece) { + if (piece.getColor() == Color.WHITE) { + return ANSI_WHITE + getPieceName(piece) + ANSI_RESET; + } + return ANSI_BLACK + getPieceName(piece) + ANSI_RESET; + } + + private String getPieceName(Piece piece) { + if (piece.getClass() == King.class) { + return "K"; + } + if (piece.getClass() == Queen.class) { + return "Q"; + } + if (piece.getClass() == Bishop.class) { + return "B"; + } + if (piece.getClass() == Knight.class) { + return "N"; + } + if (piece.getClass() == Rook.class) { + return "R"; + } + return "P"; + } + + private String getRowName(Row row) { + if (row == EIGHT) { + return "8"; + } + if (row == SEVEN) { + return "7"; + } + + if (row == SIX) { + return "6"; + } + + if (row == FIVE) { + return "5"; + } + + if (row == FOUR) { + return "4"; + } + + if (row == THREE) { + return "3"; + } + + if (row == TWO) { + return "2"; + } + return "1"; + } + + private String getColumnName(Column column) { + if (column == A) { + return "A"; + } + if (column == B) { + return "B"; + } + if (column == C) { + return "C"; + } + if (column == D) { + return "D"; + } + if (column == E) { + return "E"; + } + if (column == F) { + return "F"; + } + if (column == G) { + return "G"; + } + return "H"; + } + + + public void printTurn(final Turn turn) { + System.out.println(turn.getTurn().name() + "의 턴입니다."); + } +} diff --git a/src/test/java/chess/ColumnTest.java b/src/test/java/chess/ColumnTest.java index e43523240f7..36924537515 100644 --- a/src/test/java/chess/ColumnTest.java +++ b/src/test/java/chess/ColumnTest.java @@ -1,5 +1,6 @@ package chess; +import chess.domain.piece.Column; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/chess/Fixtures.java b/src/test/java/chess/Fixtures.java index f940ab37137..ad9f6769b6b 100644 --- a/src/test/java/chess/Fixtures.java +++ b/src/test/java/chess/Fixtures.java @@ -1,5 +1,9 @@ package chess; +import chess.domain.piece.Column; +import chess.domain.piece.Position; +import chess.domain.piece.Row; + @SuppressWarnings("unused") public final class Fixtures { diff --git a/src/test/java/chess/PositionTest.java b/src/test/java/chess/PositionTest.java index 3ad7cc64084..32cd0ced5d4 100644 --- a/src/test/java/chess/PositionTest.java +++ b/src/test/java/chess/PositionTest.java @@ -1,5 +1,7 @@ package chess; +import chess.domain.Movement; +import chess.domain.piece.Position; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -164,7 +166,7 @@ void moveRight_2_F1() { assertThat(moved).isEqualTo(H1); } - ///// + /// // @DisplayName("A8은 맨 위다.") @Test diff --git a/src/test/java/chess/RowTest.java b/src/test/java/chess/RowTest.java index fcb65485410..9a0375d75de 100644 --- a/src/test/java/chess/RowTest.java +++ b/src/test/java/chess/RowTest.java @@ -1,5 +1,6 @@ package chess; +import chess.domain.piece.Row; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/chess/domain/piece/BishopTest.java b/src/test/java/chess/domain/piece/BishopTest.java new file mode 100644 index 00000000000..0603416b668 --- /dev/null +++ b/src/test/java/chess/domain/piece/BishopTest.java @@ -0,0 +1,43 @@ +package chess.domain.piece; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import chess.MoveStrategy.SpecialMoveStrategy; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class BishopTest { + + @DisplayName("비숍 이동 가능 테스트") + @Test + void bishopCanMoveTest() { + + // given + Piece bishop = new Bishop(Color.BLACK, new Position(Row.ONE, Column.A)); + Position endPosition = new Position(Row.EIGHT, Column.H); + + // when + List result = bishop.canMove(endPosition); + + // then + assertThat(result.size()).isEqualTo(7); + } + + @DisplayName("비숍 이동 불가능 테스트") + @Test + void bishopCantMoveTest() { + + // given + Piece bishop = new Bishop(Color.BLACK, new Position(Row.ONE, Column.A), new SpecialMoveStrategy()); + Position endPosition = new Position(Row.EIGHT, Column.F); + + // when + + // then + assertThatThrownBy(() -> bishop.canMove(endPosition)) + .isInstanceOf(IllegalArgumentException.class); + } + +} From 7f25f9db7dec5c1f922a03a5431febeb37ce741f Mon Sep 17 00:00:00 2001 From: CheChe903 Date: Sat, 22 Mar 2025 19:35:18 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat=20:=20=EC=B2=B4=EC=8A=A4=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MoveStrategy/DefaultMoveStrategy.java | 27 ------------- .../java/chess/MoveStrategy/MoveStrategy.java | 11 ------ .../chess/MoveStrategy/PawnMoveStrategy.java | 39 ------------------- .../MoveStrategy/SpecialMoveStrategy.java | 29 -------------- 4 files changed, 106 deletions(-) delete mode 100644 src/main/java/chess/MoveStrategy/DefaultMoveStrategy.java delete mode 100644 src/main/java/chess/MoveStrategy/MoveStrategy.java delete mode 100644 src/main/java/chess/MoveStrategy/PawnMoveStrategy.java delete mode 100644 src/main/java/chess/MoveStrategy/SpecialMoveStrategy.java diff --git a/src/main/java/chess/MoveStrategy/DefaultMoveStrategy.java b/src/main/java/chess/MoveStrategy/DefaultMoveStrategy.java deleted file mode 100644 index ffb307ae615..00000000000 --- a/src/main/java/chess/MoveStrategy/DefaultMoveStrategy.java +++ /dev/null @@ -1,27 +0,0 @@ -package chess.MoveStrategy; - -import chess.domain.Movement; -import chess.domain.piece.Position; -import java.util.ArrayList; -import java.util.List; - -public class DefaultMoveStrategy implements MoveStrategy { - - @Override - public List canMove(final Position startPosition, final Position endPosition, List canMove, - final boolean firstMove) { - - List positions = new ArrayList<>(); - for (Movement movement : canMove) { - positions.clear(); - if (startPosition.canMove(movement)) { - Position nextPosition = startPosition.move(movement); - positions.add(nextPosition); - if (nextPosition.equals(endPosition)) { - return positions; - } - } - } - throw new IllegalArgumentException("갈 수 없는 위치입니다."); - } -} diff --git a/src/main/java/chess/MoveStrategy/MoveStrategy.java b/src/main/java/chess/MoveStrategy/MoveStrategy.java deleted file mode 100644 index 6a635c5e9fd..00000000000 --- a/src/main/java/chess/MoveStrategy/MoveStrategy.java +++ /dev/null @@ -1,11 +0,0 @@ -package chess.MoveStrategy; - -import chess.domain.Movement; -import chess.domain.piece.Position; -import java.util.List; - -public interface MoveStrategy { - - List canMove(Position startPosition, Position endPosition, List canMove, - final boolean firstMove); -} diff --git a/src/main/java/chess/MoveStrategy/PawnMoveStrategy.java b/src/main/java/chess/MoveStrategy/PawnMoveStrategy.java deleted file mode 100644 index 527e551ed1e..00000000000 --- a/src/main/java/chess/MoveStrategy/PawnMoveStrategy.java +++ /dev/null @@ -1,39 +0,0 @@ -package chess.MoveStrategy; - -import static chess.domain.Movement.UP_UP; - -import chess.domain.Movement; -import chess.domain.piece.Position; -import java.util.ArrayList; -import java.util.List; - -public class PawnMoveStrategy implements MoveStrategy { - - @Override - public List canMove(final Position startPosition, final Position endPosition, - final List canMove, - final boolean firstMove) { - - List positions = new ArrayList<>(); - for (Movement movement : canMove) { - positions.clear(); - if (movement == UP_UP && firstMove) { - if (startPosition.canMove(movement)) { - Position nextPosition = startPosition.move(movement); - positions.add(nextPosition); - if (nextPosition.equals(endPosition)) { - return positions; - } - } - } else if (startPosition.canMove(movement)) { - Position nextPosition = startPosition.move(movement); - positions.add(nextPosition); - if (nextPosition.equals(endPosition)) { - return positions; - } - } - } - - throw new IllegalArgumentException("갈 수 없는 곳입니다."); - } -} diff --git a/src/main/java/chess/MoveStrategy/SpecialMoveStrategy.java b/src/main/java/chess/MoveStrategy/SpecialMoveStrategy.java deleted file mode 100644 index 897656bc5ef..00000000000 --- a/src/main/java/chess/MoveStrategy/SpecialMoveStrategy.java +++ /dev/null @@ -1,29 +0,0 @@ -package chess.MoveStrategy; - -import chess.domain.Movement; -import chess.domain.piece.Position; -import java.util.ArrayList; -import java.util.List; - -public class SpecialMoveStrategy implements MoveStrategy { - - @Override - public List canMove(final Position startPosition, final Position endPosition, - final List canMove, - final boolean firstMove) { - List positions = new ArrayList<>(); - Position currentPosition = startPosition; - for (Movement movement : canMove) { - positions.clear(); - while (currentPosition.canMove(movement)) { - Position nextPosition = currentPosition.move(movement); - positions.add(nextPosition); - if (nextPosition.equals(endPosition)) { - return positions; - } - currentPosition = nextPosition; - } - } - throw new IllegalArgumentException("갈 수 없는 곳입니다."); - } -}