From 30b8b60ce93165e0d0ef53acae8fffb19be53d22 Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 13:44:33 +0900 Subject: [PATCH 01/25] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EB=B0=8F=20=EC=B6=94=ED=9B=84=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=20=EB=AA=A9=EB=A1=9D=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/README.md b/README.md index 8102f91c870..cd1cee1e2dc 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,37 @@ ## 우아한테크코스 코드리뷰 - [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md) + +### 기능 목록 +- [ ] 초기 보드판을 구성한다. +- [ ] 플레이어가 턴을 주고 받는다. +- [ ] 플레이어는 자신의 턴에 기물을 움직인다. + - [ ] 킹 + - 어느 방향이든 위/아래/양옆/대각선을 한 칸씩 이동할 수 있다. + - [ ] 퀸 + - 일직선으로 어떤 방향이든 원하는 만큼 이동할 수 있다. + - [ ] 룩 + - 일직선으로 앞/뒤/양옆으로 원하는 만큼 이동할 수 있다. + - [ ] 비숍 + - 일직선으로 대각선을 원하는 만큼 이동할 수 있다. + - [ ] 나이트 + - 한 방향으로 두칸을 이동하고 그와 90도를 이루는 방향으로 한칸 이동한다.(L자 모양) + - 진행 경로에 다른 기물이 있어도 가로 막히지 않는다. + - [ ] 폰 + - 처음 움직이는 폰은 앞으로 두 칸까지 이동할 수 있다. + - 이후부터는 앞으로 한 칸씩만 이동할 수 있다. + - 잡을 때는 대각선으로 한 칸 앞에 있는 상대 기물만 잡을 수 있다. + - 이동 규칙 + - [ ] 나이트를 제외한 모든 기물은 다른 기물을 뛰어 넘을 수 없다. + - [ ] 상대편의 말만 잡을 수 있다. +- [ ] 킹이 잡히면 잡힌 쪽이 패배하며 게임을 종료한다. + + +### 추후 구현 목록 +- 킹은 스스로 체크 위치로 이동할 수 없다. +- 폰을 승진할 수 있다. +- 앙 파상 규칙을 적용한다. +- 캐슬링 규칙을 적용한다. +- 킹이 잡히면 게임을 종료한다. +- 체크 메이트 규칙을 적용한다. +- 게임을 끝낼 수 없는 경우 무승부처리한다. From f0595c8ee66972144fd726aaa57fe8f92eee51c3 Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 13:51:21 +0900 Subject: [PATCH 02/25] =?UTF-8?q?feat:=20Piece=20=EC=B6=94=EC=83=81=20?= =?UTF-8?q?=EB=B6=80=EB=AA=A8=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/piece/Bishop.java | 2 +- src/main/java/chess/piece/King.java | 2 +- src/main/java/chess/piece/Knight.java | 2 +- src/main/java/chess/piece/Pawn.java | 2 +- src/main/java/chess/piece/Piece.java | 4 ++++ src/main/java/chess/piece/Queen.java | 2 +- src/main/java/chess/piece/Rook.java | 2 +- 7 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 src/main/java/chess/piece/Piece.java diff --git a/src/main/java/chess/piece/Bishop.java b/src/main/java/chess/piece/Bishop.java index b14ab70f981..9d7d822faea 100644 --- a/src/main/java/chess/piece/Bishop.java +++ b/src/main/java/chess/piece/Bishop.java @@ -1,5 +1,5 @@ package chess.piece; -public class Bishop { +public class Bishop extends Piece { } diff --git a/src/main/java/chess/piece/King.java b/src/main/java/chess/piece/King.java index d64210cad13..f0baf5b1695 100644 --- a/src/main/java/chess/piece/King.java +++ b/src/main/java/chess/piece/King.java @@ -1,5 +1,5 @@ package chess.piece; -public class King { +public class King extends Piece { } diff --git a/src/main/java/chess/piece/Knight.java b/src/main/java/chess/piece/Knight.java index 2ee7c47a3bc..be407ec080e 100644 --- a/src/main/java/chess/piece/Knight.java +++ b/src/main/java/chess/piece/Knight.java @@ -1,5 +1,5 @@ package chess.piece; -public class Knight { +public class Knight extends Piece { } diff --git a/src/main/java/chess/piece/Pawn.java b/src/main/java/chess/piece/Pawn.java index c8b6cafa51e..0e548a9bc68 100644 --- a/src/main/java/chess/piece/Pawn.java +++ b/src/main/java/chess/piece/Pawn.java @@ -1,5 +1,5 @@ package chess.piece; -public class Pawn { +public class Pawn extends Piece { } diff --git a/src/main/java/chess/piece/Piece.java b/src/main/java/chess/piece/Piece.java new file mode 100644 index 00000000000..c022fe5a0ee --- /dev/null +++ b/src/main/java/chess/piece/Piece.java @@ -0,0 +1,4 @@ +package chess.piece; + +public abstract class Piece { +} diff --git a/src/main/java/chess/piece/Queen.java b/src/main/java/chess/piece/Queen.java index 9b547261c4b..e704fa52084 100644 --- a/src/main/java/chess/piece/Queen.java +++ b/src/main/java/chess/piece/Queen.java @@ -1,5 +1,5 @@ package chess.piece; -public class Queen { +public class Queen extends Piece { } diff --git a/src/main/java/chess/piece/Rook.java b/src/main/java/chess/piece/Rook.java index 7ed4d08bf03..d2a38fa27bc 100644 --- a/src/main/java/chess/piece/Rook.java +++ b/src/main/java/chess/piece/Rook.java @@ -1,5 +1,5 @@ package chess.piece; -public class Rook { +public class Rook extends Piece { } From b448b11852825cabffbd3e179a4719236358101e Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 14:17:51 +0900 Subject: [PATCH 03/25] =?UTF-8?q?feat:=20=ED=82=B9=EC=9D=80=20=EC=9B=90?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EB=B0=A9=ED=96=A5=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=ED=95=9C=EC=B9=B8=20=EC=9D=B4=EB=8F=99=20=EA=B0=80=EB=8A=A5?= =?UTF-8?q?=ED=95=98=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 이동 목적지가 보드의 범위 밖이거나 킹이 이동할 수 없을 경우 예외를 발생한다. --- README.md | 5 ++-- src/main/java/chess/Position.java | 20 ++++++++++++++ src/main/java/chess/board/Board.java | 4 +++ src/main/java/chess/piece/Bishop.java | 7 +++++ src/main/java/chess/piece/King.java | 38 +++++++++++++++++++++++++++ src/main/java/chess/piece/Knight.java | 7 +++++ src/main/java/chess/piece/Pawn.java | 6 +++++ src/main/java/chess/piece/Piece.java | 4 +++ src/main/java/chess/piece/Queen.java | 7 +++++ src/main/java/chess/piece/Rook.java | 7 +++++ 10 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 src/main/java/chess/board/Board.java diff --git a/README.md b/README.md index cd1cee1e2dc..0a5193caaae 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ - [ ] 초기 보드판을 구성한다. - [ ] 플레이어가 턴을 주고 받는다. - [ ] 플레이어는 자신의 턴에 기물을 움직인다. - - [ ] 킹 + - [x] 킹 - 어느 방향이든 위/아래/양옆/대각선을 한 칸씩 이동할 수 있다. - [ ] 퀸 - 일직선으로 어떤 방향이든 원하는 만큼 이동할 수 있다. @@ -28,7 +28,8 @@ - 이동 규칙 - [ ] 나이트를 제외한 모든 기물은 다른 기물을 뛰어 넘을 수 없다. - [ ] 상대편의 말만 잡을 수 있다. -- [ ] 킹이 잡히면 잡힌 쪽이 패배하며 게임을 종료한다. + - [ ] 입력한 곳으로 이동할 수 없는 경우 예외를 발생한다. +- [ ] 킹이 잡히면 잡힌 쪽이 패배하며 게임을 종료한다 ### 추후 구현 목록 diff --git a/src/main/java/chess/Position.java b/src/main/java/chess/Position.java index 3ebeb0ea185..7d6d1f968f8 100644 --- a/src/main/java/chess/Position.java +++ b/src/main/java/chess/Position.java @@ -1,5 +1,7 @@ package chess; +import java.util.Objects; + public record Position( Column column, Row row @@ -167,4 +169,22 @@ public Position moveHorizontal(final int step) { } return this; } + + @Override + public boolean equals(Object object) { + if (object == null || getClass() != object.getClass()) { + return false; + } + Position position = (Position) object; + return row == position.row && column == position.column; + } + + @Override + public int hashCode() { + return Objects.hash(column, row); + } + + public boolean canNotMove(Movement movement) { + return !canMove(movement); + } } diff --git a/src/main/java/chess/board/Board.java b/src/main/java/chess/board/Board.java new file mode 100644 index 00000000000..0dd2cec0cda --- /dev/null +++ b/src/main/java/chess/board/Board.java @@ -0,0 +1,4 @@ +package chess.board; + +public class Board { +} diff --git a/src/main/java/chess/piece/Bishop.java b/src/main/java/chess/piece/Bishop.java index 9d7d822faea..64f74bf5cd7 100644 --- a/src/main/java/chess/piece/Bishop.java +++ b/src/main/java/chess/piece/Bishop.java @@ -1,5 +1,12 @@ package chess.piece; +import chess.Position; +import chess.board.Board; + public class Bishop extends Piece { + @Override + public void validateMovable(Board board, Position start, Position goal) { + + } } diff --git a/src/main/java/chess/piece/King.java b/src/main/java/chess/piece/King.java index f0baf5b1695..039d4c4dc2d 100644 --- a/src/main/java/chess/piece/King.java +++ b/src/main/java/chess/piece/King.java @@ -1,5 +1,43 @@ package chess.piece; +import chess.Movement; +import chess.Position; +import chess.board.Board; +import java.util.ArrayList; +import java.util.List; + public class King extends Piece { + public static List> allMovements = new ArrayList<>(); + + static { + allMovements.add(List.of(Movement.UP)); + allMovements.add(List.of(Movement.DOWN)); + allMovements.add(List.of(Movement.LEFT)); + allMovements.add(List.of(Movement.RIGHT)); + allMovements.add(List.of(Movement.RIGHT_UP)); + allMovements.add(List.of(Movement.LEFT_UP)); + allMovements.add(List.of(Movement.RIGHT_DOWN)); + allMovements.add(List.of(Movement.LEFT_DOWN)); + } + + @Override + public void validateMovable(Board board, Position start, Position goal) { + findRoot(start, goal); + } + private List findRoot(Position start, Position goal) { + for (List movements : allMovements) { + Position now = start; + for (Movement movement : movements) { + if (now.canNotMove(movement)) { + break; + } + now = now.move(movement); + } + if (now.equals(goal)) { + return movements; + } + } + throw new IllegalArgumentException("경로가 존재하지 않습니다."); + } } diff --git a/src/main/java/chess/piece/Knight.java b/src/main/java/chess/piece/Knight.java index be407ec080e..95b330678a1 100644 --- a/src/main/java/chess/piece/Knight.java +++ b/src/main/java/chess/piece/Knight.java @@ -1,5 +1,12 @@ package chess.piece; +import chess.Position; +import chess.board.Board; + public class Knight extends Piece { + @Override + public void validateMovable(Board board, Position start, Position goal) { + + } } diff --git a/src/main/java/chess/piece/Pawn.java b/src/main/java/chess/piece/Pawn.java index 0e548a9bc68..2daf8a88352 100644 --- a/src/main/java/chess/piece/Pawn.java +++ b/src/main/java/chess/piece/Pawn.java @@ -1,5 +1,11 @@ package chess.piece; +import chess.Position; +import chess.board.Board; + public class Pawn extends Piece { + @Override + public void validateMovable(Board board, Position start, Position goal) { + } } diff --git a/src/main/java/chess/piece/Piece.java b/src/main/java/chess/piece/Piece.java index c022fe5a0ee..31dface38eb 100644 --- a/src/main/java/chess/piece/Piece.java +++ b/src/main/java/chess/piece/Piece.java @@ -1,4 +1,8 @@ package chess.piece; +import chess.Position; +import chess.board.Board; + public abstract class Piece { + public abstract void validateMovable(Board board, Position start, Position goal); } diff --git a/src/main/java/chess/piece/Queen.java b/src/main/java/chess/piece/Queen.java index e704fa52084..009139442db 100644 --- a/src/main/java/chess/piece/Queen.java +++ b/src/main/java/chess/piece/Queen.java @@ -1,5 +1,12 @@ package chess.piece; +import chess.Position; +import chess.board.Board; + public class Queen extends Piece { + @Override + public void validateMovable(Board board, Position start, Position goal) { + + } } diff --git a/src/main/java/chess/piece/Rook.java b/src/main/java/chess/piece/Rook.java index d2a38fa27bc..a96135dde9b 100644 --- a/src/main/java/chess/piece/Rook.java +++ b/src/main/java/chess/piece/Rook.java @@ -1,5 +1,12 @@ package chess.piece; +import chess.Position; +import chess.board.Board; + public class Rook extends Piece { + @Override + public void validateMovable(Board board, Position start, Position goal) { + + } } From 4ec0a000eb70e298ab39835df16f8123b4ed6664 Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 14:21:41 +0900 Subject: [PATCH 04/25] =?UTF-8?q?feat:=20=EA=B0=81=20=EA=B8=B0=EB=AC=BC=20?= =?UTF-8?q?=EC=9D=B8=EC=8A=A4=ED=84=B4=EC=8A=A4=EB=8A=94=20=ED=8C=80?= =?UTF-8?q?=EC=9D=84=20=EC=9D=98=EB=AF=B8=ED=95=98=EB=8A=94=20=EC=83=89?= =?UTF-8?q?=EA=B9=94=EC=9D=84=20=EA=B0=80=EC=A7=84=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 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/Piece.java | 7 +++++++ src/main/java/chess/piece/Queen.java | 5 +++++ src/main/java/chess/piece/Rook.java | 5 +++++ 7 files changed, 37 insertions(+) diff --git a/src/main/java/chess/piece/Bishop.java b/src/main/java/chess/piece/Bishop.java index 64f74bf5cd7..08876a8df7d 100644 --- a/src/main/java/chess/piece/Bishop.java +++ b/src/main/java/chess/piece/Bishop.java @@ -1,10 +1,15 @@ package chess.piece; +import chess.Color; import chess.Position; import chess.board.Board; public class Bishop extends Piece { + public Bishop(final Color color) { + super(color); + } + @Override public void validateMovable(Board board, Position start, Position goal) { diff --git a/src/main/java/chess/piece/King.java b/src/main/java/chess/piece/King.java index 039d4c4dc2d..022b27288a9 100644 --- a/src/main/java/chess/piece/King.java +++ b/src/main/java/chess/piece/King.java @@ -1,5 +1,6 @@ package chess.piece; +import chess.Color; import chess.Movement; import chess.Position; import chess.board.Board; @@ -20,6 +21,10 @@ public class King extends Piece { allMovements.add(List.of(Movement.LEFT_DOWN)); } + public King(final Color color) { + super(color); + } + @Override public void validateMovable(Board board, Position start, Position goal) { findRoot(start, goal); diff --git a/src/main/java/chess/piece/Knight.java b/src/main/java/chess/piece/Knight.java index 95b330678a1..c97c3050695 100644 --- a/src/main/java/chess/piece/Knight.java +++ b/src/main/java/chess/piece/Knight.java @@ -1,10 +1,15 @@ package chess.piece; +import chess.Color; import chess.Position; import chess.board.Board; public class Knight extends Piece { + public Knight(final Color color) { + super(color); + } + @Override public void validateMovable(Board board, Position start, Position goal) { diff --git a/src/main/java/chess/piece/Pawn.java b/src/main/java/chess/piece/Pawn.java index 2daf8a88352..8788feb1127 100644 --- a/src/main/java/chess/piece/Pawn.java +++ b/src/main/java/chess/piece/Pawn.java @@ -1,9 +1,14 @@ package chess.piece; +import chess.Color; import chess.Position; import chess.board.Board; public class Pawn extends Piece { + public Pawn(final Color color) { + super(color); + } + @Override public void validateMovable(Board board, Position start, Position goal) { diff --git a/src/main/java/chess/piece/Piece.java b/src/main/java/chess/piece/Piece.java index 31dface38eb..8c67ef89f15 100644 --- a/src/main/java/chess/piece/Piece.java +++ b/src/main/java/chess/piece/Piece.java @@ -1,8 +1,15 @@ package chess.piece; +import chess.Color; import chess.Position; import chess.board.Board; public abstract class Piece { + private final Color color; + + protected Piece(final Color color) { + this.color = color; + } + public abstract void validateMovable(Board board, Position start, Position goal); } diff --git a/src/main/java/chess/piece/Queen.java b/src/main/java/chess/piece/Queen.java index 009139442db..c602bdc5cff 100644 --- a/src/main/java/chess/piece/Queen.java +++ b/src/main/java/chess/piece/Queen.java @@ -1,10 +1,15 @@ package chess.piece; +import chess.Color; import chess.Position; import chess.board.Board; public class Queen extends Piece { + public Queen(final Color color) { + super(color); + } + @Override public void validateMovable(Board board, Position start, Position goal) { diff --git a/src/main/java/chess/piece/Rook.java b/src/main/java/chess/piece/Rook.java index a96135dde9b..fa9e10b0a90 100644 --- a/src/main/java/chess/piece/Rook.java +++ b/src/main/java/chess/piece/Rook.java @@ -1,10 +1,15 @@ package chess.piece; +import chess.Color; import chess.Position; import chess.board.Board; public class Rook extends Piece { + public Rook(final Color color) { + super(color); + } + @Override public void validateMovable(Board board, Position start, Position goal) { From 59a586935b8eece5fa82558c8590b2dafd78b04a Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 14:24:57 +0900 Subject: [PATCH 05/25] =?UTF-8?q?feat:=20King=EC=9D=B4=20=EA=B0=99?= =?UTF-8?q?=EC=9D=80=20=ED=8C=80=EC=9D=84=20=EC=9E=A1=EC=9C=BC=EB=A0=A4?= =?UTF-8?q?=EA=B3=A0=20=ED=95=A0=20=EA=B2=BD=EC=9A=B0=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EB=A5=BC=20=EB=B0=9C=EC=83=9D=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/board/Board.java | 7 +++++++ src/main/java/chess/piece/King.java | 7 +++++++ src/main/java/chess/piece/Piece.java | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/chess/board/Board.java b/src/main/java/chess/board/Board.java index 0dd2cec0cda..3948a6e07d5 100644 --- a/src/main/java/chess/board/Board.java +++ b/src/main/java/chess/board/Board.java @@ -1,4 +1,11 @@ package chess.board; +import chess.Color; +import chess.Position; + public class Board { + public boolean sameColorPieceExists(Position goal, Color color) { + // TODO + return false; + } } diff --git a/src/main/java/chess/piece/King.java b/src/main/java/chess/piece/King.java index 022b27288a9..26b9e53b964 100644 --- a/src/main/java/chess/piece/King.java +++ b/src/main/java/chess/piece/King.java @@ -28,6 +28,7 @@ public King(final Color color) { @Override public void validateMovable(Board board, Position start, Position goal) { findRoot(start, goal); + validateSameTeamOnGoal(board, goal); } private List findRoot(Position start, Position goal) { @@ -45,4 +46,10 @@ private List findRoot(Position start, Position goal) { } throw new IllegalArgumentException("경로가 존재하지 않습니다."); } + + private void validateSameTeamOnGoal(Board board, Position goal) { + if (board.sameColorPieceExists(goal, color)) { + throw new IllegalArgumentException("상대편의 말만 잡을 수 있습니다."); + } + } } diff --git a/src/main/java/chess/piece/Piece.java b/src/main/java/chess/piece/Piece.java index 8c67ef89f15..eba57d28c9b 100644 --- a/src/main/java/chess/piece/Piece.java +++ b/src/main/java/chess/piece/Piece.java @@ -5,7 +5,7 @@ import chess.board.Board; public abstract class Piece { - private final Color color; + protected final Color color; protected Piece(final Color color) { this.color = color; From 44a4dfa133a87dea50015d3242a6e0db17dab506 Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 14:33:02 +0900 Subject: [PATCH 06/25] =?UTF-8?q?feat:=20Bishop=EC=9D=98=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EA=B0=80=EB=8A=A5=ED=95=9C=20=EA=B2=BD=EC=9A=B0?= =?UTF-8?q?=EC=9D=98=20=EC=88=98=EB=A5=BC=20=EC=B4=88=EA=B8=B0=ED=99=94?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/piece/Bishop.java | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/main/java/chess/piece/Bishop.java b/src/main/java/chess/piece/Bishop.java index 08876a8df7d..fe7d307a34b 100644 --- a/src/main/java/chess/piece/Bishop.java +++ b/src/main/java/chess/piece/Bishop.java @@ -1,10 +1,31 @@ package chess.piece; +import static chess.Movement.LEFT_DOWN; +import static chess.Movement.LEFT_UP; +import static chess.Movement.RIGHT_DOWN; +import static chess.Movement.RIGHT_UP; + import chess.Color; +import chess.Movement; import chess.Position; import chess.board.Board; +import java.util.ArrayList; +import java.util.List; public class Bishop extends Piece { + public static List> allMovements = new ArrayList<>(); + + static { + for (Movement movement : List.of(LEFT_UP, RIGHT_UP, RIGHT_DOWN, LEFT_DOWN)) { + for (int i = 1; i < 8; i++) { + List movements = new ArrayList<>(); + for (int j = 0; j < i; j++) { + movements.add(movement); + } + allMovements.add(movements); + } + } + } public Bishop(final Color color) { super(color); From 7bf7bb7946febb018a42b8050e4ad8830b0727c1 Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 14:40:53 +0900 Subject: [PATCH 07/25] =?UTF-8?q?feat:=20Bishop=EC=9D=B4=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EB=B6=88=EA=B0=80=EB=8A=A5=ED=95=9C=20=EA=B2=BD?= =?UTF-8?q?=EC=9A=B0=EC=97=90=20=EC=98=88=EC=99=B8=EB=A5=BC=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 비숍 특성 상 움직일 수 없는 경로인 경우/중간에 다른 기물이 있는 경우/ 도착지에 존재하는 피스가 같은 팀인 경우 --- src/main/java/chess/board/Board.java | 5 ++++ src/main/java/chess/piece/Bishop.java | 40 +++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/main/java/chess/board/Board.java b/src/main/java/chess/board/Board.java index 3948a6e07d5..4d311696c8d 100644 --- a/src/main/java/chess/board/Board.java +++ b/src/main/java/chess/board/Board.java @@ -8,4 +8,9 @@ public boolean sameColorPieceExists(Position goal, Color color) { // TODO return false; } + + public boolean isPieceExists(Position position) { + // TODO + return false; + } } diff --git a/src/main/java/chess/piece/Bishop.java b/src/main/java/chess/piece/Bishop.java index fe7d307a34b..b8edab0e000 100644 --- a/src/main/java/chess/piece/Bishop.java +++ b/src/main/java/chess/piece/Bishop.java @@ -33,6 +33,46 @@ public Bishop(final Color color) { @Override public void validateMovable(Board board, Position start, Position goal) { + List root = findRoot(start, goal); + validateMiddlePath(board, root); + validateSameColorPieceOnGoal(board, goal); + } + + private static void validateMiddlePath(Board board, List root) { + root.removeFirst(); + root.removeLast(); + for (Position position : root) { + if (board.isPieceExists(position)) { + throw new IllegalArgumentException("중간에 다른 기물을 뛰어넘을 수 없습니다."); + } + } + } + + /** + * 제자리로 움직이는 경우 TODO + */ + private List findRoot(Position start, Position goal) { + for (List movements : allMovements) { + List root = new ArrayList<>(); + Position now = start; + root.add(now); + for (Movement movement : movements) { + if (now.canNotMove(movement)) { + break; + } + now = now.move(movement); + root.add(now); + } + if (now.equals(goal)) { + return root; + } + } + throw new IllegalArgumentException("경로가 존재하지 않습니다."); + } + private void validateSameColorPieceOnGoal(Board board, Position goal) { + if (board.sameColorPieceExists(goal, color)) { + throw new IllegalArgumentException("상대편의 말만 잡을 수 있습니다."); + } } } From ade188b5fc39056fc224ad1760742e4d7a333d87 Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 14:46:38 +0900 Subject: [PATCH 08/25] =?UTF-8?q?feat:=20=EA=B8=B0=EB=AC=BC=EC=9D=98=20?= =?UTF-8?q?=EC=9B=80=EC=A7=81=EC=9E=84=EC=9D=84=20=EC=B2=B4=ED=81=AC?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B3=B5=ED=86=B5=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=EC=9D=84=20Piece=20=EC=83=81=EC=9C=84=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=EC=97=90=20=EA=B5=AC=ED=98=84=ED=95=9C=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/Application.java | 11 +++++++++++ src/main/java/chess/piece/Bishop.java | 21 +++------------------ src/main/java/chess/piece/King.java | 20 ++++++++------------ src/main/java/chess/piece/Knight.java | 8 +++++++- src/main/java/chess/piece/Pawn.java | 9 ++++++++- src/main/java/chess/piece/Piece.java | 20 +++++++++++++++++++- src/main/java/chess/piece/Queen.java | 8 +++++++- src/main/java/chess/piece/Rook.java | 8 +++++++- 8 files changed, 70 insertions(+), 35 deletions(-) create mode 100644 src/main/java/chess/Application.java diff --git a/src/main/java/chess/Application.java b/src/main/java/chess/Application.java new file mode 100644 index 00000000000..12a09b867fe --- /dev/null +++ b/src/main/java/chess/Application.java @@ -0,0 +1,11 @@ +package chess; + +import static chess.Color.*; + +import chess.piece.Bishop; + +public class Application { + public static void main(String[] args) { + Bishop bishop = new Bishop(BLACK); + } +} diff --git a/src/main/java/chess/piece/Bishop.java b/src/main/java/chess/piece/Bishop.java index b8edab0e000..44227da67f9 100644 --- a/src/main/java/chess/piece/Bishop.java +++ b/src/main/java/chess/piece/Bishop.java @@ -13,6 +13,7 @@ import java.util.List; public class Bishop extends Piece { + public static List> allMovements = new ArrayList<>(); static { @@ -31,14 +32,7 @@ public Bishop(final Color color) { super(color); } - @Override - public void validateMovable(Board board, Position start, Position goal) { - List root = findRoot(start, goal); - validateMiddlePath(board, root); - validateSameColorPieceOnGoal(board, goal); - } - - private static void validateMiddlePath(Board board, List root) { + protected void validateMiddlePath(Board board, List root) { root.removeFirst(); root.removeLast(); for (Position position : root) { @@ -48,10 +42,7 @@ private static void validateMiddlePath(Board board, List root) { } } - /** - * 제자리로 움직이는 경우 TODO - */ - private List findRoot(Position start, Position goal) { + protected List findRoot(Position start, Position goal) { for (List movements : allMovements) { List root = new ArrayList<>(); Position now = start; @@ -69,10 +60,4 @@ private List findRoot(Position start, Position goal) { } throw new IllegalArgumentException("경로가 존재하지 않습니다."); } - - private void validateSameColorPieceOnGoal(Board board, Position goal) { - if (board.sameColorPieceExists(goal, color)) { - throw new IllegalArgumentException("상대편의 말만 잡을 수 있습니다."); - } - } } diff --git a/src/main/java/chess/piece/King.java b/src/main/java/chess/piece/King.java index 26b9e53b964..f4c67df96ff 100644 --- a/src/main/java/chess/piece/King.java +++ b/src/main/java/chess/piece/King.java @@ -8,6 +8,7 @@ import java.util.List; public class King extends Piece { + public static List> allMovements = new ArrayList<>(); static { @@ -25,31 +26,26 @@ public King(final Color color) { super(color); } - @Override - public void validateMovable(Board board, Position start, Position goal) { - findRoot(start, goal); - validateSameTeamOnGoal(board, goal); - } - - private List findRoot(Position start, Position goal) { + protected List findRoot(Position start, Position goal) { for (List movements : allMovements) { + List root = new ArrayList<>(); Position now = start; + root.add(now); for (Movement movement : movements) { if (now.canNotMove(movement)) { break; } now = now.move(movement); + root.add(now); } if (now.equals(goal)) { - return movements; + return root; } } throw new IllegalArgumentException("경로가 존재하지 않습니다."); } - private void validateSameTeamOnGoal(Board board, Position goal) { - if (board.sameColorPieceExists(goal, color)) { - throw new IllegalArgumentException("상대편의 말만 잡을 수 있습니다."); - } + @Override + protected void validateMiddlePath(Board board, List root) { } } diff --git a/src/main/java/chess/piece/Knight.java b/src/main/java/chess/piece/Knight.java index c97c3050695..1bd3f14e5f0 100644 --- a/src/main/java/chess/piece/Knight.java +++ b/src/main/java/chess/piece/Knight.java @@ -3,6 +3,7 @@ import chess.Color; import chess.Position; import chess.board.Board; +import java.util.List; public class Knight extends Piece { @@ -11,7 +12,12 @@ public Knight(final Color color) { } @Override - public void validateMovable(Board board, Position start, Position goal) { + protected List findRoot(Position start, Position goal) { + return List.of(); + } + + @Override + protected void validateMiddlePath(Board board, List root) { } } diff --git a/src/main/java/chess/piece/Pawn.java b/src/main/java/chess/piece/Pawn.java index 8788feb1127..8b304da50df 100644 --- a/src/main/java/chess/piece/Pawn.java +++ b/src/main/java/chess/piece/Pawn.java @@ -3,14 +3,21 @@ import chess.Color; import chess.Position; import chess.board.Board; +import java.util.List; public class Pawn extends Piece { + public Pawn(final Color color) { super(color); } @Override - public void validateMovable(Board board, Position start, Position goal) { + protected List findRoot(Position start, Position goal) { + return List.of(); + } + + @Override + protected void validateMiddlePath(Board board, List root) { } } diff --git a/src/main/java/chess/piece/Piece.java b/src/main/java/chess/piece/Piece.java index eba57d28c9b..e48731d286e 100644 --- a/src/main/java/chess/piece/Piece.java +++ b/src/main/java/chess/piece/Piece.java @@ -3,13 +3,31 @@ import chess.Color; import chess.Position; import chess.board.Board; +import java.util.List; public abstract class Piece { + protected final Color color; protected Piece(final Color color) { this.color = color; } - public abstract void validateMovable(Board board, Position start, Position goal); + public void validateMovable(Board board, Position start, Position goal) { + List root = findRoot(start, goal); + validateMiddlePath(board, root); + validateSameColorPieceOnGoal(board, goal); + } + + private void validateSameColorPieceOnGoal(Board board, Position goal) { + if (board.sameColorPieceExists(goal, color)) { + throw new IllegalArgumentException("상대편의 말만 잡을 수 있습니다."); + } + } + + /** + * 제자리로 움직이는 경우 TODO + */ + protected abstract List findRoot(Position start, Position goal); + protected abstract void validateMiddlePath(Board board, List root); } diff --git a/src/main/java/chess/piece/Queen.java b/src/main/java/chess/piece/Queen.java index c602bdc5cff..65e8c658f22 100644 --- a/src/main/java/chess/piece/Queen.java +++ b/src/main/java/chess/piece/Queen.java @@ -3,6 +3,7 @@ import chess.Color; import chess.Position; import chess.board.Board; +import java.util.List; public class Queen extends Piece { @@ -11,7 +12,12 @@ public Queen(final Color color) { } @Override - public void validateMovable(Board board, Position start, Position goal) { + protected List findRoot(Position start, Position goal) { + return List.of(); + } + + @Override + protected void validateMiddlePath(Board board, List root) { } } diff --git a/src/main/java/chess/piece/Rook.java b/src/main/java/chess/piece/Rook.java index fa9e10b0a90..e1ca63382bf 100644 --- a/src/main/java/chess/piece/Rook.java +++ b/src/main/java/chess/piece/Rook.java @@ -3,6 +3,7 @@ import chess.Color; import chess.Position; import chess.board.Board; +import java.util.List; public class Rook extends Piece { @@ -11,7 +12,12 @@ public Rook(final Color color) { } @Override - public void validateMovable(Board board, Position start, Position goal) { + protected List findRoot(Position start, Position goal) { + return List.of(); + } + + @Override + protected void validateMiddlePath(Board board, List root) { } } From 65f73040a5baf8e0fe7282cb4cdf97ae1dab4a2f Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 14:51:28 +0900 Subject: [PATCH 09/25] =?UTF-8?q?feat:=20Knight=EC=9D=98=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EA=B0=80=EB=8A=A5=ED=95=9C=20=EA=B2=BD=EC=9A=B0?= =?UTF-8?q?=EC=9D=98=20=EC=88=98=EB=A5=BC=20=EC=B4=88=EA=B8=B0=ED=99=94?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +-- src/main/java/chess/piece/Knight.java | 40 +++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0a5193caaae..76502f56878 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,9 @@ - 일직선으로 어떤 방향이든 원하는 만큼 이동할 수 있다. - [ ] 룩 - 일직선으로 앞/뒤/양옆으로 원하는 만큼 이동할 수 있다. - - [ ] 비숍 + - [x] 비숍 - 일직선으로 대각선을 원하는 만큼 이동할 수 있다. - - [ ] 나이트 + - [x] 나이트 - 한 방향으로 두칸을 이동하고 그와 90도를 이루는 방향으로 한칸 이동한다.(L자 모양) - 진행 경로에 다른 기물이 있어도 가로 막히지 않는다. - [ ] 폰 diff --git a/src/main/java/chess/piece/Knight.java b/src/main/java/chess/piece/Knight.java index 1bd3f14e5f0..aafa22ab193 100644 --- a/src/main/java/chess/piece/Knight.java +++ b/src/main/java/chess/piece/Knight.java @@ -1,23 +1,59 @@ package chess.piece; +import static chess.Movement.DOWN_DOWN_LEFT; +import static chess.Movement.DOWN_DOWN_RIGHT; +import static chess.Movement.LEFT_LEFT_DOWN; +import static chess.Movement.LEFT_LEFT_UP; +import static chess.Movement.RIGHT_RIGHT_DOWN; +import static chess.Movement.RIGHT_RIGHT_UP; +import static chess.Movement.UP_UP_LEFT; +import static chess.Movement.UP_UP_RIGHT; + import chess.Color; +import chess.Movement; import chess.Position; import chess.board.Board; +import java.util.ArrayList; import java.util.List; public class Knight extends Piece { + public static List> allMovements = new ArrayList<>(); + static { + allMovements.add(List.of(UP_UP_RIGHT)); + allMovements.add(List.of(UP_UP_LEFT)); + allMovements.add(List.of(DOWN_DOWN_RIGHT)); + allMovements.add(List.of(DOWN_DOWN_LEFT)); + allMovements.add(List.of(LEFT_LEFT_UP)); + allMovements.add(List.of(LEFT_LEFT_DOWN)); + allMovements.add(List.of(RIGHT_RIGHT_UP)); + allMovements.add(List.of(RIGHT_RIGHT_DOWN)); + } public Knight(final Color color) { super(color); } @Override protected List findRoot(Position start, Position goal) { - return List.of(); + for (List movements : allMovements) { + List root = new ArrayList<>(); + Position now = start; + root.add(now); + for (Movement movement : movements) { + if (now.canNotMove(movement)) { + break; + } + now = now.move(movement); + root.add(now); + } + if (now.equals(goal)) { + return root; + } + } + throw new IllegalArgumentException("경로가 존재하지 않습니다."); } @Override protected void validateMiddlePath(Board board, List root) { - } } From 9837c633689873a3b3abd8d8c3795c1c5a700c42 Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 14:58:02 +0900 Subject: [PATCH 10/25] =?UTF-8?q?feat:=20Queen=EC=9D=98=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EA=B0=80=EB=8A=A5=ED=95=9C=20=EA=B2=BD=EC=9A=B0?= =?UTF-8?q?=EC=9D=98=20=EC=88=98=EB=A5=BC=20=EC=B4=88=EA=B8=B0=ED=99=94?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/chess/piece/Queen.java | 48 ++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 76502f56878..9746ee31c15 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ - [ ] 플레이어는 자신의 턴에 기물을 움직인다. - [x] 킹 - 어느 방향이든 위/아래/양옆/대각선을 한 칸씩 이동할 수 있다. - - [ ] 퀸 + - [x] 퀸 - 일직선으로 어떤 방향이든 원하는 만큼 이동할 수 있다. - [ ] 룩 - 일직선으로 앞/뒤/양옆으로 원하는 만큼 이동할 수 있다. diff --git a/src/main/java/chess/piece/Queen.java b/src/main/java/chess/piece/Queen.java index 65e8c658f22..5f7eb1b2e4a 100644 --- a/src/main/java/chess/piece/Queen.java +++ b/src/main/java/chess/piece/Queen.java @@ -1,23 +1,67 @@ package chess.piece; +import static chess.Movement.DOWN; +import static chess.Movement.LEFT; +import static chess.Movement.LEFT_DOWN; +import static chess.Movement.LEFT_UP; +import static chess.Movement.RIGHT; +import static chess.Movement.RIGHT_DOWN; +import static chess.Movement.RIGHT_UP; +import static chess.Movement.UP; + import chess.Color; +import chess.Movement; import chess.Position; import chess.board.Board; +import java.util.ArrayList; import java.util.List; public class Queen extends Piece { + public static List> allMovements = new ArrayList<>(); + static { + for (Movement movement : List.of(LEFT, RIGHT, DOWN, UP, LEFT_DOWN, LEFT_UP, RIGHT_UP, RIGHT_DOWN)) { + for (int i = 1; i < 8; i++) { + List movements = new ArrayList<>(); + for (int j = 0; j < i; j++) { + movements.add(movement); + } + allMovements.add(movements); + } + } + } public Queen(final Color color) { super(color); } @Override protected List findRoot(Position start, Position goal) { - return List.of(); + for (List movements : allMovements) { + List root = new ArrayList<>(); + Position now = start; + root.add(now); + for (Movement movement : movements) { + if (now.canNotMove(movement)) { + break; + } + now = now.move(movement); + root.add(now); + } + if (now.equals(goal)) { + return root; + } + } + throw new IllegalArgumentException("경로가 존재하지 않습니다."); } @Override protected void validateMiddlePath(Board board, List root) { - + root.removeFirst(); + root.removeLast(); + for (Position position : root) { + if (board.isPieceExists(position)) { + throw new IllegalArgumentException("중간에 다른 기물을 뛰어넘을 수 없습니다."); + } + } } } From 07d81a8983aff32a93adff767236f55630055afd Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 14:59:07 +0900 Subject: [PATCH 11/25] =?UTF-8?q?feat:=20Rook=EC=9D=98=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EA=B0=80=EB=8A=A5=ED=95=9C=20=EA=B2=BD=EC=9A=B0?= =?UTF-8?q?=EC=9D=98=20=EC=88=98=EB=A5=BC=20=EC=B4=88=EA=B8=B0=ED=99=94?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/chess/piece/Rook.java | 44 +++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9746ee31c15..65f800af9a0 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ - 어느 방향이든 위/아래/양옆/대각선을 한 칸씩 이동할 수 있다. - [x] 퀸 - 일직선으로 어떤 방향이든 원하는 만큼 이동할 수 있다. - - [ ] 룩 + - [x] 룩 - 일직선으로 앞/뒤/양옆으로 원하는 만큼 이동할 수 있다. - [x] 비숍 - 일직선으로 대각선을 원하는 만큼 이동할 수 있다. diff --git a/src/main/java/chess/piece/Rook.java b/src/main/java/chess/piece/Rook.java index e1ca63382bf..f64c489d361 100644 --- a/src/main/java/chess/piece/Rook.java +++ b/src/main/java/chess/piece/Rook.java @@ -1,23 +1,63 @@ package chess.piece; +import static chess.Movement.DOWN; +import static chess.Movement.LEFT; +import static chess.Movement.RIGHT; +import static chess.Movement.UP; + import chess.Color; +import chess.Movement; import chess.Position; import chess.board.Board; +import java.util.ArrayList; import java.util.List; public class Rook extends Piece { + public static List> allMovements = new ArrayList<>(); + static { + for (Movement movement : List.of(LEFT, RIGHT, DOWN, UP)) { + for (int i = 1; i < 8; i++) { + List movements = new ArrayList<>(); + for (int j = 0; j < i; j++) { + movements.add(movement); + } + allMovements.add(movements); + } + } + } public Rook(final Color color) { super(color); } @Override protected List findRoot(Position start, Position goal) { - return List.of(); + for (List movements : allMovements) { + List root = new ArrayList<>(); + Position now = start; + root.add(now); + for (Movement movement : movements) { + if (now.canNotMove(movement)) { + break; + } + now = now.move(movement); + root.add(now); + } + if (now.equals(goal)) { + return root; + } + } + throw new IllegalArgumentException("경로가 존재하지 않습니다."); } @Override protected void validateMiddlePath(Board board, List root) { - + root.removeFirst(); + root.removeLast(); + for (Position position : root) { + if (board.isPieceExists(position)) { + throw new IllegalArgumentException("중간에 다른 기물을 뛰어넘을 수 없습니다."); + } + } } } From 1f4591aab66f20aa60a0661af86b2baf08966257 Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 15:01:30 +0900 Subject: [PATCH 12/25] =?UTF-8?q?feat:=20Pawn=EC=9D=98=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EA=B0=80=EB=8A=A5=ED=95=9C=20=EA=B2=BD=EC=9A=B0?= =?UTF-8?q?=EC=9D=98=20=EC=88=98=EB=A5=BC=20=EC=B4=88=EA=B8=B0=ED=99=94?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- src/main/java/chess/piece/Pawn.java | 10 ++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 65f800af9a0..a20cc6dba43 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,9 @@ - 한 방향으로 두칸을 이동하고 그와 90도를 이루는 방향으로 한칸 이동한다.(L자 모양) - 진행 경로에 다른 기물이 있어도 가로 막히지 않는다. - [ ] 폰 - - 처음 움직이는 폰은 앞으로 두 칸까지 이동할 수 있다. - - 이후부터는 앞으로 한 칸씩만 이동할 수 있다. - - 잡을 때는 대각선으로 한 칸 앞에 있는 상대 기물만 잡을 수 있다. + - [ ] 처음 움직이는 폰은 앞으로 두 칸까지 이동할 수 있다. + - [ ] 이후부터는 앞으로 한 칸씩만 이동할 수 있다. + - [ ] 잡을 때는 대각선으로 한 칸 앞에 있는 상대 기물만 잡을 수 있다. - 이동 규칙 - [ ] 나이트를 제외한 모든 기물은 다른 기물을 뛰어 넘을 수 없다. - [ ] 상대편의 말만 잡을 수 있다. diff --git a/src/main/java/chess/piece/Pawn.java b/src/main/java/chess/piece/Pawn.java index 8b304da50df..c7f6524987e 100644 --- a/src/main/java/chess/piece/Pawn.java +++ b/src/main/java/chess/piece/Pawn.java @@ -1,11 +1,21 @@ package chess.piece; import chess.Color; +import chess.Movement; import chess.Position; import chess.board.Board; +import java.util.ArrayList; import java.util.List; public class Pawn extends Piece { + public static List> allMovements = new ArrayList<>(); + + static { + allMovements.add(List.of(Movement.UP)); + allMovements.add(List.of(Movement.UP_UP)); + allMovements.add(List.of(Movement.LEFT_UP)); + allMovements.add(List.of(Movement.RIGHT_UP)); + } public Pawn(final Color color) { super(color); From fcd814032a44525a42ea30f59745ac03db5a1a01 Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 15:08:26 +0900 Subject: [PATCH 13/25] =?UTF-8?q?feat:=20=EC=B2=98=EC=9D=8C=20=EC=9B=80?= =?UTF-8?q?=EC=A7=81=EC=9D=B4=EB=8A=94=20Pawn=EB=A7=8C=20=EC=95=9E?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=91=90=20=EC=B9=B8=EA=B9=8C=EC=A7=80=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- src/main/java/chess/piece/Pawn.java | 35 ++++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index a20cc6dba43..02e11ec46d3 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,8 @@ - 한 방향으로 두칸을 이동하고 그와 90도를 이루는 방향으로 한칸 이동한다.(L자 모양) - 진행 경로에 다른 기물이 있어도 가로 막히지 않는다. - [ ] 폰 - - [ ] 처음 움직이는 폰은 앞으로 두 칸까지 이동할 수 있다. - - [ ] 이후부터는 앞으로 한 칸씩만 이동할 수 있다. + - [x] 처음 움직이는 폰은 앞으로 두 칸까지 이동할 수 있다. + - [x] 이후부터는 앞으로 한 칸씩만 이동할 수 있다. - [ ] 잡을 때는 대각선으로 한 칸 앞에 있는 상대 기물만 잡을 수 있다. - 이동 규칙 - [ ] 나이트를 제외한 모든 기물은 다른 기물을 뛰어 넘을 수 없다. diff --git a/src/main/java/chess/piece/Pawn.java b/src/main/java/chess/piece/Pawn.java index c7f6524987e..b666537f697 100644 --- a/src/main/java/chess/piece/Pawn.java +++ b/src/main/java/chess/piece/Pawn.java @@ -1,5 +1,11 @@ package chess.piece; +import static chess.Movement.LEFT_UP; +import static chess.Movement.RIGHT_UP; +import static chess.Movement.UP; +import static chess.Movement.UP_UP; +import static chess.Row.TWO; + import chess.Color; import chess.Movement; import chess.Position; @@ -11,10 +17,10 @@ public class Pawn extends Piece { public static List> allMovements = new ArrayList<>(); static { - allMovements.add(List.of(Movement.UP)); - allMovements.add(List.of(Movement.UP_UP)); - allMovements.add(List.of(Movement.LEFT_UP)); - allMovements.add(List.of(Movement.RIGHT_UP)); + allMovements.add(List.of(UP)); + allMovements.add(List.of(UP_UP)); + allMovements.add(List.of(LEFT_UP)); + allMovements.add(List.of(RIGHT_UP)); } public Pawn(final Color color) { @@ -23,11 +29,28 @@ public Pawn(final Color color) { @Override protected List findRoot(Position start, Position goal) { - return List.of(); + for (List movements : allMovements) { + List root = new ArrayList<>(); + Position now = start; + root.add(now); + for (Movement movement : movements) { + if (now.canNotMove(movement)) { + break; + } + now = now.move(movement); + root.add(now); + } + if (now.equals(goal)) { + if (start.row() != TWO && movements.contains(UP_UP)) { + throw new IllegalArgumentException("처음 움직이는 폰만 앞으로 두 칸을 이동할 수 있습니다."); + } + return root; + } + } + throw new IllegalArgumentException("경로가 존재하지 않습니다."); } @Override protected void validateMiddlePath(Board board, List root) { - } } From 0a8cb861118143b87a4aefbeba9ba7a665ab0e5d Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 15:25:29 +0900 Subject: [PATCH 14/25] =?UTF-8?q?feat:=20=EC=B2=B4=EC=8A=A4=ED=8C=90?= =?UTF-8?q?=EC=9D=84=20=EC=B4=88=EA=B8=B0=ED=99=94=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/Application.java | 47 +++++++++++++++++++++++++++- src/main/java/chess/board/Board.java | 11 ++++++- src/main/java/chess/piece/Piece.java | 2 +- 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/main/java/chess/Application.java b/src/main/java/chess/Application.java index 12a09b867fe..d14438b36cb 100644 --- a/src/main/java/chess/Application.java +++ b/src/main/java/chess/Application.java @@ -1,11 +1,56 @@ package chess; import static chess.Color.*; +import static chess.Column.*; +import static chess.Row.*; +import chess.board.Board; import chess.piece.Bishop; +import chess.piece.King; +import chess.piece.Knight; +import chess.piece.Pawn; +import chess.piece.Piece; +import chess.piece.Queen; +import chess.piece.Rook; +import java.util.HashMap; +import java.util.Map; public class Application { public static void main(String[] args) { - Bishop bishop = new Bishop(BLACK); + Board board = new Board(makeInitialBoard()); + } + + private static Map makeInitialBoard() { + Map board = new HashMap<>(); + initPawns(board); + board.put(new Position(ONE, A), new Rook(WHITE)); + board.put(new Position(ONE, H), new Rook(WHITE)); + board.put(new Position(EIGHT, A), new Rook(BLACK)); + board.put(new Position(EIGHT, H), new Rook(BLACK)); + + board.put(new Position(ONE, B), new Knight(WHITE)); + board.put(new Position(ONE, G), new Knight(WHITE)); + board.put(new Position(EIGHT, B), new Knight(BLACK)); + board.put(new Position(EIGHT, G), new Knight(BLACK)); + + board.put(new Position(ONE, C), new Bishop(WHITE)); + board.put(new Position(ONE, F), new Bishop(WHITE)); + board.put(new Position(EIGHT, C), new Bishop(BLACK)); + board.put(new Position(EIGHT, F), new Bishop(BLACK)); + + board.put(new Position(ONE, D), new Queen(WHITE)); + board.put(new Position(EIGHT, D), new Queen(BLACK)); + + board.put(new Position(ONE, E), new King(WHITE)); + board.put(new Position(EIGHT, E), new King(BLACK)); + + return board; + } + + private static void initPawns(Map board) { + for (Column column : Column.values()) { + board.put(new Position(TWO, column), new Pawn(WHITE)); + board.put(new Position(SEVEN, column), new Pawn(BLACK)); + } } } diff --git a/src/main/java/chess/board/Board.java b/src/main/java/chess/board/Board.java index 4d311696c8d..469570b963f 100644 --- a/src/main/java/chess/board/Board.java +++ b/src/main/java/chess/board/Board.java @@ -2,9 +2,18 @@ import chess.Color; import chess.Position; +import chess.piece.Piece; +import java.util.HashMap; +import java.util.Map; public class Board { - public boolean sameColorPieceExists(Position goal, Color color) { + private final Map board; + + public Board(Map board) { + this.board = new HashMap<>(board); + } + + public boolean isSameColorPieceExists(Position goal, Color color) { // TODO return false; } diff --git a/src/main/java/chess/piece/Piece.java b/src/main/java/chess/piece/Piece.java index e48731d286e..339baea8f2d 100644 --- a/src/main/java/chess/piece/Piece.java +++ b/src/main/java/chess/piece/Piece.java @@ -20,7 +20,7 @@ public void validateMovable(Board board, Position start, Position goal) { } private void validateSameColorPieceOnGoal(Board board, Position goal) { - if (board.sameColorPieceExists(goal, color)) { + if (board.isSameColorPieceExists(goal, color)) { throw new IllegalArgumentException("상대편의 말만 잡을 수 있습니다."); } } From 4e7ead90337b54a63c9c2fe35fea95a26e4e0526 Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 15:41:06 +0900 Subject: [PATCH 15/25] =?UTF-8?q?test:=20=EA=B2=BD=EB=A1=9C=20=EC=A4=91?= =?UTF-8?q?=EA=B0=84=EC=97=90=20=EA=B8=B0=EB=AC=BC=EC=9D=B4=20=EC=A1=B4?= =?UTF-8?q?=EC=9E=AC=ED=95=98=EB=A9=B4=20=EC=98=88=EC=99=B8=EB=A5=BC=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/board/Board.java | 9 +++- src/test/java/chess/Fixtures.java | 57 ++++++++++++++++++++++++ src/test/java/chess/board/BoardTest.java | 19 ++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 src/test/java/chess/board/BoardTest.java diff --git a/src/main/java/chess/board/Board.java b/src/main/java/chess/board/Board.java index 469570b963f..5a62f62f4cb 100644 --- a/src/main/java/chess/board/Board.java +++ b/src/main/java/chess/board/Board.java @@ -13,13 +13,18 @@ public Board(Map board) { this.board = new HashMap<>(board); } + public void move(Position start, Position goal) { + Piece piece = board.get(start); + piece.validateMovable(this, start, goal); + } + public boolean isSameColorPieceExists(Position goal, Color color) { // TODO return false; } public boolean isPieceExists(Position position) { - // TODO - return false; + Piece piece = board.get(position); + return piece != null; } } diff --git a/src/test/java/chess/Fixtures.java b/src/test/java/chess/Fixtures.java index f940ab37137..ec07e8dc66d 100644 --- a/src/test/java/chess/Fixtures.java +++ b/src/test/java/chess/Fixtures.java @@ -1,5 +1,31 @@ package chess; +import static chess.Color.BLACK; +import static chess.Color.WHITE; +import static chess.Column.A; +import static chess.Column.B; +import static chess.Column.C; +import static chess.Column.D; +import static chess.Column.E; +import static chess.Column.F; +import static chess.Column.G; +import static chess.Column.H; +import static chess.Row.EIGHT; +import static chess.Row.ONE; +import static chess.Row.SEVEN; +import static chess.Row.TWO; + +import chess.board.Board; +import chess.piece.Bishop; +import chess.piece.King; +import chess.piece.Knight; +import chess.piece.Pawn; +import chess.piece.Piece; +import chess.piece.Queen; +import chess.piece.Rook; +import java.util.HashMap; +import java.util.Map; + @SuppressWarnings("unused") public final class Fixtures { @@ -74,7 +100,38 @@ public final class Fixtures { public static final Position H6 = new Position(Column.H, Row.SIX); public static final Position H7 = new Position(Column.H, Row.SEVEN); public static final Position H8 = new Position(Column.H, Row.EIGHT); + public static final Board generalBoard = new Board(makeGeneralBoard()); private Fixtures() { } + + private static Map makeGeneralBoard() { + Map board = new HashMap<>(); + for (Column column : Column.values()) { + board.put(new Position(TWO, column), new Pawn(WHITE)); + board.put(new Position(SEVEN, column), new Pawn(BLACK)); + } + board.put(new Position(ONE, A), new Rook(WHITE)); + board.put(new Position(ONE, H), new Rook(WHITE)); + board.put(new Position(EIGHT, A), new Rook(BLACK)); + board.put(new Position(EIGHT, H), new Rook(BLACK)); + + board.put(new Position(ONE, B), new Knight(WHITE)); + board.put(new Position(ONE, G), new Knight(WHITE)); + board.put(new Position(EIGHT, B), new Knight(BLACK)); + board.put(new Position(EIGHT, G), new Knight(BLACK)); + + board.put(new Position(ONE, C), new Bishop(WHITE)); + board.put(new Position(ONE, F), new Bishop(WHITE)); + board.put(new Position(EIGHT, C), new Bishop(BLACK)); + board.put(new Position(EIGHT, F), new Bishop(BLACK)); + + board.put(new Position(ONE, D), new Queen(WHITE)); + board.put(new Position(EIGHT, D), new Queen(BLACK)); + + board.put(new Position(ONE, E), new King(WHITE)); + board.put(new Position(EIGHT, E), new King(BLACK)); + + return board; + } } diff --git a/src/test/java/chess/board/BoardTest.java b/src/test/java/chess/board/BoardTest.java new file mode 100644 index 00000000000..b2fbe555600 --- /dev/null +++ b/src/test/java/chess/board/BoardTest.java @@ -0,0 +1,19 @@ +package chess.board; + +import static chess.Fixtures.A1; +import static chess.Fixtures.A3; +import static chess.Fixtures.generalBoard; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +class BoardTest { + @Test + void move() { + //when + //then + Assertions.assertThatThrownBy(() -> generalBoard.move(A1, A3)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("중간에 다른 기물을 뛰어넘을 수 없습니다."); + } +} From c22dd29f07bedd24b605aba7716d2e03144ec3d6 Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 15:44:46 +0900 Subject: [PATCH 16/25] =?UTF-8?q?test:=20=EA=B0=99=EC=9D=80=20=EC=83=89?= =?UTF-8?q?=EA=B9=94=EC=9D=98=20=EA=B8=B0=EB=AC=BC=EC=9D=84=20=EC=9E=A1?= =?UTF-8?q?=EC=9C=BC=EB=A0=A4=EA=B3=A0=20=ED=95=98=EB=A9=B4=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=EB=A5=BC=20=EB=B0=9C=EC=83=9D=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/board/Board.java | 4 ++-- src/main/java/chess/piece/Piece.java | 4 ++++ src/test/java/chess/board/BoardTest.java | 18 +++++++++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/main/java/chess/board/Board.java b/src/main/java/chess/board/Board.java index 5a62f62f4cb..19c62b85817 100644 --- a/src/main/java/chess/board/Board.java +++ b/src/main/java/chess/board/Board.java @@ -19,8 +19,8 @@ public void move(Position start, Position goal) { } public boolean isSameColorPieceExists(Position goal, Color color) { - // TODO - return false; + Piece piece = board.get(goal); + return piece.isSameColor(color); } public boolean isPieceExists(Position position) { diff --git a/src/main/java/chess/piece/Piece.java b/src/main/java/chess/piece/Piece.java index 339baea8f2d..44c4a82e325 100644 --- a/src/main/java/chess/piece/Piece.java +++ b/src/main/java/chess/piece/Piece.java @@ -30,4 +30,8 @@ private void validateSameColorPieceOnGoal(Board board, Position goal) { */ protected abstract List findRoot(Position start, Position goal); protected abstract void validateMiddlePath(Board board, List root); + + public boolean isSameColor(Color other) { + return color == other; + } } diff --git a/src/test/java/chess/board/BoardTest.java b/src/test/java/chess/board/BoardTest.java index b2fbe555600..ea5adf44588 100644 --- a/src/test/java/chess/board/BoardTest.java +++ b/src/test/java/chess/board/BoardTest.java @@ -1,19 +1,35 @@ package chess.board; import static chess.Fixtures.A1; +import static chess.Fixtures.A2; import static chess.Fixtures.A3; import static chess.Fixtures.generalBoard; import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +/** + * Test 위치 조정 TODO + */ class BoardTest { + @DisplayName("중간에_다른_기물이_존재하면_예외를_발생한다") @Test - void move() { + void move1() { //when //then Assertions.assertThatThrownBy(() -> generalBoard.move(A1, A3)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("중간에 다른 기물을 뛰어넘을 수 없습니다."); } + + @DisplayName("도착지에_같은_색깔의_말이_존재하면_예외를_발생한다") + @Test + void move2() { + //when + //then + Assertions.assertThatThrownBy(() -> generalBoard.move(A1, A2)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("상대편의 말만 잡을 수 있습니다."); + } } From 0637b6f7744b8d04b269b9189ed1f9f05eb80bc6 Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 15:48:04 +0900 Subject: [PATCH 17/25] =?UTF-8?q?test:=20Knight=EB=8A=94=20=EC=A4=91?= =?UTF-8?q?=EA=B0=84=20=EA=B8=B0=EB=AC=BC=EC=9D=84=20=EB=9B=B0=EC=96=B4?= =?UTF-8?q?=EB=84=98=EC=9D=84=20=EC=88=98=20=EC=9E=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/board/Board.java | 3 +++ src/test/java/chess/board/BoardTest.java | 3 --- src/test/java/chess/piece/KnightTest.java | 20 ++++++++++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 src/test/java/chess/piece/KnightTest.java diff --git a/src/main/java/chess/board/Board.java b/src/main/java/chess/board/Board.java index 19c62b85817..68173566909 100644 --- a/src/main/java/chess/board/Board.java +++ b/src/main/java/chess/board/Board.java @@ -20,6 +20,9 @@ public void move(Position start, Position goal) { public boolean isSameColorPieceExists(Position goal, Color color) { Piece piece = board.get(goal); + if (piece == null) { + return false; + } return piece.isSameColor(color); } diff --git a/src/test/java/chess/board/BoardTest.java b/src/test/java/chess/board/BoardTest.java index ea5adf44588..19c70de0b13 100644 --- a/src/test/java/chess/board/BoardTest.java +++ b/src/test/java/chess/board/BoardTest.java @@ -9,9 +9,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -/** - * Test 위치 조정 TODO - */ class BoardTest { @DisplayName("중간에_다른_기물이_존재하면_예외를_발생한다") @Test diff --git a/src/test/java/chess/piece/KnightTest.java b/src/test/java/chess/piece/KnightTest.java new file mode 100644 index 00000000000..dbd93a62e4b --- /dev/null +++ b/src/test/java/chess/piece/KnightTest.java @@ -0,0 +1,20 @@ +package chess.piece; + +import static chess.Fixtures.A3; +import static chess.Fixtures.B1; +import static chess.Fixtures.generalBoard; +import static org.assertj.core.api.Assertions.assertThatCode; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class KnightTest { + @DisplayName("Knight는_중간에_다른_기물을_뛰어넘을_수_있다") + @Test + void move1() { + //when + //then + assertThatCode(() -> generalBoard.move(B1, A3)) + .doesNotThrowAnyException(); + } +} From 4c54227a5a64c6c5e081d1d175c411b370b5c884 Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 15:52:40 +0900 Subject: [PATCH 18/25] =?UTF-8?q?test:=20=EC=9D=B4=EB=AF=B8=20=EC=9B=80?= =?UTF-8?q?=EC=A7=81=EC=9D=B8=20Pawn=EC=9D=B4=20=EC=95=9E=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=91=90=EC=B9=B8=20=EC=9D=B4=EB=8F=99=20=EC=8B=9C?= =?UTF-8?q?=20=EC=98=88=EC=99=B8=EB=A5=BC=20=EB=B0=9C=EC=83=9D=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/board/Board.java | 2 ++ src/test/java/chess/piece/PawnTest.java | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/test/java/chess/piece/PawnTest.java diff --git a/src/main/java/chess/board/Board.java b/src/main/java/chess/board/Board.java index 68173566909..2ae35a029bf 100644 --- a/src/main/java/chess/board/Board.java +++ b/src/main/java/chess/board/Board.java @@ -16,6 +16,8 @@ public Board(Map board) { public void move(Position start, Position goal) { Piece piece = board.get(start); piece.validateMovable(this, start, goal); + board.put(goal, piece); + board.remove(start); } public boolean isSameColorPieceExists(Position goal, Color color) { diff --git a/src/test/java/chess/piece/PawnTest.java b/src/test/java/chess/piece/PawnTest.java new file mode 100644 index 00000000000..c66093e57fc --- /dev/null +++ b/src/test/java/chess/piece/PawnTest.java @@ -0,0 +1,24 @@ +package chess.piece; + +import static chess.Fixtures.A2; +import static chess.Fixtures.A3; +import static chess.Fixtures.A5; +import static chess.Fixtures.generalBoard; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class PawnTest { + @DisplayName("이미_움직인_폰이_앞으로_두칸을_이동하면_예외를_발생한다") + @Test + void move1() { + //when + generalBoard.move(A2, A3); + + //then + assertThatThrownBy(() -> generalBoard.move(A3, A5)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("처음 움직이는 폰만 앞으로 두 칸을 이동할 수 있습니다."); + } +} From 54f963ebeb48940dc8a95e55fd39c7e672cfb9aa Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 16:07:13 +0900 Subject: [PATCH 19/25] =?UTF-8?q?test:=20Knight=EC=9D=98=20=EC=A0=95?= =?UTF-8?q?=EC=83=81=EC=A0=81=EC=9D=B8=20=EC=9D=B4=EB=8F=99=EC=9D=84=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/piece/Piece.java | 1 + src/test/java/chess/Fixtures.java | 5 ++- src/test/java/chess/board/BoardTest.java | 16 +++++++--- src/test/java/chess/piece/KnightTest.java | 37 +++++++++++++++++++++-- src/test/java/chess/piece/PawnTest.java | 10 ++++-- 5 files changed, 56 insertions(+), 13 deletions(-) diff --git a/src/main/java/chess/piece/Piece.java b/src/main/java/chess/piece/Piece.java index 44c4a82e325..77126d852f1 100644 --- a/src/main/java/chess/piece/Piece.java +++ b/src/main/java/chess/piece/Piece.java @@ -16,6 +16,7 @@ protected Piece(final Color color) { public void validateMovable(Board board, Position start, Position goal) { List root = findRoot(start, goal); validateMiddlePath(board, root); + validateSameColorPieceOnGoal(board, goal); } diff --git a/src/test/java/chess/Fixtures.java b/src/test/java/chess/Fixtures.java index ec07e8dc66d..95509ace628 100644 --- a/src/test/java/chess/Fixtures.java +++ b/src/test/java/chess/Fixtures.java @@ -100,12 +100,11 @@ public final class Fixtures { public static final Position H6 = new Position(Column.H, Row.SIX); public static final Position H7 = new Position(Column.H, Row.SEVEN); public static final Position H8 = new Position(Column.H, Row.EIGHT); - public static final Board generalBoard = new Board(makeGeneralBoard()); private Fixtures() { } - private static Map makeGeneralBoard() { + public static Board makeGeneralBoard() { Map board = new HashMap<>(); for (Column column : Column.values()) { board.put(new Position(TWO, column), new Pawn(WHITE)); @@ -132,6 +131,6 @@ private static Map makeGeneralBoard() { board.put(new Position(ONE, E), new King(WHITE)); board.put(new Position(EIGHT, E), new King(BLACK)); - return board; + return new Board(board); } } diff --git a/src/test/java/chess/board/BoardTest.java b/src/test/java/chess/board/BoardTest.java index 19c70de0b13..fcd1e268fc9 100644 --- a/src/test/java/chess/board/BoardTest.java +++ b/src/test/java/chess/board/BoardTest.java @@ -3,7 +3,7 @@ import static chess.Fixtures.A1; import static chess.Fixtures.A2; import static chess.Fixtures.A3; -import static chess.Fixtures.generalBoard; +import static chess.Fixtures.makeGeneralBoard; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; @@ -13,8 +13,11 @@ class BoardTest { @DisplayName("중간에_다른_기물이_존재하면_예외를_발생한다") @Test void move1() { - //when - //then + // given + Board generalBoard = makeGeneralBoard(); + + // when + // then Assertions.assertThatThrownBy(() -> generalBoard.move(A1, A3)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("중간에 다른 기물을 뛰어넘을 수 없습니다."); @@ -23,8 +26,11 @@ void move1() { @DisplayName("도착지에_같은_색깔의_말이_존재하면_예외를_발생한다") @Test void move2() { - //when - //then + // given + Board generalBoard = makeGeneralBoard(); + + // when + // then Assertions.assertThatThrownBy(() -> generalBoard.move(A1, A2)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("상대편의 말만 잡을 수 있습니다."); diff --git a/src/test/java/chess/piece/KnightTest.java b/src/test/java/chess/piece/KnightTest.java index dbd93a62e4b..09d2aa7fb1d 100644 --- a/src/test/java/chess/piece/KnightTest.java +++ b/src/test/java/chess/piece/KnightTest.java @@ -2,11 +2,24 @@ import static chess.Fixtures.A3; import static chess.Fixtures.B1; -import static chess.Fixtures.generalBoard; +import static chess.Fixtures.D4; +import static chess.Fixtures.makeGeneralBoard; +import static org.assertj.core.api.Assertions.as; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.InstanceOfAssertFactories.MAP; +import chess.Color; +import chess.Column; +import chess.Position; +import chess.Row; +import chess.board.Board; +import java.util.HashMap; +import java.util.Map; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; class KnightTest { @DisplayName("Knight는_중간에_다른_기물을_뛰어넘을_수_있다") @@ -14,7 +27,27 @@ class KnightTest { void move1() { //when //then - assertThatCode(() -> generalBoard.move(B1, A3)) + assertThatCode(() -> makeGeneralBoard().move(B1, A3)) .doesNotThrowAnyException(); } + + @DisplayName("Knight는_적합한_경로일_시_이동할_수_있다") + @CsvSource(value = {"C:SIX", "E:SIX", "C:TWO", "E:TWO", "B:THREE", "B:FIVE", "F:THREE", "F:FIVE"}, + delimiterString = ":") + @ParameterizedTest + void move2(Column column, Row row) { + // given + Map initialBoard = new HashMap<>(); + Knight knight = new Knight(Color.WHITE); + initialBoard.put(D4, knight); + Board board = new Board(initialBoard); + Position goal = new Position(column, row); + + //when + board.move(D4, goal); + + //then + assertThat(board).extracting("board", as(MAP)) + .containsEntry(goal, knight); + } } diff --git a/src/test/java/chess/piece/PawnTest.java b/src/test/java/chess/piece/PawnTest.java index c66093e57fc..1fe5b8c5b45 100644 --- a/src/test/java/chess/piece/PawnTest.java +++ b/src/test/java/chess/piece/PawnTest.java @@ -3,9 +3,10 @@ import static chess.Fixtures.A2; import static chess.Fixtures.A3; import static chess.Fixtures.A5; -import static chess.Fixtures.generalBoard; +import static chess.Fixtures.makeGeneralBoard; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import chess.board.Board; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -13,10 +14,13 @@ class PawnTest { @DisplayName("이미_움직인_폰이_앞으로_두칸을_이동하면_예외를_발생한다") @Test void move1() { - //when + // given + Board generalBoard = makeGeneralBoard(); + + // when generalBoard.move(A2, A3); - //then + // then assertThatThrownBy(() -> generalBoard.move(A3, A5)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("처음 움직이는 폰만 앞으로 두 칸을 이동할 수 있습니다."); From 2c2aab5d167ef808b0459f4be57a021d1cd2afec Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 16:25:48 +0900 Subject: [PATCH 20/25] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EA=B0=80=20=ED=84=B4=EC=9D=84=20=EB=8F=8C=EB=A9=B0=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=EC=9D=84=20=EC=9E=85=EB=A0=A5=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +++--- src/main/java/chess/Application.java | 22 +++++++++++++++ src/main/java/chess/Column.java | 31 ++++++++++++++------ src/main/java/chess/Row.java | 42 ++++++++++++++++++++++------ 4 files changed, 83 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 02e11ec46d3..c2162fadee5 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ - [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md) ### 기능 목록 -- [ ] 초기 보드판을 구성한다. -- [ ] 플레이어가 턴을 주고 받는다. -- [ ] 플레이어는 자신의 턴에 기물을 움직인다. +- [x] 초기 보드판을 구성한다. +- [x] 플레이어가 턴을 주고 받는다. +- [x] 플레이어는 자신의 턴에 기물을 움직인다. - [x] 킹 - 어느 방향이든 위/아래/양옆/대각선을 한 칸씩 이동할 수 있다. - [x] 퀸 @@ -28,7 +28,7 @@ - 이동 규칙 - [ ] 나이트를 제외한 모든 기물은 다른 기물을 뛰어 넘을 수 없다. - [ ] 상대편의 말만 잡을 수 있다. - - [ ] 입력한 곳으로 이동할 수 없는 경우 예외를 발생한다. + - [x] 입력한 곳으로 이동할 수 없는 경우 예외를 발생한다. - [ ] 킹이 잡히면 잡힌 쪽이 패배하며 게임을 종료한다 diff --git a/src/main/java/chess/Application.java b/src/main/java/chess/Application.java index d14438b36cb..6c40d03439a 100644 --- a/src/main/java/chess/Application.java +++ b/src/main/java/chess/Application.java @@ -14,10 +14,32 @@ import chess.piece.Rook; import java.util.HashMap; import java.util.Map; +import java.util.Scanner; public class Application { + private static final Scanner scanner = new Scanner(System.in); + public static void main(String[] args) { Board board = new Board(makeInitialBoard()); + System.out.println("체스 게임을 시작합니다."); + Color currentColor = WHITE; + while(true) { + System.out.printf("%s 차례입니다.\n움직이려는 말의 좌표와 도착 좌표를 입력하세요.\n", currentColor); + String input = scanner.nextLine(); + String[] split = input.split(" "); + String[] startString = split[0].split(""); + String[] goalString = split[1].split(""); + Position start = createPosition(startString); + Position goal = createPosition(goalString); + board.move(start, goal); + currentColor = currentColor.opposite(); + } + } + + public static Position createPosition(String[] positionString) { + Column column = getColumn(positionString[0]); + Row row = getRow(positionString[1]); + return new Position(row, column); } private static Map makeInitialBoard() { diff --git a/src/main/java/chess/Column.java b/src/main/java/chess/Column.java index b64b4dc77a3..a857189dbb1 100644 --- a/src/main/java/chess/Column.java +++ b/src/main/java/chess/Column.java @@ -2,14 +2,29 @@ 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 value; + + Column(String value) { + this.value = value; + } + + public static Column getColumn(String value) { + for (Column column : values()) { + if (column.value.equals(value)) { + return column; + } + } + throw new IllegalArgumentException("유효하지 않은 Column입니다."); + } public boolean isFarLeft() { return ordinal() == 0; diff --git a/src/main/java/chess/Row.java b/src/main/java/chess/Row.java index 126ed048daa..5edf7560b0d 100644 --- a/src/main/java/chess/Row.java +++ b/src/main/java/chess/Row.java @@ -1,15 +1,41 @@ package chess; +import java.util.InputMismatchException; + 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 value; + + Row(int value) { + this.value = value; + } + + public static Row getRow(String value) { + try { + int intValue = Integer.parseInt(value); + return getRow(intValue); + } catch(NumberFormatException e) { + throw new IllegalArgumentException("유효하지 않은 Row입니다."); + } + } + + public static Row getRow(int value) { + for (Row row : values()) { + if (row.value == value) { + return row; + } + } + throw new IllegalArgumentException("유효하지 않은 Row입니다."); + } public boolean isTop() { return ordinal() == 0; From b12eb80841659c62374b0f93bce2d35e0395e61c Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 17:07:41 +0900 Subject: [PATCH 21/25] =?UTF-8?q?feat:=20=ED=9D=91=EC=83=89=20=EC=A7=84?= =?UTF-8?q?=EC=98=81=20=ED=8F=B0=EC=9D=80=20=ED=9D=B0=EC=83=89=20=EC=A7=84?= =?UTF-8?q?=EC=98=81=EA=B3=BC=20=EB=B0=98=EB=8C=80=EB=A1=9C=20=EC=9B=80?= =?UTF-8?q?=EC=A7=81=EC=9D=B8=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +++-- src/main/java/chess/piece/Pawn.java | 28 ++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index c2162fadee5..db576a2f768 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,10 @@ - [x] 처음 움직이는 폰은 앞으로 두 칸까지 이동할 수 있다. - [x] 이후부터는 앞으로 한 칸씩만 이동할 수 있다. - [ ] 잡을 때는 대각선으로 한 칸 앞에 있는 상대 기물만 잡을 수 있다. + - [x] 흑색 진영은 흰색 진영과 반대로 이동한다. - 이동 규칙 - - [ ] 나이트를 제외한 모든 기물은 다른 기물을 뛰어 넘을 수 없다. - - [ ] 상대편의 말만 잡을 수 있다. + - [x] 나이트를 제외한 모든 기물은 다른 기물을 뛰어 넘을 수 없다. + - [x] 상대편의 말만 잡을 수 있다. - [x] 입력한 곳으로 이동할 수 없는 경우 예외를 발생한다. - [ ] 킹이 잡히면 잡힌 쪽이 패배하며 게임을 종료한다 diff --git a/src/main/java/chess/piece/Pawn.java b/src/main/java/chess/piece/Pawn.java index b666537f697..3f7880a200c 100644 --- a/src/main/java/chess/piece/Pawn.java +++ b/src/main/java/chess/piece/Pawn.java @@ -1,7 +1,8 @@ package chess.piece; -import static chess.Movement.LEFT_UP; -import static chess.Movement.RIGHT_UP; +import static chess.Movement.DOWN; +import static chess.Movement.LEFT; +import static chess.Movement.RIGHT; import static chess.Movement.UP; import static chess.Movement.UP_UP; import static chess.Row.TWO; @@ -18,9 +19,13 @@ public class Pawn extends Piece { static { allMovements.add(List.of(UP)); - allMovements.add(List.of(UP_UP)); - allMovements.add(List.of(LEFT_UP)); - allMovements.add(List.of(RIGHT_UP)); + allMovements.add(List.of(UP, UP)); + allMovements.add(List.of(DOWN)); + allMovements.add(List.of(DOWN, DOWN)); + allMovements.add(List.of(LEFT, UP)); + allMovements.add(List.of(RIGHT, UP)); + allMovements.add(List.of(LEFT, DOWN)); + allMovements.add(List.of(RIGHT, DOWN)); } public Pawn(final Color color) { @@ -41,16 +46,27 @@ protected List findRoot(Position start, Position goal) { root.add(now); } if (now.equals(goal)) { + if (color.isWhite() && movements.contains(DOWN)) { + break; + } + if (color.isBlack() && movements.contains(UP) || movements.contains(UP_UP)) { + break; + } if (start.row() != TWO && movements.contains(UP_UP)) { throw new IllegalArgumentException("처음 움직이는 폰만 앞으로 두 칸을 이동할 수 있습니다."); } return root; } } - throw new IllegalArgumentException("경로가 존재하지 않습니다."); + throw new IllegalArgumentException("해당 기물은 해당 위치로 이동할 수 없습니다."); } @Override protected void validateMiddlePath(Board board, List root) { } + + @Override + public String toString() { + return "폰"; + } } From f68225498733a12832b55f70345cd1c2b589e356 Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 17:08:35 +0900 Subject: [PATCH 22/25] =?UTF-8?q?feat:=20=EB=A7=A4=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EC=9E=90=20=EC=9E=85=EB=A0=A5=EB=A7=88=EB=8B=A4=20=EB=B3=B4?= =?UTF-8?q?=EB=93=9C=20=ED=8C=90=EC=9D=84=20=EC=B6=9C=EB=A0=A5=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/Application.java | 47 ++++++++++++++++++++---- src/main/java/chess/Row.java | 4 ++ src/main/java/chess/board/Board.java | 14 ++++++- src/main/java/chess/piece/Bishop.java | 7 +++- src/main/java/chess/piece/King.java | 7 +++- src/main/java/chess/piece/Knight.java | 7 +++- src/main/java/chess/piece/Piece.java | 6 ++- src/main/java/chess/piece/Queen.java | 7 +++- src/main/java/chess/piece/Rook.java | 7 +++- src/test/java/chess/board/BoardTest.java | 4 +- 10 files changed, 93 insertions(+), 17 deletions(-) diff --git a/src/main/java/chess/Application.java b/src/main/java/chess/Application.java index 6c40d03439a..000659a55c2 100644 --- a/src/main/java/chess/Application.java +++ b/src/main/java/chess/Application.java @@ -23,19 +23,50 @@ public static void main(String[] args) { Board board = new Board(makeInitialBoard()); System.out.println("체스 게임을 시작합니다."); Color currentColor = WHITE; + printCurrentBoard(board); while(true) { - System.out.printf("%s 차례입니다.\n움직이려는 말의 좌표와 도착 좌표를 입력하세요.\n", currentColor); - String input = scanner.nextLine(); - String[] split = input.split(" "); - String[] startString = split[0].split(""); - String[] goalString = split[1].split(""); - Position start = createPosition(startString); - Position goal = createPosition(goalString); - board.move(start, goal); + System.out.printf("\n%s 차례입니다.\n움직이려는 기물의 좌표와 도착 좌표를 입력하세요.\n", currentColor); + playTurn(board, currentColor); + printCurrentBoard(board); currentColor = currentColor.opposite(); } } + private static void playTurn(Board board, Color currentColor) { + String input = scanner.nextLine(); + String[] split = input.split(" "); + String[] startString = split[0].split(""); + String[] goalString = split[1].split(""); + Position start = createPosition(startString); + Position goal = createPosition(goalString); + try { + board.move(currentColor, start, goal); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + System.out.println("다시 입력하세요"); + playTurn(board, currentColor); + } + } + + private static void printCurrentBoard(Board currentBoard) { + Map board = currentBoard.getBoard(); + System.out.println(); + for (Row row : Row.values()) { + System.out.print(row.getValue()); + for (Column column : Column.values()) { + Position position = new Position(row, column); + Piece piece = board.get(position); + if (piece == null) { + System.out.print("ㅁ"); + continue; + } + System.out.print(piece); + } + System.out.println(); + } + System.out.println(" A"); + } + public static Position createPosition(String[] positionString) { Column column = getColumn(positionString[0]); Row row = getRow(positionString[1]); diff --git a/src/main/java/chess/Row.java b/src/main/java/chess/Row.java index 5edf7560b0d..e0bec84f1c6 100644 --- a/src/main/java/chess/Row.java +++ b/src/main/java/chess/Row.java @@ -37,6 +37,10 @@ public static Row getRow(int value) { throw new IllegalArgumentException("유효하지 않은 Row입니다."); } + public int getValue() { + return value; + } + public boolean isTop() { return ordinal() == 0; } diff --git a/src/main/java/chess/board/Board.java b/src/main/java/chess/board/Board.java index 2ae35a029bf..90b4bd2212b 100644 --- a/src/main/java/chess/board/Board.java +++ b/src/main/java/chess/board/Board.java @@ -1,8 +1,10 @@ package chess.board; import chess.Color; +import chess.Column; import chess.Position; import chess.piece.Piece; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -13,8 +15,14 @@ public Board(Map board) { this.board = new HashMap<>(board); } - public void move(Position start, Position goal) { + public void move(Color color, Position start, Position goal) { Piece piece = board.get(start); + if (piece == null) { + throw new IllegalArgumentException("해당 위치에 기물이 존재하지 않습니다."); + } + if (piece.isDifferentColor(color)) { + throw new IllegalArgumentException("다른 팀의 기물을 움직일 수 없습니다."); + } piece.validateMovable(this, start, goal); board.put(goal, piece); board.remove(start); @@ -32,4 +40,8 @@ public boolean isPieceExists(Position position) { Piece piece = board.get(position); return piece != null; } + + public Map getBoard() { + return Collections.unmodifiableMap(board); + } } diff --git a/src/main/java/chess/piece/Bishop.java b/src/main/java/chess/piece/Bishop.java index 44227da67f9..905b5a170bc 100644 --- a/src/main/java/chess/piece/Bishop.java +++ b/src/main/java/chess/piece/Bishop.java @@ -58,6 +58,11 @@ protected List findRoot(Position start, Position goal) { return root; } } - throw new IllegalArgumentException("경로가 존재하지 않습니다."); + throw new IllegalArgumentException("해당 기물은 해당 위치로 이동할 수 없습니다."); + } + + @Override + public String toString() { + return "숍"; } } diff --git a/src/main/java/chess/piece/King.java b/src/main/java/chess/piece/King.java index f4c67df96ff..0e6f11124c3 100644 --- a/src/main/java/chess/piece/King.java +++ b/src/main/java/chess/piece/King.java @@ -42,10 +42,15 @@ protected List findRoot(Position start, Position goal) { return root; } } - throw new IllegalArgumentException("경로가 존재하지 않습니다."); + throw new IllegalArgumentException("해당 기물은 해당 위치로 이동할 수 없습니다."); } @Override protected void validateMiddlePath(Board board, List root) { } + + @Override + public String toString() { + return "킹"; + } } diff --git a/src/main/java/chess/piece/Knight.java b/src/main/java/chess/piece/Knight.java index aafa22ab193..1930915203b 100644 --- a/src/main/java/chess/piece/Knight.java +++ b/src/main/java/chess/piece/Knight.java @@ -50,10 +50,15 @@ protected List findRoot(Position start, Position goal) { return root; } } - throw new IllegalArgumentException("경로가 존재하지 않습니다."); + throw new IllegalArgumentException("해당 기물은 해당 위치로 이동할 수 없습니다."); } @Override protected void validateMiddlePath(Board board, List root) { } + + @Override + public String toString() { + return "말"; + } } diff --git a/src/main/java/chess/piece/Piece.java b/src/main/java/chess/piece/Piece.java index 77126d852f1..4d99a2fef6b 100644 --- a/src/main/java/chess/piece/Piece.java +++ b/src/main/java/chess/piece/Piece.java @@ -22,7 +22,7 @@ public void validateMovable(Board board, Position start, Position goal) { private void validateSameColorPieceOnGoal(Board board, Position goal) { if (board.isSameColorPieceExists(goal, color)) { - throw new IllegalArgumentException("상대편의 말만 잡을 수 있습니다."); + throw new IllegalArgumentException("상대편의 기물만 잡을 수 있습니다."); } } @@ -35,4 +35,8 @@ private void validateSameColorPieceOnGoal(Board board, Position goal) { public boolean isSameColor(Color other) { return color == other; } + + public boolean isDifferentColor(Color other) { + return color != other; + } } diff --git a/src/main/java/chess/piece/Queen.java b/src/main/java/chess/piece/Queen.java index 5f7eb1b2e4a..ca0f47dc071 100644 --- a/src/main/java/chess/piece/Queen.java +++ b/src/main/java/chess/piece/Queen.java @@ -51,7 +51,7 @@ protected List findRoot(Position start, Position goal) { return root; } } - throw new IllegalArgumentException("경로가 존재하지 않습니다."); + throw new IllegalArgumentException("해당 기물은 해당 위치로 이동할 수 없습니다."); } @Override @@ -64,4 +64,9 @@ protected void validateMiddlePath(Board board, List root) { } } } + + @Override + public String toString() { + return "퀸"; + } } diff --git a/src/main/java/chess/piece/Rook.java b/src/main/java/chess/piece/Rook.java index f64c489d361..d68c2265da9 100644 --- a/src/main/java/chess/piece/Rook.java +++ b/src/main/java/chess/piece/Rook.java @@ -47,7 +47,7 @@ protected List findRoot(Position start, Position goal) { return root; } } - throw new IllegalArgumentException("경로가 존재하지 않습니다."); + throw new IllegalArgumentException("해당 기물은 해당 위치로 이동할 수 없습니다."); } @Override @@ -60,4 +60,9 @@ protected void validateMiddlePath(Board board, List root) { } } } + + @Override + public String toString() { + return "룩"; + } } diff --git a/src/test/java/chess/board/BoardTest.java b/src/test/java/chess/board/BoardTest.java index fcd1e268fc9..8951cec0f18 100644 --- a/src/test/java/chess/board/BoardTest.java +++ b/src/test/java/chess/board/BoardTest.java @@ -23,7 +23,7 @@ void move1() { .hasMessage("중간에 다른 기물을 뛰어넘을 수 없습니다."); } - @DisplayName("도착지에_같은_색깔의_말이_존재하면_예외를_발생한다") + @DisplayName("도착지에_같은_색깔의_기이_존재하면_예외를_발생한다") @Test void move2() { // given @@ -33,6 +33,6 @@ void move2() { // then Assertions.assertThatThrownBy(() -> generalBoard.move(A1, A2)) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("상대편의 말만 잡을 수 있습니다."); + .hasMessage("상대편의 기물만 잡을 수 있습니다."); } } From f6ddb197b6abc8c54a2c11409cd4142db697b41c Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 17:18:05 +0900 Subject: [PATCH 23/25] =?UTF-8?q?feat:=20=ED=9D=91=EC=83=89=20=EC=A7=84?= =?UTF-8?q?=EC=98=81=20=ED=8F=B0=EB=8F=84=20=EC=B2=98=EC=9D=8C=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=EC=9D=B4=20=EC=95=84=EB=8B=88=EB=A9=B4=20=EC=95=84?= =?UTF-8?q?=EB=9E=98=EB=A1=9C=20=EB=91=90=EC=B9=B8=20=EC=9D=B4=EB=8F=99?= =?UTF-8?q?=ED=95=A0=20=EC=88=98=20=EC=97=86=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/piece/Pawn.java | 13 ++++++++----- src/test/java/chess/board/BoardTest.java | 5 +++-- src/test/java/chess/piece/KnightTest.java | 4 ++-- src/test/java/chess/piece/PawnTest.java | 6 +++--- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/main/java/chess/piece/Pawn.java b/src/main/java/chess/piece/Pawn.java index 3f7880a200c..daeb7626dbe 100644 --- a/src/main/java/chess/piece/Pawn.java +++ b/src/main/java/chess/piece/Pawn.java @@ -1,10 +1,12 @@ package chess.piece; import static chess.Movement.DOWN; +import static chess.Movement.DOWN_DOWN; import static chess.Movement.LEFT; import static chess.Movement.RIGHT; import static chess.Movement.UP; import static chess.Movement.UP_UP; +import static chess.Row.SEVEN; import static chess.Row.TWO; import chess.Color; @@ -19,9 +21,9 @@ public class Pawn extends Piece { static { allMovements.add(List.of(UP)); - allMovements.add(List.of(UP, UP)); + allMovements.add(List.of(UP_UP)); allMovements.add(List.of(DOWN)); - allMovements.add(List.of(DOWN, DOWN)); + allMovements.add(List.of(DOWN_DOWN)); allMovements.add(List.of(LEFT, UP)); allMovements.add(List.of(RIGHT, UP)); allMovements.add(List.of(LEFT, DOWN)); @@ -46,13 +48,14 @@ protected List findRoot(Position start, Position goal) { root.add(now); } if (now.equals(goal)) { - if (color.isWhite() && movements.contains(DOWN)) { + if (color.isWhite() && (movements.contains(DOWN) || movements.contains(DOWN_DOWN))) { break; } - if (color.isBlack() && movements.contains(UP) || movements.contains(UP_UP)) { + if (color.isBlack() && (movements.contains(UP) || movements.contains(UP_UP))) { break; } - if (start.row() != TWO && movements.contains(UP_UP)) { + if ((start.row() != TWO) && movements.contains(UP_UP) || + (start.row() != SEVEN) && movements.contains(DOWN_DOWN)) { throw new IllegalArgumentException("처음 움직이는 폰만 앞으로 두 칸을 이동할 수 있습니다."); } return root; diff --git a/src/test/java/chess/board/BoardTest.java b/src/test/java/chess/board/BoardTest.java index 8951cec0f18..3631b06a069 100644 --- a/src/test/java/chess/board/BoardTest.java +++ b/src/test/java/chess/board/BoardTest.java @@ -5,6 +5,7 @@ import static chess.Fixtures.A3; import static chess.Fixtures.makeGeneralBoard; +import chess.Color; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -18,7 +19,7 @@ void move1() { // when // then - Assertions.assertThatThrownBy(() -> generalBoard.move(A1, A3)) + Assertions.assertThatThrownBy(() -> generalBoard.move(Color.WHITE, A1, A3)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("중간에 다른 기물을 뛰어넘을 수 없습니다."); } @@ -31,7 +32,7 @@ void move2() { // when // then - Assertions.assertThatThrownBy(() -> generalBoard.move(A1, A2)) + Assertions.assertThatThrownBy(() -> generalBoard.move(Color.WHITE, A1, A2)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("상대편의 기물만 잡을 수 있습니다."); } diff --git a/src/test/java/chess/piece/KnightTest.java b/src/test/java/chess/piece/KnightTest.java index 09d2aa7fb1d..b57b6b50a90 100644 --- a/src/test/java/chess/piece/KnightTest.java +++ b/src/test/java/chess/piece/KnightTest.java @@ -27,7 +27,7 @@ class KnightTest { void move1() { //when //then - assertThatCode(() -> makeGeneralBoard().move(B1, A3)) + assertThatCode(() -> makeGeneralBoard().move(Color.WHITE, B1, A3)) .doesNotThrowAnyException(); } @@ -44,7 +44,7 @@ void move2(Column column, Row row) { Position goal = new Position(column, row); //when - board.move(D4, goal); + board.move(Color.WHITE, D4, goal); //then assertThat(board).extracting("board", as(MAP)) diff --git a/src/test/java/chess/piece/PawnTest.java b/src/test/java/chess/piece/PawnTest.java index 1fe5b8c5b45..c1bfeaedc7e 100644 --- a/src/test/java/chess/piece/PawnTest.java +++ b/src/test/java/chess/piece/PawnTest.java @@ -6,6 +6,7 @@ import static chess.Fixtures.makeGeneralBoard; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import chess.Color; import chess.board.Board; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -16,12 +17,11 @@ class PawnTest { void move1() { // given Board generalBoard = makeGeneralBoard(); + generalBoard.move(Color.WHITE, A2, A3); // when - generalBoard.move(A2, A3); - // then - assertThatThrownBy(() -> generalBoard.move(A3, A5)) + assertThatThrownBy(() -> generalBoard.move(Color.WHITE, A3, A5)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("처음 움직이는 폰만 앞으로 두 칸을 이동할 수 있습니다."); } From 52808806e46054e380643a67dbb21ad478b3258a Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 17:25:20 +0900 Subject: [PATCH 24/25] =?UTF-8?q?feat:=20=ED=8F=B0=EC=9D=80=20=EB=8C=80?= =?UTF-8?q?=EA=B0=81=20=EC=9C=84=EC=B9=98=EC=97=90=20=EC=83=81=EB=8C=80=20?= =?UTF-8?q?=EA=B8=B0=EB=AC=BC=EC=9D=B4=20=EC=A1=B4=EC=9E=AC=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EA=B2=BD=EC=9A=B0=EC=97=90=EB=A7=8C=20=EB=8C=80?= =?UTF-8?q?=EA=B0=81=EC=9C=BC=EB=A1=9C=20=EC=9B=80=EC=A7=81=EC=9D=BC=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/board/Board.java | 9 +++++++++ src/main/java/chess/piece/Bishop.java | 2 +- src/main/java/chess/piece/King.java | 2 +- src/main/java/chess/piece/Knight.java | 2 +- src/main/java/chess/piece/Pawn.java | 5 ++++- src/main/java/chess/piece/Piece.java | 8 ++++++-- src/main/java/chess/piece/Queen.java | 2 +- src/main/java/chess/piece/Rook.java | 2 +- 8 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/main/java/chess/board/Board.java b/src/main/java/chess/board/Board.java index 90b4bd2212b..31364782f26 100644 --- a/src/main/java/chess/board/Board.java +++ b/src/main/java/chess/board/Board.java @@ -36,6 +36,15 @@ public boolean isSameColorPieceExists(Position goal, Color color) { return piece.isSameColor(color); } + public boolean isDifferentColorPieceNotExists(Position start, Position goal) { + Piece startPiece = board.get(start); + Piece goalPiece = board.get(goal); + if (startPiece == null || goalPiece == null) { + return true; + } + return startPiece.isSameColor(goalPiece); + } + public boolean isPieceExists(Position position) { Piece piece = board.get(position); return piece != null; diff --git a/src/main/java/chess/piece/Bishop.java b/src/main/java/chess/piece/Bishop.java index 905b5a170bc..b168319e84d 100644 --- a/src/main/java/chess/piece/Bishop.java +++ b/src/main/java/chess/piece/Bishop.java @@ -42,7 +42,7 @@ protected void validateMiddlePath(Board board, List root) { } } - protected List findRoot(Position start, Position goal) { + protected List findRoot(Board board, Position start, Position goal) { for (List movements : allMovements) { List root = new ArrayList<>(); Position now = start; diff --git a/src/main/java/chess/piece/King.java b/src/main/java/chess/piece/King.java index 0e6f11124c3..6c054626e66 100644 --- a/src/main/java/chess/piece/King.java +++ b/src/main/java/chess/piece/King.java @@ -26,7 +26,7 @@ public King(final Color color) { super(color); } - protected List findRoot(Position start, Position goal) { + protected List findRoot(Board board, Position start, Position goal) { for (List movements : allMovements) { List root = new ArrayList<>(); Position now = start; diff --git a/src/main/java/chess/piece/Knight.java b/src/main/java/chess/piece/Knight.java index 1930915203b..a65d138dffb 100644 --- a/src/main/java/chess/piece/Knight.java +++ b/src/main/java/chess/piece/Knight.java @@ -34,7 +34,7 @@ public Knight(final Color color) { } @Override - protected List findRoot(Position start, Position goal) { + protected List findRoot(Board board, Position start, Position goal) { for (List movements : allMovements) { List root = new ArrayList<>(); Position now = start; diff --git a/src/main/java/chess/piece/Pawn.java b/src/main/java/chess/piece/Pawn.java index daeb7626dbe..8494fba5c9d 100644 --- a/src/main/java/chess/piece/Pawn.java +++ b/src/main/java/chess/piece/Pawn.java @@ -35,7 +35,7 @@ public Pawn(final Color color) { } @Override - protected List findRoot(Position start, Position goal) { + protected List findRoot(Board board, Position start, Position goal) { for (List movements : allMovements) { List root = new ArrayList<>(); Position now = start; @@ -58,6 +58,9 @@ protected List findRoot(Position start, Position goal) { (start.row() != SEVEN) && movements.contains(DOWN_DOWN)) { throw new IllegalArgumentException("처음 움직이는 폰만 앞으로 두 칸을 이동할 수 있습니다."); } + if ((movements.contains(LEFT) || movements.contains(RIGHT)) && board.isDifferentColorPieceNotExists(start, goal)) { + throw new IllegalArgumentException("상대 기물이 있는 경우에만 대각선으로 이동할 수 있습니다."); + } return root; } } diff --git a/src/main/java/chess/piece/Piece.java b/src/main/java/chess/piece/Piece.java index 4d99a2fef6b..7a0d9c315e4 100644 --- a/src/main/java/chess/piece/Piece.java +++ b/src/main/java/chess/piece/Piece.java @@ -14,7 +14,7 @@ protected Piece(final Color color) { } public void validateMovable(Board board, Position start, Position goal) { - List root = findRoot(start, goal); + List root = findRoot(board, start, goal); validateMiddlePath(board, root); validateSameColorPieceOnGoal(board, goal); @@ -29,13 +29,17 @@ private void validateSameColorPieceOnGoal(Board board, Position goal) { /** * 제자리로 움직이는 경우 TODO */ - protected abstract List findRoot(Position start, Position goal); + protected abstract List findRoot(Board board, Position start, Position goal); protected abstract void validateMiddlePath(Board board, List root); public boolean isSameColor(Color other) { return color == other; } + public boolean isSameColor(Piece other) { + return color == other.color; + } + public boolean isDifferentColor(Color other) { return color != other; } diff --git a/src/main/java/chess/piece/Queen.java b/src/main/java/chess/piece/Queen.java index ca0f47dc071..4edbb5cfc79 100644 --- a/src/main/java/chess/piece/Queen.java +++ b/src/main/java/chess/piece/Queen.java @@ -35,7 +35,7 @@ public Queen(final Color color) { } @Override - protected List findRoot(Position start, Position goal) { + protected List findRoot(Board board, Position start, Position goal) { for (List movements : allMovements) { List root = new ArrayList<>(); Position now = start; diff --git a/src/main/java/chess/piece/Rook.java b/src/main/java/chess/piece/Rook.java index d68c2265da9..9c55d6800c5 100644 --- a/src/main/java/chess/piece/Rook.java +++ b/src/main/java/chess/piece/Rook.java @@ -31,7 +31,7 @@ public Rook(final Color color) { } @Override - protected List findRoot(Position start, Position goal) { + protected List findRoot(Board board, Position start, Position goal) { for (List movements : allMovements) { List root = new ArrayList<>(); Position now = start; From 0cac3bd73c9a1ecb9a56d44053042eba61f71c3e Mon Sep 17 00:00:00 2001 From: kjyyjk Date: Sat, 22 Mar 2025 19:31:15 +0900 Subject: [PATCH 25/25] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=B5=9C=EC=8B=A0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index db576a2f768..92fd710db6e 100644 --- a/README.md +++ b/README.md @@ -21,16 +21,15 @@ - [x] 나이트 - 한 방향으로 두칸을 이동하고 그와 90도를 이루는 방향으로 한칸 이동한다.(L자 모양) - 진행 경로에 다른 기물이 있어도 가로 막히지 않는다. - - [ ] 폰 + - [x] 폰 - [x] 처음 움직이는 폰은 앞으로 두 칸까지 이동할 수 있다. - [x] 이후부터는 앞으로 한 칸씩만 이동할 수 있다. - - [ ] 잡을 때는 대각선으로 한 칸 앞에 있는 상대 기물만 잡을 수 있다. + - [x] 잡을 때는 대각선으로 한 칸 앞에 있는 상대 기물만 잡을 수 있다. - [x] 흑색 진영은 흰색 진영과 반대로 이동한다. - 이동 규칙 - [x] 나이트를 제외한 모든 기물은 다른 기물을 뛰어 넘을 수 없다. - [x] 상대편의 말만 잡을 수 있다. - [x] 입력한 곳으로 이동할 수 없는 경우 예외를 발생한다. -- [ ] 킹이 잡히면 잡힌 쪽이 패배하며 게임을 종료한다 ### 추후 구현 목록 @@ -41,3 +40,4 @@ - 킹이 잡히면 게임을 종료한다. - 체크 메이트 규칙을 적용한다. - 게임을 끝낼 수 없는 경우 무승부처리한다. +- 킹이 잡히면 잡힌 쪽이 패배하며 게임을 종료한다