From ef5351d056760355c888e8759bcf00cd4c3544bd Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Tue, 24 Mar 2026 20:05:54 +0900 Subject: [PATCH 01/87] =?UTF-8?q?docs:=20=EA=B5=AC=ED=98=84=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EB=82=B4=EC=9A=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/README.md b/README.md index 9775dda0ae..f843025f43 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,58 @@ # java-janggi 장기 미션 저장소 + +## 구현 기능 내용 +### 입력 기능 +- [ ] + +### 출력 기능 +- [ ] 9 x 10 장기판에 기물을 기본 세팅하여 출력한다. + - '상마', '상마' 순서로 출력한다. + - 기물이 없는 경우 'x' 로 출력한다. + +### 핵심 기능 +- [ ] 장기판 초기화 + - '상마', '상마' 순서로 초기화한다. +- [ ] 기물의 이동을 구현한다. + - 이동 경로에 다른 기물이 존재하지 않을 때만 그대로 이동할 수 있다. + - 이동 경로에 같은 팀 기물이 존재한다면 이동하지 못한다. + - 이동 경로에 다른 팀 기물이 존재한다면 해당 기물을 잡을 수 있다. + - 이동할 기물이 포이고 이동 경로에 포를 제외한 다른 기물이 있다면 기물을 넘어서 이동할 수 있다. + +### 예외 기능 +- [ ] 장기판을 벗어나면 예외를 발생한다. +- [ ] 졸/병이 후퇴하면 예외를 발생한다. +- [ ] 포가 포를 넘으려고 하면 예외를 발생한다. + +## 프로그램 흐름도 +1. 장기판 초기화 + +## 기물의 이동 규칙 +1. 차 +- 상하좌우 방향으로 기물이 없는 곳까지 원하는 만큼 이동할 수 있다. +- 궁성 내부에 위치한 경우 대각선 이동도 가능한다. +- 이동 경로 중간에 다른 기물이 존재하면 이동할 수 없다. + +2. 마 +- 상하좌우 방향으로 한 칸 이동한 뒤 대각선 방향으로 한 칸 이동할 수 있다. +- 이동 경로 중 첫 번째 칸에 다른 기물이 존재하면 이동할 수 없다. + +3. 상 +- 상하좌우 방향으로 한 칸 이동한 뒤 대각선 방향으로 두 칸 이동할 수 있다. +- 이동 경로 중간에 다른 기물이 존재하면 이동할 수 없다. + +4. 사 +- 상하좌우 대각선 방향으로 한 칸 이동할 수 있다. + +5. 궁 +- 상하좌우 대각선 방향으로 한 칸 이동할 수 있다. + +6. 포 +- 상하좌우 방향으로 이동할 수 있다. +- 이동 시 반드시 다른 기물 하나를 뛰어넘어야 한다. +- 뛰어넘을 기물이 없는 경우 이동할 수 없다. + +7. 졸 / 병 +- 기본적으로 전진 및 좌우 방향으로 한 칸 이동할 수 있다. +- 뒤로 이동할 수 없습니다. From 1f59cd9560f174a22a8014a55bdfbd5efa32e751 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Tue, 24 Mar 2026 20:20:58 +0900 Subject: [PATCH 02/87] =?UTF-8?q?feat:=20=EC=9C=84=EC=B9=98=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20=EB=B0=8F=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/vo/Position.java | 24 +++++++++++++++++++++++ src/test/java/domain/vo/PositionTest.java | 23 ++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 src/main/java/domain/vo/Position.java create mode 100644 src/test/java/domain/vo/PositionTest.java diff --git a/src/main/java/domain/vo/Position.java b/src/main/java/domain/vo/Position.java new file mode 100644 index 0000000000..0fc6fcc3f5 --- /dev/null +++ b/src/main/java/domain/vo/Position.java @@ -0,0 +1,24 @@ +package domain.vo; + +public class Position { + + private final int row; + private final int col; + + private Position(final int row, final int col) { + this.row = row; + this.col = col; + } + + public static Position of(final int row, final int col) { + return new Position(row, col); + } + + public int getRow() { + return this.row; + } + + public int getCol() { + return this.col; + } +} diff --git a/src/test/java/domain/vo/PositionTest.java b/src/test/java/domain/vo/PositionTest.java new file mode 100644 index 0000000000..722939a332 --- /dev/null +++ b/src/test/java/domain/vo/PositionTest.java @@ -0,0 +1,23 @@ +package domain.vo; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class PositionTest { + + @Test + @DisplayName("정상적인 좌표값 입력 시 Position을 생성한다.") + void 위치_정상_입력() { + // given + // when + int x = 1; + int y = 1; + + Position position = Position.of(x, y); + + // then + Assertions.assertEquals(x, position.getRow()); + Assertions.assertEquals(y, position.getCol()); + } +} From 7da0ceba85821a0a2c0b19329748666b86ebac20 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Tue, 24 Mar 2026 20:44:57 +0900 Subject: [PATCH 03/87] =?UTF-8?q?feat:=20=EC=9C=84=EC=B9=98=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EA=B2=80=EC=A6=9D=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1=20=EB=B0=8F=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/vo/Position.java | 18 ++++++++++++++ src/test/java/domain/vo/PositionTest.java | 30 ++++++++++++++++++++--- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/main/java/domain/vo/Position.java b/src/main/java/domain/vo/Position.java index 0fc6fcc3f5..8b43b287a0 100644 --- a/src/main/java/domain/vo/Position.java +++ b/src/main/java/domain/vo/Position.java @@ -6,10 +6,28 @@ public class Position { private final int col; private Position(final int row, final int col) { + validate(row, col); this.row = row; this.col = col; } + private void validate(int row, int col) { + validateRowInRange(row); + validateColInRange(col); + } + + private void validateColInRange(int col) { + if (0 > col || col > 8) { + throw new IllegalArgumentException("[ERROR] 열이 0~8 범위를 벗어났습니다."); + } + } + + private void validateRowInRange(int row) { + if (0 > row || row > 9) { + throw new IllegalArgumentException("[ERROR] 행이 0~9 범위를 벗어났습니다."); + } + } + public static Position of(final int row, final int col) { return new Position(row, col); } diff --git a/src/test/java/domain/vo/PositionTest.java b/src/test/java/domain/vo/PositionTest.java index 722939a332..23f8864ace 100644 --- a/src/test/java/domain/vo/PositionTest.java +++ b/src/test/java/domain/vo/PositionTest.java @@ -1,9 +1,11 @@ package domain.vo; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; + class PositionTest { @Test @@ -17,7 +19,29 @@ class PositionTest { Position position = Position.of(x, y); // then - Assertions.assertEquals(x, position.getRow()); - Assertions.assertEquals(y, position.getCol()); + assertEquals(x, position.getRow()); + assertEquals(y, position.getCol()); + } + + @Test + @DisplayName("행이 0~9 범위를 벗어나면 예외를 발생한다.") + void 위치_행_비정상_입력() { + // given + // when + // then + assertThatThrownBy(() ->Position.of(-1, 0)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("[ERROR] 행이 0~9 범위를 벗어났습니다."); + } + + @Test + @DisplayName("열이 0~8 범위를 벗어나면 예외를 발생한다.") + void 위치_열_비정상_입력() { + // given + // when + // then + assertThatThrownBy(() ->Position.of(0, -1)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("[ERROR] 열이 0~8 범위를 벗어났습니다."); } } From 3f21be8acfa8fa4c64439fc3860c15b7ac4bf904 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Tue, 24 Mar 2026 21:07:16 +0900 Subject: [PATCH 04/87] =?UTF-8?q?feat:=20=EC=9E=A5=EA=B8=B0=ED=8C=90=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=9E=91=EC=84=B1=20=EB=B0=8F=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Board.java | 52 +++++++++++++++++++++++++++++ src/main/java/domain/Piece.java | 6 ++++ src/test/java/domain/BoardTest.java | 18 ++++++++++ 3 files changed, 76 insertions(+) create mode 100644 src/main/java/domain/Board.java create mode 100644 src/main/java/domain/Piece.java create mode 100644 src/test/java/domain/BoardTest.java diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java new file mode 100644 index 0000000000..f1d212c3fd --- /dev/null +++ b/src/main/java/domain/Board.java @@ -0,0 +1,52 @@ +package domain; + +import domain.vo.Position; + +import java.util.HashMap; +import java.util.Map; + +public class Board { + + private final Map board; + + private Board() { + board = new HashMap<>(); + board.put(Position.of(0, 0), new Piece()); + board.put(Position.of(0, 1), new Piece()); + board.put(Position.of(0, 2), new Piece()); + board.put(Position.of(0, 3), new Piece()); + board.put(Position.of(0, 4), new Piece()); + board.put(Position.of(0, 6), new Piece()); + board.put(Position.of(0, 7), new Piece()); + board.put(Position.of(0, 8), new Piece()); + board.put(Position.of(1, 4), new Piece()); + board.put(Position.of(2, 1), new Piece()); + board.put(Position.of(2, 8), new Piece()); + board.put(Position.of(3, 0), new Piece()); + board.put(Position.of(3, 2), new Piece()); + board.put(Position.of(3, 4), new Piece()); + board.put(Position.of(3, 6), new Piece()); + board.put(Position.of(3, 8), new Piece()); + + board.put(Position.of(9, 0), new Piece()); + board.put(Position.of(9, 1), new Piece()); + board.put(Position.of(9, 2), new Piece()); + board.put(Position.of(9, 3), new Piece()); + board.put(Position.of(9, 4), new Piece()); + board.put(Position.of(9, 6), new Piece()); + board.put(Position.of(9, 7), new Piece()); + board.put(Position.of(9, 8), new Piece()); + board.put(Position.of(8, 4), new Piece()); + board.put(Position.of(7, 1), new Piece()); + board.put(Position.of(7, 8), new Piece()); + board.put(Position.of(6, 0), new Piece()); + board.put(Position.of(6, 2), new Piece()); + board.put(Position.of(6, 4), new Piece()); + board.put(Position.of(6, 6), new Piece()); + board.put(Position.of(6, 8), new Piece()); + } + + public static Board of() { + return new Board(); + } +} diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java new file mode 100644 index 0000000000..f88f3d8c6c --- /dev/null +++ b/src/main/java/domain/Piece.java @@ -0,0 +1,6 @@ +package domain; + +public class Piece { + + public Piece () {} +} diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java new file mode 100644 index 0000000000..1694e90d64 --- /dev/null +++ b/src/test/java/domain/BoardTest.java @@ -0,0 +1,18 @@ +package domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +class BoardTest { + + @Test + @DisplayName("보드를 생성하면 기물들 초기화된다.") + void 보드_생성() { + // given + // when + // then + assertDoesNotThrow(Board::of); + } +} From 8acc7d5f8c748594daf64cf45116339f28e955ca Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Wed, 25 Mar 2026 11:38:08 +0900 Subject: [PATCH 05/87] =?UTF-8?q?feat:=20=EC=B0=A8=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Board.java | 64 +++++++++++++-------------- src/main/java/domain/Chariot.java | 25 +++++++++++ src/main/java/domain/Piece.java | 5 +-- src/main/java/domain/Team.java | 16 +++++++ src/test/java/domain/ChariotTest.java | 31 +++++++++++++ 5 files changed, 106 insertions(+), 35 deletions(-) create mode 100644 src/main/java/domain/Chariot.java create mode 100644 src/main/java/domain/Team.java create mode 100644 src/test/java/domain/ChariotTest.java diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index f1d212c3fd..cac6642eb8 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -11,39 +11,39 @@ public class Board { private Board() { board = new HashMap<>(); - board.put(Position.of(0, 0), new Piece()); - board.put(Position.of(0, 1), new Piece()); - board.put(Position.of(0, 2), new Piece()); - board.put(Position.of(0, 3), new Piece()); - board.put(Position.of(0, 4), new Piece()); - board.put(Position.of(0, 6), new Piece()); - board.put(Position.of(0, 7), new Piece()); - board.put(Position.of(0, 8), new Piece()); - board.put(Position.of(1, 4), new Piece()); - board.put(Position.of(2, 1), new Piece()); - board.put(Position.of(2, 8), new Piece()); - board.put(Position.of(3, 0), new Piece()); - board.put(Position.of(3, 2), new Piece()); - board.put(Position.of(3, 4), new Piece()); - board.put(Position.of(3, 6), new Piece()); - board.put(Position.of(3, 8), new Piece()); + board.put(Position.of(0, 0),Chariot.of(Team.CHU)); + board.put(Position.of(0, 1),Chariot.of(Team.CHU)); + board.put(Position.of(0, 2),Chariot.of(Team.CHU)); + board.put(Position.of(0, 3),Chariot.of(Team.CHU)); + board.put(Position.of(0, 4),Chariot.of(Team.CHU)); + board.put(Position.of(0, 6),Chariot.of(Team.CHU)); + board.put(Position.of(0, 7),Chariot.of(Team.CHU)); + board.put(Position.of(0, 8),Chariot.of(Team.CHU)); + board.put(Position.of(1, 4),Chariot.of(Team.CHU)); + board.put(Position.of(2, 1),Chariot.of(Team.CHU)); + board.put(Position.of(2, 8),Chariot.of(Team.CHU)); + board.put(Position.of(3, 0),Chariot.of(Team.CHU)); + board.put(Position.of(3, 2),Chariot.of(Team.CHU)); + board.put(Position.of(3, 4),Chariot.of(Team.CHU)); + board.put(Position.of(3, 6),Chariot.of(Team.CHU)); + board.put(Position.of(3, 8),Chariot.of(Team.CHU)); - board.put(Position.of(9, 0), new Piece()); - board.put(Position.of(9, 1), new Piece()); - board.put(Position.of(9, 2), new Piece()); - board.put(Position.of(9, 3), new Piece()); - board.put(Position.of(9, 4), new Piece()); - board.put(Position.of(9, 6), new Piece()); - board.put(Position.of(9, 7), new Piece()); - board.put(Position.of(9, 8), new Piece()); - board.put(Position.of(8, 4), new Piece()); - board.put(Position.of(7, 1), new Piece()); - board.put(Position.of(7, 8), new Piece()); - board.put(Position.of(6, 0), new Piece()); - board.put(Position.of(6, 2), new Piece()); - board.put(Position.of(6, 4), new Piece()); - board.put(Position.of(6, 6), new Piece()); - board.put(Position.of(6, 8), new Piece()); + board.put(Position.of(9, 0),Chariot.of(Team.CHU)); + board.put(Position.of(9, 1),Chariot.of(Team.CHU)); + board.put(Position.of(9, 2),Chariot.of(Team.CHU)); + board.put(Position.of(9, 3),Chariot.of(Team.CHU)); + board.put(Position.of(9, 4),Chariot.of(Team.CHU)); + board.put(Position.of(9, 6),Chariot.of(Team.CHU)); + board.put(Position.of(9, 7),Chariot.of(Team.CHU)); + board.put(Position.of(9, 8),Chariot.of(Team.CHU)); + board.put(Position.of(8, 4),Chariot.of(Team.CHU)); + board.put(Position.of(7, 1),Chariot.of(Team.CHU)); + board.put(Position.of(7, 8),Chariot.of(Team.CHU)); + board.put(Position.of(6, 0),Chariot.of(Team.CHU)); + board.put(Position.of(6, 2),Chariot.of(Team.CHU)); + board.put(Position.of(6, 4),Chariot.of(Team.CHU)); + board.put(Position.of(6, 6),Chariot.of(Team.CHU)); + board.put(Position.of(6, 8),Chariot.of(Team.CHU)); } public static Board of() { diff --git a/src/main/java/domain/Chariot.java b/src/main/java/domain/Chariot.java new file mode 100644 index 0000000000..9becbaa971 --- /dev/null +++ b/src/main/java/domain/Chariot.java @@ -0,0 +1,25 @@ +package domain; + +public class Chariot implements Piece { + + private final Team team; + + private Chariot(final Team team) { + this.team = team; + } + + public static Chariot of(final Team team) { + return new Chariot(team); + } + + public Team findMyTeam() { + return team.getNation(); + } + + @Override + public void move( + + ) { + + } +} diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java index f88f3d8c6c..562c6be2b9 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/Piece.java @@ -1,6 +1,5 @@ package domain; -public class Piece { - - public Piece () {} +public interface Piece { + void move(); } diff --git a/src/main/java/domain/Team.java b/src/main/java/domain/Team.java new file mode 100644 index 0000000000..0ea187ebef --- /dev/null +++ b/src/main/java/domain/Team.java @@ -0,0 +1,16 @@ +package domain; + +public enum Team { + CHU("초"), + HAN("한"); + + private final String nation; + + Team(String nation) { + this.nation = nation; + } + + public Team getNation() { + return this; + } +} diff --git a/src/test/java/domain/ChariotTest.java b/src/test/java/domain/ChariotTest.java new file mode 100644 index 0000000000..06096336a7 --- /dev/null +++ b/src/test/java/domain/ChariotTest.java @@ -0,0 +1,31 @@ +package domain; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class ChariotTest { + + @Test + @DisplayName("차를 생성하면 차가 초기화된다.") + void 차_생성() { + // given + // when + Chariot chariot = Chariot.of(Team.CHU); + + // then + Assertions.assertEquals(chariot.findMyTeam(), Team.CHU); + } + + @Test + @DisplayName("상하좌우로 이동 경로에 다른 기물이 없으면 이동할 수 있다.") + void 차_상하좌우_정상_이동() { + // given + Piece chariot = Chariot.of(Team.CHU); + + // when + chariot.move(); + + // then + } +} From f254898e64bf733ee25c539883692de38bac290f Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Wed, 25 Mar 2026 13:58:31 +0900 Subject: [PATCH 06/87] =?UTF-8?q?refactor:=20=EA=B8=B0=EB=AC=BC=20?= =?UTF-8?q?=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Chariot.java | 25 --------------------- src/main/java/domain/Piece.java | 5 ----- src/test/java/domain/ChariotTest.java | 31 --------------------------- src/test/java/domain/PieceTest.java | 5 +++++ 4 files changed, 5 insertions(+), 61 deletions(-) delete mode 100644 src/main/java/domain/Chariot.java delete mode 100644 src/main/java/domain/Piece.java delete mode 100644 src/test/java/domain/ChariotTest.java create mode 100644 src/test/java/domain/PieceTest.java diff --git a/src/main/java/domain/Chariot.java b/src/main/java/domain/Chariot.java deleted file mode 100644 index 9becbaa971..0000000000 --- a/src/main/java/domain/Chariot.java +++ /dev/null @@ -1,25 +0,0 @@ -package domain; - -public class Chariot implements Piece { - - private final Team team; - - private Chariot(final Team team) { - this.team = team; - } - - public static Chariot of(final Team team) { - return new Chariot(team); - } - - public Team findMyTeam() { - return team.getNation(); - } - - @Override - public void move( - - ) { - - } -} diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java deleted file mode 100644 index 562c6be2b9..0000000000 --- a/src/main/java/domain/Piece.java +++ /dev/null @@ -1,5 +0,0 @@ -package domain; - -public interface Piece { - void move(); -} diff --git a/src/test/java/domain/ChariotTest.java b/src/test/java/domain/ChariotTest.java deleted file mode 100644 index 06096336a7..0000000000 --- a/src/test/java/domain/ChariotTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package domain; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -class ChariotTest { - - @Test - @DisplayName("차를 생성하면 차가 초기화된다.") - void 차_생성() { - // given - // when - Chariot chariot = Chariot.of(Team.CHU); - - // then - Assertions.assertEquals(chariot.findMyTeam(), Team.CHU); - } - - @Test - @DisplayName("상하좌우로 이동 경로에 다른 기물이 없으면 이동할 수 있다.") - void 차_상하좌우_정상_이동() { - // given - Piece chariot = Chariot.of(Team.CHU); - - // when - chariot.move(); - - // then - } -} diff --git a/src/test/java/domain/PieceTest.java b/src/test/java/domain/PieceTest.java new file mode 100644 index 0000000000..f1a9feecf4 --- /dev/null +++ b/src/test/java/domain/PieceTest.java @@ -0,0 +1,5 @@ +package domain; + +class PieceTest { + +} From f563692b1b47a02f33fd55b1433235fae8b5cf61 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Wed, 25 Mar 2026 14:08:25 +0900 Subject: [PATCH 07/87] =?UTF-8?q?feat:=20=EA=B8=B0=EB=AC=BC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20=EB=B0=8F=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Board.java | 64 ++++++++++++++--------------- src/main/java/domain/Piece.java | 16 ++++++++ src/main/java/domain/Type.java | 21 ++++++++++ src/test/java/domain/PieceTest.java | 12 ++++++ 4 files changed, 81 insertions(+), 32 deletions(-) create mode 100644 src/main/java/domain/Piece.java create mode 100644 src/main/java/domain/Type.java diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index cac6642eb8..21cb7811b2 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -11,39 +11,39 @@ public class Board { private Board() { board = new HashMap<>(); - board.put(Position.of(0, 0),Chariot.of(Team.CHU)); - board.put(Position.of(0, 1),Chariot.of(Team.CHU)); - board.put(Position.of(0, 2),Chariot.of(Team.CHU)); - board.put(Position.of(0, 3),Chariot.of(Team.CHU)); - board.put(Position.of(0, 4),Chariot.of(Team.CHU)); - board.put(Position.of(0, 6),Chariot.of(Team.CHU)); - board.put(Position.of(0, 7),Chariot.of(Team.CHU)); - board.put(Position.of(0, 8),Chariot.of(Team.CHU)); - board.put(Position.of(1, 4),Chariot.of(Team.CHU)); - board.put(Position.of(2, 1),Chariot.of(Team.CHU)); - board.put(Position.of(2, 8),Chariot.of(Team.CHU)); - board.put(Position.of(3, 0),Chariot.of(Team.CHU)); - board.put(Position.of(3, 2),Chariot.of(Team.CHU)); - board.put(Position.of(3, 4),Chariot.of(Team.CHU)); - board.put(Position.of(3, 6),Chariot.of(Team.CHU)); - board.put(Position.of(3, 8),Chariot.of(Team.CHU)); + board.put(Position.of(0, 0),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(0, 1),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(0, 2),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(0, 3),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(0, 4),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(0, 6),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(0, 7),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(0, 8),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(1, 4),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(2, 1),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(2, 8),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(3, 0),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(3, 2),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(3, 4),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(3, 6),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(3, 8),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(9, 0),Chariot.of(Team.CHU)); - board.put(Position.of(9, 1),Chariot.of(Team.CHU)); - board.put(Position.of(9, 2),Chariot.of(Team.CHU)); - board.put(Position.of(9, 3),Chariot.of(Team.CHU)); - board.put(Position.of(9, 4),Chariot.of(Team.CHU)); - board.put(Position.of(9, 6),Chariot.of(Team.CHU)); - board.put(Position.of(9, 7),Chariot.of(Team.CHU)); - board.put(Position.of(9, 8),Chariot.of(Team.CHU)); - board.put(Position.of(8, 4),Chariot.of(Team.CHU)); - board.put(Position.of(7, 1),Chariot.of(Team.CHU)); - board.put(Position.of(7, 8),Chariot.of(Team.CHU)); - board.put(Position.of(6, 0),Chariot.of(Team.CHU)); - board.put(Position.of(6, 2),Chariot.of(Team.CHU)); - board.put(Position.of(6, 4),Chariot.of(Team.CHU)); - board.put(Position.of(6, 6),Chariot.of(Team.CHU)); - board.put(Position.of(6, 8),Chariot.of(Team.CHU)); + board.put(Position.of(9, 0),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(9, 1),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(9, 2),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(9, 3),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(9, 4),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(9, 6),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(9, 7),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(9, 8),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(8, 4),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(7, 1),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(7, 8),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(6, 0),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(6, 2),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(6, 4),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(6, 6),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(6, 8),Piece.of(Team.CHU, Type.CHARIOT)); } public static Board of() { diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java new file mode 100644 index 0000000000..7a02e1b431 --- /dev/null +++ b/src/main/java/domain/Piece.java @@ -0,0 +1,16 @@ +package domain; + +public class Piece { + + private final Team team; + private final Type type; + + private Piece(final Team team, final Type type) { + this.team = team; + this.type = type; + } + + public static Piece of(final Team team, final Type type) { + return new Piece(team, type); + } +} diff --git a/src/main/java/domain/Type.java b/src/main/java/domain/Type.java new file mode 100644 index 0000000000..40c055f976 --- /dev/null +++ b/src/main/java/domain/Type.java @@ -0,0 +1,21 @@ +package domain; + +public enum Type { + GENERAL("궁"), + CHARIOT("차"), + CANNON("포"), + HORSE("마"), + ELEPHANT("상"), + GUARD("사"), + SOLIDER("졸"); + + private final String name; + + Type(String name) { + this.name = name; + } + + public Type getType() { + return this; + } +} diff --git a/src/test/java/domain/PieceTest.java b/src/test/java/domain/PieceTest.java index f1a9feecf4..03e8897dd4 100644 --- a/src/test/java/domain/PieceTest.java +++ b/src/test/java/domain/PieceTest.java @@ -1,5 +1,17 @@ package domain; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + class PieceTest { + @Test + @DisplayName("기물을 정상 생성하면 초기화한다.") + void 기물_생성() { + // given + // when + // then + Assertions.assertDoesNotThrow(() -> Piece.of(Team.CHU, Type.CHARIOT)); + } } From cc5bd5d155cb6bca1e21e0eb69b5fd7fb7c3a418 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Wed, 25 Mar 2026 15:52:08 +0900 Subject: [PATCH 08/87] =?UTF-8?q?feat:=20=EA=B8=B0=EB=AC=BC=20=EC=A7=81?= =?UTF-8?q?=EC=84=A0=20=EC=9D=B4=EB=8F=99=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Board.java | 76 +++++++++++-------- src/main/java/domain/Piece.java | 14 +++- .../domain/strategy/CannonMoveStrategy.java | 9 +++ .../domain/strategy/ChariotMoveStrategy.java | 9 +++ .../domain/strategy/ElephantMoveStrategy.java | 9 +++ .../domain/strategy/GeneralMoveStrategy.java | 9 +++ .../domain/strategy/GuardMoveStrategy.java | 9 +++ .../domain/strategy/HorseMoveStrategy.java | 9 +++ .../java/domain/strategy/MoveStrategy.java | 6 ++ .../domain/strategy/SoldierMoveStrategy.java | 9 +++ src/main/java/domain/vo/Position.java | 14 ++++ src/test/java/domain/BoardTest.java | 18 +++++ src/test/java/domain/FixedMoveStrategy.java | 11 +++ src/test/java/domain/PieceTest.java | 2 +- 14 files changed, 167 insertions(+), 37 deletions(-) create mode 100644 src/main/java/domain/strategy/CannonMoveStrategy.java create mode 100644 src/main/java/domain/strategy/ChariotMoveStrategy.java create mode 100644 src/main/java/domain/strategy/ElephantMoveStrategy.java create mode 100644 src/main/java/domain/strategy/GeneralMoveStrategy.java create mode 100644 src/main/java/domain/strategy/GuardMoveStrategy.java create mode 100644 src/main/java/domain/strategy/HorseMoveStrategy.java create mode 100644 src/main/java/domain/strategy/MoveStrategy.java create mode 100644 src/main/java/domain/strategy/SoldierMoveStrategy.java create mode 100644 src/test/java/domain/FixedMoveStrategy.java diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index 21cb7811b2..b374732d61 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -1,5 +1,6 @@ package domain; +import domain.strategy.*; import domain.vo.Position; import java.util.HashMap; @@ -11,42 +12,51 @@ public class Board { private Board() { board = new HashMap<>(); - board.put(Position.of(0, 0),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(0, 1),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(0, 2),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(0, 3),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(0, 4),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(0, 6),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(0, 7),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(0, 8),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(1, 4),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(2, 1),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(2, 8),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(3, 0),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(3, 2),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(3, 4),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(3, 6),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(3, 8),Piece.of(Team.CHU, Type.CHARIOT)); - - board.put(Position.of(9, 0),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(9, 1),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(9, 2),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(9, 3),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(9, 4),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(9, 6),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(9, 7),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(9, 8),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(8, 4),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(7, 1),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(7, 8),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(6, 0),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(6, 2),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(6, 4),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(6, 6),Piece.of(Team.CHU, Type.CHARIOT)); - board.put(Position.of(6, 8),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(0, 0),Piece.of(Team.CHU, Type.CHARIOT, new ChariotMoveStrategy())); + board.put(Position.of(0, 1),Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(0, 2),Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(0, 3),Piece.of(Team.CHU, Type.GUARD, new GuardMoveStrategy())); + board.put(Position.of(0, 5),Piece.of(Team.CHU, Type.GUARD, new GuardMoveStrategy())); + board.put(Position.of(0, 6),Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(0, 7),Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(0, 8),Piece.of(Team.CHU, Type.CHARIOT, new ChariotMoveStrategy())); + board.put(Position.of(1, 4),Piece.of(Team.CHU, Type.GENERAL, new GeneralMoveStrategy())); + board.put(Position.of(2, 1),Piece.of(Team.CHU, Type.CANNON, new CannonMoveStrategy())); + board.put(Position.of(2, 8),Piece.of(Team.CHU, Type.CANNON, new CannonMoveStrategy())); + board.put(Position.of(3, 0),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(3, 2),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(3, 4),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(3, 6),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(3, 8),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); + + board.put(Position.of(9, 0),Piece.of(Team.HAN, Type.CHARIOT, new ChariotMoveStrategy())); + board.put(Position.of(9, 1),Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(9, 2),Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(9, 3),Piece.of(Team.HAN, Type.GUARD, new GuardMoveStrategy())); + board.put(Position.of(9, 5),Piece.of(Team.HAN, Type.GUARD, new GuardMoveStrategy())); + board.put(Position.of(9, 6),Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(9, 7),Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(9, 8),Piece.of(Team.HAN, Type.CHARIOT, new ChariotMoveStrategy())); + board.put(Position.of(8, 4),Piece.of(Team.HAN, Type.GENERAL, new GeneralMoveStrategy())); + board.put(Position.of(7, 1),Piece.of(Team.HAN, Type.CANNON, new CannonMoveStrategy())); + board.put(Position.of(7, 8),Piece.of(Team.HAN, Type.CANNON, new CannonMoveStrategy())); + board.put(Position.of(6, 0),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(6, 2),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(6, 4),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(6, 6),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(6, 8),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); } public static Board of() { return new Board(); } + + public void move(final Position from, final Position to) { + Piece fromPiece = findPieceByPosition(from); + board.put(to, fromPiece); + } + + public Piece findPieceByPosition(final Position position) { + return board.get(position); + } } diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java index 7a02e1b431..a9ba02e47c 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/Piece.java @@ -1,16 +1,24 @@ package domain; +import domain.strategy.MoveStrategy; + public class Piece { private final Team team; private final Type type; + private final MoveStrategy moveStrategy; - private Piece(final Team team, final Type type) { + private Piece(final Team team, final Type type, final MoveStrategy moveStrategy) { this.team = team; this.type = type; + this.moveStrategy = moveStrategy; + } + + public static Piece of(final Team team, final Type type, final MoveStrategy moveStrategy) { + return new Piece(team, type, moveStrategy); } - public static Piece of(final Team team, final Type type) { - return new Piece(team, type); + public Type getType() { + return type; } } diff --git a/src/main/java/domain/strategy/CannonMoveStrategy.java b/src/main/java/domain/strategy/CannonMoveStrategy.java new file mode 100644 index 0000000000..5a4e2dec36 --- /dev/null +++ b/src/main/java/domain/strategy/CannonMoveStrategy.java @@ -0,0 +1,9 @@ +package domain.strategy; + +public class CannonMoveStrategy implements MoveStrategy{ + + @Override + public boolean canMove() { + return false; + } +} diff --git a/src/main/java/domain/strategy/ChariotMoveStrategy.java b/src/main/java/domain/strategy/ChariotMoveStrategy.java new file mode 100644 index 0000000000..61da20510a --- /dev/null +++ b/src/main/java/domain/strategy/ChariotMoveStrategy.java @@ -0,0 +1,9 @@ +package domain.strategy; + +public class ChariotMoveStrategy implements MoveStrategy{ + + @Override + public boolean canMove() { + return false; + } +} diff --git a/src/main/java/domain/strategy/ElephantMoveStrategy.java b/src/main/java/domain/strategy/ElephantMoveStrategy.java new file mode 100644 index 0000000000..99578043d4 --- /dev/null +++ b/src/main/java/domain/strategy/ElephantMoveStrategy.java @@ -0,0 +1,9 @@ +package domain.strategy; + +public class ElephantMoveStrategy implements MoveStrategy{ + + @Override + public boolean canMove() { + return false; + } +} diff --git a/src/main/java/domain/strategy/GeneralMoveStrategy.java b/src/main/java/domain/strategy/GeneralMoveStrategy.java new file mode 100644 index 0000000000..edffd50a45 --- /dev/null +++ b/src/main/java/domain/strategy/GeneralMoveStrategy.java @@ -0,0 +1,9 @@ +package domain.strategy; + +public class GeneralMoveStrategy implements MoveStrategy{ + + @Override + public boolean canMove() { + return false; + } +} diff --git a/src/main/java/domain/strategy/GuardMoveStrategy.java b/src/main/java/domain/strategy/GuardMoveStrategy.java new file mode 100644 index 0000000000..068a01d22e --- /dev/null +++ b/src/main/java/domain/strategy/GuardMoveStrategy.java @@ -0,0 +1,9 @@ +package domain.strategy; + +public class GuardMoveStrategy implements MoveStrategy{ + + @Override + public boolean canMove() { + return false; + } +} diff --git a/src/main/java/domain/strategy/HorseMoveStrategy.java b/src/main/java/domain/strategy/HorseMoveStrategy.java new file mode 100644 index 0000000000..22f9cdf57c --- /dev/null +++ b/src/main/java/domain/strategy/HorseMoveStrategy.java @@ -0,0 +1,9 @@ +package domain.strategy; + +public class HorseMoveStrategy implements MoveStrategy{ + + @Override + public boolean canMove() { + return false; + } +} diff --git a/src/main/java/domain/strategy/MoveStrategy.java b/src/main/java/domain/strategy/MoveStrategy.java new file mode 100644 index 0000000000..beea633e62 --- /dev/null +++ b/src/main/java/domain/strategy/MoveStrategy.java @@ -0,0 +1,6 @@ +package domain.strategy; + +public interface MoveStrategy { + + boolean canMove(); +} diff --git a/src/main/java/domain/strategy/SoldierMoveStrategy.java b/src/main/java/domain/strategy/SoldierMoveStrategy.java new file mode 100644 index 0000000000..05cc9f5e01 --- /dev/null +++ b/src/main/java/domain/strategy/SoldierMoveStrategy.java @@ -0,0 +1,9 @@ +package domain.strategy; + +public class SoldierMoveStrategy implements MoveStrategy{ + + @Override + public boolean canMove() { + return false; + } +} diff --git a/src/main/java/domain/vo/Position.java b/src/main/java/domain/vo/Position.java index 8b43b287a0..2b6ed562ed 100644 --- a/src/main/java/domain/vo/Position.java +++ b/src/main/java/domain/vo/Position.java @@ -1,5 +1,7 @@ package domain.vo; +import java.util.Objects; + public class Position { private final int row; @@ -39,4 +41,16 @@ public int getRow() { public int getCol() { return this.col; } + + @Override + public boolean equals(Object object) { + if (object == null || getClass() != object.getClass()) return false; + Position position = (Position) object; + return row == position.row && col == position.col; + } + + @Override + public int hashCode() { + return Objects.hash(row, col); + } } diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java index 1694e90d64..2121aa41d8 100644 --- a/src/test/java/domain/BoardTest.java +++ b/src/test/java/domain/BoardTest.java @@ -1,5 +1,7 @@ package domain; +import domain.vo.Position; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -15,4 +17,20 @@ class BoardTest { // then assertDoesNotThrow(Board::of); } + + @Test + @DisplayName("기물의 직선 이동 경로에 다른 기물이 없으면 이동한다.") + void 기물_직선_이동() { + // given + Board board = Board.of(); + + // when + Position from = Position.of(0, 0); + Position to = Position.of(1, 0); + board.move(from, to); + + // then + Piece findPiece = board.findPieceByPosition(to); + Assertions.assertEquals(Type.CHARIOT, findPiece.getType()); + } } diff --git a/src/test/java/domain/FixedMoveStrategy.java b/src/test/java/domain/FixedMoveStrategy.java new file mode 100644 index 0000000000..b98fc1fa89 --- /dev/null +++ b/src/test/java/domain/FixedMoveStrategy.java @@ -0,0 +1,11 @@ +package domain; + +import domain.strategy.MoveStrategy; + +public class FixedMoveStrategy implements MoveStrategy { + + @Override + public boolean canMove() { + return true; + } +} diff --git a/src/test/java/domain/PieceTest.java b/src/test/java/domain/PieceTest.java index 03e8897dd4..048087c053 100644 --- a/src/test/java/domain/PieceTest.java +++ b/src/test/java/domain/PieceTest.java @@ -12,6 +12,6 @@ class PieceTest { // given // when // then - Assertions.assertDoesNotThrow(() -> Piece.of(Team.CHU, Type.CHARIOT)); + Assertions.assertDoesNotThrow(() -> Piece.of(Team.CHU, Type.CHARIOT, new FixedMoveStrategy())); } } From d9272408d85400582454f3dc5a55248e01066369 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Wed, 25 Mar 2026 16:36:20 +0900 Subject: [PATCH 09/87] =?UTF-8?q?feat:=20=EB=8C=80=EA=B0=81=EC=84=A0=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Board.java | 7 ++++++- .../domain/strategy/ChariotMoveStrategy.java | 2 ++ src/test/java/domain/BoardTest.java | 18 +++++++++++++++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index b374732d61..7f15039e22 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -51,7 +51,12 @@ public static Board of() { return new Board(); } - public void move(final Position from, final Position to) { + public void straightMove(final Position from, final Position to) { + Piece fromPiece = findPieceByPosition(from); + board.put(to, fromPiece); + } + + public void diagonalMove(final Position from, final Position to) { Piece fromPiece = findPieceByPosition(from); board.put(to, fromPiece); } diff --git a/src/main/java/domain/strategy/ChariotMoveStrategy.java b/src/main/java/domain/strategy/ChariotMoveStrategy.java index 61da20510a..754b3163fa 100644 --- a/src/main/java/domain/strategy/ChariotMoveStrategy.java +++ b/src/main/java/domain/strategy/ChariotMoveStrategy.java @@ -4,6 +4,8 @@ public class ChariotMoveStrategy implements MoveStrategy{ @Override public boolean canMove() { + + return false; } } diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java index 2121aa41d8..e326a2bf5b 100644 --- a/src/test/java/domain/BoardTest.java +++ b/src/test/java/domain/BoardTest.java @@ -6,6 +6,7 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; class BoardTest { @@ -27,10 +28,25 @@ class BoardTest { // when Position from = Position.of(0, 0); Position to = Position.of(1, 0); - board.move(from, to); + board.straightMove(from, to); // then Piece findPiece = board.findPieceByPosition(to); Assertions.assertEquals(Type.CHARIOT, findPiece.getType()); } + + @Test + @DisplayName("기물의 대각선 이동 경로에 다른 기물이 없으면 이동한다.") + void 기물_대각선_이동() { + // given + Board board = Board.of(); + Position to = Position.of(3, 3); + + // when + board.straightMove(Position.of(0, 1), Position.of(1, 1)); + board.diagonalMove(Position.of(1, 1), to); + + // then + assertEquals(Type.ELEPHANT, board.findPieceByPosition(to).getType()); + } } From d706d5b8cf0e2b151e20e6940361b999690406bd Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Wed, 25 Mar 2026 17:12:24 +0900 Subject: [PATCH 10/87] =?UTF-8?q?feat:=20=EC=A7=81=EC=84=A0=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EC=A0=84=EB=9E=B5=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Board.java | 10 +++-- .../domain/strategy/CannonMoveStrategy.java | 7 +++- .../domain/strategy/ChariotMoveStrategy.java | 39 +++++++++++++++++-- .../domain/strategy/ElephantMoveStrategy.java | 8 +++- .../domain/strategy/GeneralMoveStrategy.java | 7 +++- .../domain/strategy/GuardMoveStrategy.java | 6 ++- .../domain/strategy/HorseMoveStrategy.java | 7 +++- .../java/domain/strategy/MoveStrategy.java | 5 ++- .../domain/strategy/SoldierMoveStrategy.java | 7 +++- src/test/java/domain/BoardTest.java | 5 +-- src/test/java/domain/FixedMoveStrategy.java | 5 ++- .../strategy/ChariotMoveStrategyTest.java | 25 ++++++++++++ 12 files changed, 108 insertions(+), 23 deletions(-) create mode 100644 src/test/java/domain/strategy/ChariotMoveStrategyTest.java diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index 7f15039e22..e030438de4 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -56,11 +56,15 @@ public void straightMove(final Position from, final Position to) { board.put(to, fromPiece); } - public void diagonalMove(final Position from, final Position to) { - Piece fromPiece = findPieceByPosition(from); - board.put(to, fromPiece); + public boolean isExistPosition(Position tempPosition) { + return board.containsKey(tempPosition); } +// public void diagonalMove(final Position from, final Position to) { +// Piece fromPiece = findPieceByPosition(from); +// board.put(to, fromPiece); +// } + public Piece findPieceByPosition(final Position position) { return board.get(position); } diff --git a/src/main/java/domain/strategy/CannonMoveStrategy.java b/src/main/java/domain/strategy/CannonMoveStrategy.java index 5a4e2dec36..cbb227e5d0 100644 --- a/src/main/java/domain/strategy/CannonMoveStrategy.java +++ b/src/main/java/domain/strategy/CannonMoveStrategy.java @@ -1,9 +1,12 @@ package domain.strategy; -public class CannonMoveStrategy implements MoveStrategy{ +import domain.Board; +import domain.vo.Position; + +public class CannonMoveStrategy implements MoveStrategy { @Override - public boolean canMove() { + public boolean canMove(Position from, Position to, Board board) { return false; } } diff --git a/src/main/java/domain/strategy/ChariotMoveStrategy.java b/src/main/java/domain/strategy/ChariotMoveStrategy.java index 754b3163fa..84a236c605 100644 --- a/src/main/java/domain/strategy/ChariotMoveStrategy.java +++ b/src/main/java/domain/strategy/ChariotMoveStrategy.java @@ -1,11 +1,44 @@ package domain.strategy; +import domain.Board; +import domain.vo.Position; + public class ChariotMoveStrategy implements MoveStrategy{ @Override - public boolean canMove() { - + public boolean canMove(Position from, Position to, Board board) { + int currentRow = from.getRow(); + int currentCol = from.getCol(); + + int targetRow = to.getRow(); + int targetCol = to.getCol(); + + if (currentCol != targetCol && currentRow != targetRow) { + return false; + } + + if (currentCol == targetCol) { + int min = Math.min(currentRow, targetRow) + 1; + int max = Math.max(currentRow, targetRow); + + for (int temp = min; temp < max; temp++) { + if (board.isExistPosition(Position.of(temp, currentCol))) { + return false; + } + } + } + + if (targetRow == currentRow) { + int min = Math.min(currentCol, targetCol) + 1; + int max = Math.max(currentCol, targetCol); + + for (int temp = min; temp < max; temp++) { + if (board.isExistPosition(Position.of(currentRow, temp))) { + return false; + } + } + } - return false; + return true; } } diff --git a/src/main/java/domain/strategy/ElephantMoveStrategy.java b/src/main/java/domain/strategy/ElephantMoveStrategy.java index 99578043d4..736050399d 100644 --- a/src/main/java/domain/strategy/ElephantMoveStrategy.java +++ b/src/main/java/domain/strategy/ElephantMoveStrategy.java @@ -1,9 +1,13 @@ package domain.strategy; -public class ElephantMoveStrategy implements MoveStrategy{ +import domain.Board; +import domain.vo.Position; + +public class ElephantMoveStrategy implements MoveStrategy { + @Override - public boolean canMove() { + public boolean canMove(Position from, Position to, Board board) { return false; } } diff --git a/src/main/java/domain/strategy/GeneralMoveStrategy.java b/src/main/java/domain/strategy/GeneralMoveStrategy.java index edffd50a45..59912a2ade 100644 --- a/src/main/java/domain/strategy/GeneralMoveStrategy.java +++ b/src/main/java/domain/strategy/GeneralMoveStrategy.java @@ -1,9 +1,12 @@ package domain.strategy; -public class GeneralMoveStrategy implements MoveStrategy{ +import domain.Board; +import domain.vo.Position; + +public class GeneralMoveStrategy implements MoveStrategy { @Override - public boolean canMove() { + public boolean canMove(Position from, Position to, Board board) { return false; } } diff --git a/src/main/java/domain/strategy/GuardMoveStrategy.java b/src/main/java/domain/strategy/GuardMoveStrategy.java index 068a01d22e..b724bb8284 100644 --- a/src/main/java/domain/strategy/GuardMoveStrategy.java +++ b/src/main/java/domain/strategy/GuardMoveStrategy.java @@ -1,9 +1,13 @@ package domain.strategy; +import domain.Board; +import domain.vo.Position; + public class GuardMoveStrategy implements MoveStrategy{ + @Override - public boolean canMove() { + public boolean canMove(Position from, Position to, Board board) { return false; } } diff --git a/src/main/java/domain/strategy/HorseMoveStrategy.java b/src/main/java/domain/strategy/HorseMoveStrategy.java index 22f9cdf57c..eff5f2362a 100644 --- a/src/main/java/domain/strategy/HorseMoveStrategy.java +++ b/src/main/java/domain/strategy/HorseMoveStrategy.java @@ -1,9 +1,12 @@ package domain.strategy; -public class HorseMoveStrategy implements MoveStrategy{ +import domain.Board; +import domain.vo.Position; + +public class HorseMoveStrategy implements MoveStrategy { @Override - public boolean canMove() { + public boolean canMove(Position from, Position to, Board board) { return false; } } diff --git a/src/main/java/domain/strategy/MoveStrategy.java b/src/main/java/domain/strategy/MoveStrategy.java index beea633e62..f457f78b9e 100644 --- a/src/main/java/domain/strategy/MoveStrategy.java +++ b/src/main/java/domain/strategy/MoveStrategy.java @@ -1,6 +1,9 @@ package domain.strategy; +import domain.Board; +import domain.vo.Position; + public interface MoveStrategy { - boolean canMove(); + boolean canMove(Position from, Position to, Board board); } diff --git a/src/main/java/domain/strategy/SoldierMoveStrategy.java b/src/main/java/domain/strategy/SoldierMoveStrategy.java index 05cc9f5e01..077d201d11 100644 --- a/src/main/java/domain/strategy/SoldierMoveStrategy.java +++ b/src/main/java/domain/strategy/SoldierMoveStrategy.java @@ -1,9 +1,12 @@ package domain.strategy; -public class SoldierMoveStrategy implements MoveStrategy{ +import domain.Board; +import domain.vo.Position; + +public class SoldierMoveStrategy implements MoveStrategy { @Override - public boolean canMove() { + public boolean canMove(Position from, Position to, Board board) { return false; } } diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java index e326a2bf5b..6523cce427 100644 --- a/src/test/java/domain/BoardTest.java +++ b/src/test/java/domain/BoardTest.java @@ -6,7 +6,6 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertEquals; class BoardTest { @@ -44,9 +43,9 @@ class BoardTest { // when board.straightMove(Position.of(0, 1), Position.of(1, 1)); - board.diagonalMove(Position.of(1, 1), to); + // board.diagonalMove(Position.of(1, 1), to); // then - assertEquals(Type.ELEPHANT, board.findPieceByPosition(to).getType()); + // assertEquals(Type.ELEPHANT, board.findPieceByPosition(to).getType()); } } diff --git a/src/test/java/domain/FixedMoveStrategy.java b/src/test/java/domain/FixedMoveStrategy.java index b98fc1fa89..63d1a9ea55 100644 --- a/src/test/java/domain/FixedMoveStrategy.java +++ b/src/test/java/domain/FixedMoveStrategy.java @@ -1,11 +1,12 @@ package domain; import domain.strategy.MoveStrategy; +import domain.vo.Position; public class FixedMoveStrategy implements MoveStrategy { @Override - public boolean canMove() { - return true; + public boolean canMove(Position from, Position to, Board board) { + return false; } } diff --git a/src/test/java/domain/strategy/ChariotMoveStrategyTest.java b/src/test/java/domain/strategy/ChariotMoveStrategyTest.java new file mode 100644 index 0000000000..bf83a09b1c --- /dev/null +++ b/src/test/java/domain/strategy/ChariotMoveStrategyTest.java @@ -0,0 +1,25 @@ +package domain.strategy; + +import domain.Board; +import domain.vo.Position; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class ChariotMoveStrategyTest { + + @Test + @DisplayName("차의 직선 이동 경로에 기물이 없으면 직선 이동한다.") + void 차_직선_이동() { + // given + ChariotMoveStrategy strategy = new ChariotMoveStrategy(); + Board board = Board.of(); + + // when + Position from = Position.of(0, 0); + Position to = Position.of(2, 0); + + // then + Assertions.assertTrue(strategy.canMove(from, to, board)); + } +} From 4c73af09a7cf913b59925e61324eacae60571650 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Wed, 25 Mar 2026 17:40:44 +0900 Subject: [PATCH 11/87] =?UTF-8?q?feat:=20=EC=B0=A8=20=EC=A0=84=EB=9E=B5=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EB=B0=8F=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Piece.java | 4 ++ .../domain/strategy/ChariotMoveStrategy.java | 41 ++++++++++++++----- .../strategy/ChariotMoveStrategyTest.java | 30 ++++++++++++++ 3 files changed, 65 insertions(+), 10 deletions(-) diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java index a9ba02e47c..2b1cd6e5df 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/Piece.java @@ -21,4 +21,8 @@ public static Piece of(final Team team, final Type type, final MoveStrategy move public Type getType() { return type; } + + public Team getTeam() { + return team; + } } diff --git a/src/main/java/domain/strategy/ChariotMoveStrategy.java b/src/main/java/domain/strategy/ChariotMoveStrategy.java index 84a236c605..8c34273cf3 100644 --- a/src/main/java/domain/strategy/ChariotMoveStrategy.java +++ b/src/main/java/domain/strategy/ChariotMoveStrategy.java @@ -1,6 +1,7 @@ package domain.strategy; import domain.Board; +import domain.Piece; import domain.vo.Position; public class ChariotMoveStrategy implements MoveStrategy{ @@ -13,18 +14,18 @@ public boolean canMove(Position from, Position to, Board board) { int targetRow = to.getRow(); int targetCol = to.getCol(); - if (currentCol != targetCol && currentRow != targetRow) { + if (checkStraightPath(currentCol, targetCol, currentRow, targetRow)) return false; - } if (currentCol == targetCol) { int min = Math.min(currentRow, targetRow) + 1; int max = Math.max(currentRow, targetRow); - for (int temp = min; temp < max; temp++) { - if (board.isExistPosition(Position.of(temp, currentCol))) { - return false; - } + if (checkClearPath(board, min, max, currentCol)) + return false; + + if (board.isExistPosition(Position.of(targetRow, targetCol))) { + return isOtherTeam(board, currentRow, currentCol, targetRow, targetCol); } } @@ -32,13 +33,33 @@ public boolean canMove(Position from, Position to, Board board) { int min = Math.min(currentCol, targetCol) + 1; int max = Math.max(currentCol, targetCol); - for (int temp = min; temp < max; temp++) { - if (board.isExistPosition(Position.of(currentRow, temp))) { - return false; - } + if (checkClearPath(board, min, max, currentCol)) + return false; + + if (board.isExistPosition(Position.of(targetRow, targetCol))) { + return isOtherTeam(board, currentRow, currentCol, targetRow, targetCol); } } return true; } + + private boolean checkStraightPath(int currentCol, int targetCol, int currentRow, int targetRow) { + return currentCol != targetCol && currentRow != targetRow; + } + + private boolean isOtherTeam(Board board, int currentRow, int currentCol, int targetRow, int targetCol) { + Piece currentPiece = board.findPieceByPosition(Position.of(currentRow, currentCol)); + Piece targetPiece = board.findPieceByPosition(Position.of(targetRow, targetCol)); + return currentPiece.getTeam() != targetPiece.getTeam(); + } + + private boolean checkClearPath(Board board, int min, int max, int currentCol) { + for (int temp = min; temp < max; temp++) { + if (board.isExistPosition(Position.of(temp, currentCol))) { + return true; + } + } + return false; + } } diff --git a/src/test/java/domain/strategy/ChariotMoveStrategyTest.java b/src/test/java/domain/strategy/ChariotMoveStrategyTest.java index bf83a09b1c..53c6691f10 100644 --- a/src/test/java/domain/strategy/ChariotMoveStrategyTest.java +++ b/src/test/java/domain/strategy/ChariotMoveStrategyTest.java @@ -22,4 +22,34 @@ class ChariotMoveStrategyTest { // then Assertions.assertTrue(strategy.canMove(from, to, board)); } + + @Test + @DisplayName("이동 목적지에 같은 팀 기물이 있으면 직선 이동하지 않는다.") + void 차_목적지에_같은_팀_기물이_있으면_이동_불가() { + // given + ChariotMoveStrategy strategy = new ChariotMoveStrategy(); + Board board = Board.of(); + + // when + Position from = Position.of(0, 0); + Position to = Position.of(3, 0); + + // then + Assertions.assertFalse(strategy.canMove(from, to, board)); + } + + @Test + @DisplayName("이동 목적지에 다른 팀 기물이 있으면 직선 이동한다.") + void 차_목적지에_다른_팀_기물이_있으면_이동_가능() { + // given + ChariotMoveStrategy strategy = new ChariotMoveStrategy(); + Board board = Board.of(); + + // when + Position from = Position.of(3, 0); + Position to = Position.of(6, 0); + + // then + Assertions.assertTrue(strategy.canMove(from, to, board)); + } } From 715bc707bdb0db34b9591ea90d79bd3a8cab1dec Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Wed, 25 Mar 2026 17:59:50 +0900 Subject: [PATCH 12/87] =?UTF-8?q?feat:=20=EC=83=81=20=EC=A0=84=EB=9E=B5=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EB=B0=8F=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=EC=A1=B0?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/ElephantMoveStrategy.java | 9 +++++++ .../strategy/ElephantMoveStrategyTest.java | 27 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/test/java/domain/strategy/ElephantMoveStrategyTest.java diff --git a/src/main/java/domain/strategy/ElephantMoveStrategy.java b/src/main/java/domain/strategy/ElephantMoveStrategy.java index 736050399d..38d6ba293b 100644 --- a/src/main/java/domain/strategy/ElephantMoveStrategy.java +++ b/src/main/java/domain/strategy/ElephantMoveStrategy.java @@ -8,6 +8,15 @@ public class ElephantMoveStrategy implements MoveStrategy { @Override public boolean canMove(Position from, Position to, Board board) { + int currentRow = from.getRow(); + int currentCol = from.getCol(); + + int targetRow = to.getRow(); + int targetCol = to.getCol(); + +// if (checkStraightPath(currentCol, targetCol, currentRow, targetRow)) +// return false; + return false; } } diff --git a/src/test/java/domain/strategy/ElephantMoveStrategyTest.java b/src/test/java/domain/strategy/ElephantMoveStrategyTest.java new file mode 100644 index 0000000000..de2c1c3526 --- /dev/null +++ b/src/test/java/domain/strategy/ElephantMoveStrategyTest.java @@ -0,0 +1,27 @@ +package domain.strategy; + +import domain.Board; +import domain.vo.Position; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class ElephantMoveStrategyTest { + + @Test + @DisplayName("상의 이동 경로에 다른 기물이 없으면 정상 이동한다.") + void 상_정상_이동() { + // given + MoveStrategy strategy = new ElephantMoveStrategy(); + Board board = Board.of(); + + // when + Position from = Position.of(0, 1); + Position to = Position.of(3, 3); + + // then + Assertions.assertTrue(strategy.canMove(from, to, board)); + } +} From a915e9e42761e3c0428fb433d02fe16e750c6cf6 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Wed, 25 Mar 2026 19:11:26 +0900 Subject: [PATCH 13/87] =?UTF-8?q?refactor:=20=EC=B0=A8=20=EC=A0=84?= =?UTF-8?q?=EB=9E=B5=20=ED=8C=A8=ED=84=B4=20=EB=A9=94=EC=86=8C=EB=93=9C=20?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/strategy/ChariotMoveStrategy.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/domain/strategy/ChariotMoveStrategy.java b/src/main/java/domain/strategy/ChariotMoveStrategy.java index 8c34273cf3..d677017046 100644 --- a/src/main/java/domain/strategy/ChariotMoveStrategy.java +++ b/src/main/java/domain/strategy/ChariotMoveStrategy.java @@ -14,7 +14,7 @@ public boolean canMove(Position from, Position to, Board board) { int targetRow = to.getRow(); int targetCol = to.getCol(); - if (checkStraightPath(currentCol, targetCol, currentRow, targetRow)) + if (checkNotStraightPath(currentCol, targetCol, currentRow, targetRow)) return false; if (currentCol == targetCol) { @@ -44,7 +44,7 @@ public boolean canMove(Position from, Position to, Board board) { return true; } - private boolean checkStraightPath(int currentCol, int targetCol, int currentRow, int targetRow) { + private boolean checkNotStraightPath(int currentCol, int targetCol, int currentRow, int targetRow) { return currentCol != targetCol && currentRow != targetRow; } From 750232aca8a73f19a9668fc9922f9652eb1ac46b Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Wed, 25 Mar 2026 19:46:50 +0900 Subject: [PATCH 14/87] =?UTF-8?q?feat:=20=EC=83=81=20=EC=A0=84=EB=9E=B5=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/ElephantMoveStrategy.java | 100 +++++++++++++++++- .../strategy/ElephantMoveStrategyTest.java | 36 ++++++- 2 files changed, 128 insertions(+), 8 deletions(-) diff --git a/src/main/java/domain/strategy/ElephantMoveStrategy.java b/src/main/java/domain/strategy/ElephantMoveStrategy.java index 38d6ba293b..1c4fa5e37b 100644 --- a/src/main/java/domain/strategy/ElephantMoveStrategy.java +++ b/src/main/java/domain/strategy/ElephantMoveStrategy.java @@ -5,7 +5,6 @@ public class ElephantMoveStrategy implements MoveStrategy { - @Override public boolean canMove(Position from, Position to, Board board) { int currentRow = from.getRow(); @@ -14,9 +13,102 @@ public boolean canMove(Position from, Position to, Board board) { int targetRow = to.getRow(); int targetCol = to.getCol(); -// if (checkStraightPath(currentCol, targetCol, currentRow, targetRow)) -// return false; + if (Math.abs(currentRow - targetRow) == 3) { + if (targetRow > currentRow) { + currentRow += 1; + if (board.isExistPosition(Position.of(currentRow, currentCol))) { + return false; + } + if (currentCol < targetCol) { + if (board.isExistPosition(Position.of(currentRow + 1, currentCol + 1)) + || board.isExistPosition(Position.of(currentRow + 2, currentCol + 2))) { + return false; + } + return true; + } + if (currentCol > targetCol) { + if (board.isExistPosition(Position.of(currentRow + 1, currentCol - 1)) + || board.isExistPosition(Position.of(currentRow + 2, currentCol - 2))) { + return false; + } + return true; + } + } + + if (targetRow < currentRow) { + currentRow -= 1; + if (board.isExistPosition(Position.of(currentRow, currentCol))) { + return false; + } + if (currentCol < targetCol) { + if (board.isExistPosition(Position.of(currentRow - 1, currentCol + 1)) + || board.isExistPosition(Position.of(currentRow - 2, currentCol + 2))) { + return false; + } + + return true; + } + if (currentCol > targetCol) { + if (board.isExistPosition(Position.of(currentRow - 1, currentCol - 1)) + || board.isExistPosition(Position.of(currentRow - 2, currentCol - 2))) { + return false; + } + + return true; + } + } + } + + if (Math.abs(currentRow - targetRow) == 2) { + if (targetCol > currentCol) { + currentCol += 1; + if (board.isExistPosition(Position.of(currentRow, currentCol))) { + return false; + } + + if (currentRow < targetRow) { + if (board.isExistPosition(Position.of(currentRow + 1, currentCol + 1)) + || board.isExistPosition(Position.of(currentRow + 2, currentCol + 2))) { + return false; + } + + return true; + } + if (currentRow > targetRow) { + if (board.isExistPosition(Position.of(currentRow - 1, currentCol + 1)) + || board.isExistPosition(Position.of(currentRow - 2, currentCol + 2))) { + return false; + } + + return true; + } + } + + if (targetCol < currentCol) { + currentCol -= 1; + if (board.isExistPosition(Position.of(currentRow, currentCol))) { + return false; + } + + if (currentRow < targetRow) { + if (board.isExistPosition(Position.of(currentRow + 1, currentCol - 1)) + || board.isExistPosition(Position.of(currentRow + 2, currentCol - 2))) { + return false; + } + + return true; + } + if (currentRow > targetRow) { + if (board.isExistPosition(Position.of(currentRow - 1, currentCol - 1)) + || board.isExistPosition(Position.of(currentRow - 2, currentCol - 2))) { + return false; + } + + return true; + } + } + } - return false; + return true; } } diff --git a/src/test/java/domain/strategy/ElephantMoveStrategyTest.java b/src/test/java/domain/strategy/ElephantMoveStrategyTest.java index de2c1c3526..7a864040db 100644 --- a/src/test/java/domain/strategy/ElephantMoveStrategyTest.java +++ b/src/test/java/domain/strategy/ElephantMoveStrategyTest.java @@ -6,13 +6,11 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - class ElephantMoveStrategyTest { @Test - @DisplayName("상의 이동 경로에 다른 기물이 없으면 정상 이동한다.") - void 상_정상_이동() { + @DisplayName("초나라 상의 이동 경로에 다른 기물이 없으면 정상 이동한다.") + void 초나라_상_정상_이동() { // given MoveStrategy strategy = new ElephantMoveStrategy(); Board board = Board.of(); @@ -24,4 +22,34 @@ class ElephantMoveStrategyTest { // then Assertions.assertTrue(strategy.canMove(from, to, board)); } + + @Test + @DisplayName("한나라 상의 이동 경로에 다른 기물이 없으면 정상 이동한다.") + void 한나라_상_정상_이동() { + // given + MoveStrategy strategy = new ElephantMoveStrategy(); + Board board = Board.of(); + + // when + Position from = Position.of(9, 1); + Position to = Position.of(6, 3); + + // then + Assertions.assertTrue(strategy.canMove(from, to, board)); + } + + @Test + @DisplayName("초나라 상의 이동 경로에 기물이 있으면 이동하지 않는다.") + void 초나라_상_이동_경로에_기물이_있으면_이동_불가() { + // given + MoveStrategy strategy = new ElephantMoveStrategy(); + Board board = Board.of(); + + // when + Position from = Position.of(0, 1); + Position to = Position.of(2, 4); + + // then + Assertions.assertFalse(strategy.canMove(from, to, board)); + } } From 4265ad4e88dae6e7b7046be6d77f062586f29da1 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Wed, 25 Mar 2026 20:03:45 +0900 Subject: [PATCH 15/87] =?UTF-8?q?feat:=20=EC=83=81=20=EB=AA=A9=EC=A0=81?= =?UTF-8?q?=EC=A7=80=20=EA=B8=B0=EB=AC=BC=EB=B3=84=20=EC=9D=B4=EB=8F=99=20?= =?UTF-8?q?=ED=8C=90=EC=A0=95=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=ED=8C=90=EC=A0=95=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/ElephantMoveStrategy.java | 61 ++++++++++++------- .../strategy/ElephantMoveStrategyTest.java | 30 +++++++++ 2 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/main/java/domain/strategy/ElephantMoveStrategy.java b/src/main/java/domain/strategy/ElephantMoveStrategy.java index 1c4fa5e37b..b6cb006540 100644 --- a/src/main/java/domain/strategy/ElephantMoveStrategy.java +++ b/src/main/java/domain/strategy/ElephantMoveStrategy.java @@ -1,6 +1,7 @@ package domain.strategy; import domain.Board; +import domain.Piece; import domain.vo.Position; public class ElephantMoveStrategy implements MoveStrategy { @@ -20,17 +21,21 @@ public boolean canMove(Position from, Position to, Board board) { return false; } if (currentCol < targetCol) { - if (board.isExistPosition(Position.of(currentRow + 1, currentCol + 1)) - || board.isExistPosition(Position.of(currentRow + 2, currentCol + 2))) { + if (board.isExistPosition(Position.of(currentRow + 1, currentCol + 1))) { return false; } + if (board.isExistPosition(Position.of(currentRow + 2, currentCol + 2))) { + return isOtherTeam(board, currentRow + 2, currentCol + 2, targetRow, targetCol); + } return true; } if (currentCol > targetCol) { - if (board.isExistPosition(Position.of(currentRow + 1, currentCol - 1)) - || board.isExistPosition(Position.of(currentRow + 2, currentCol - 2))) { + if (board.isExistPosition(Position.of(currentRow + 1, currentCol - 1))) { return false; } + if (board.isExistPosition(Position.of(currentRow + 2, currentCol - 2))) { + return isOtherTeam(board, currentRow + 2, currentCol - 2, targetRow, targetCol); + } return true; } } @@ -41,19 +46,21 @@ public boolean canMove(Position from, Position to, Board board) { return false; } if (currentCol < targetCol) { - if (board.isExistPosition(Position.of(currentRow - 1, currentCol + 1)) - || board.isExistPosition(Position.of(currentRow - 2, currentCol + 2))) { + if (board.isExistPosition(Position.of(currentRow - 1, currentCol + 1))) { return false; } - + if (board.isExistPosition(Position.of(currentRow - 2, currentCol + 2))) { + return isOtherTeam(board, currentRow - 2, currentCol + 2, targetRow, targetCol); + } return true; } if (currentCol > targetCol) { - if (board.isExistPosition(Position.of(currentRow - 1, currentCol - 1)) - || board.isExistPosition(Position.of(currentRow - 2, currentCol - 2))) { + if (board.isExistPosition(Position.of(currentRow - 1, currentCol - 1))) { return false; } - + if (board.isExistPosition(Position.of(currentRow - 2, currentCol - 2))) { + return isOtherTeam(board, currentRow - 2, currentCol - 2, targetRow, targetCol); + } return true; } } @@ -67,19 +74,21 @@ public boolean canMove(Position from, Position to, Board board) { } if (currentRow < targetRow) { - if (board.isExistPosition(Position.of(currentRow + 1, currentCol + 1)) - || board.isExistPosition(Position.of(currentRow + 2, currentCol + 2))) { + if (board.isExistPosition(Position.of(currentRow + 1, currentCol + 1))) { return false; } - + if (board.isExistPosition(Position.of(currentRow + 2, currentCol + 2))) { + return isOtherTeam(board, currentRow + 2, currentCol + 2, targetRow, targetCol); + } return true; } if (currentRow > targetRow) { - if (board.isExistPosition(Position.of(currentRow - 1, currentCol + 1)) - || board.isExistPosition(Position.of(currentRow - 2, currentCol + 2))) { + if (board.isExistPosition(Position.of(currentRow - 1, currentCol + 1))) { return false; } - + if (board.isExistPosition(Position.of(currentRow - 2, currentCol + 2))) { + return isOtherTeam(board, currentRow - 2, currentCol + 2, targetRow, targetCol); + } return true; } } @@ -91,19 +100,21 @@ public boolean canMove(Position from, Position to, Board board) { } if (currentRow < targetRow) { - if (board.isExistPosition(Position.of(currentRow + 1, currentCol - 1)) - || board.isExistPosition(Position.of(currentRow + 2, currentCol - 2))) { + if (board.isExistPosition(Position.of(currentRow + 1, currentCol - 1))) { return false; } - + if (board.isExistPosition(Position.of(currentRow + 2, currentCol - 2))) { + return isOtherTeam(board, currentRow + 2, currentCol - 2, targetRow, targetCol); + } return true; } if (currentRow > targetRow) { - if (board.isExistPosition(Position.of(currentRow - 1, currentCol - 1)) - || board.isExistPosition(Position.of(currentRow - 2, currentCol - 2))) { + if (board.isExistPosition(Position.of(currentRow - 1, currentCol - 1))) { return false; } - + if (board.isExistPosition(Position.of(currentRow - 2, currentCol - 2))) { + return isOtherTeam(board, currentRow - 2, currentCol - 2, targetRow, targetCol); + } return true; } } @@ -111,4 +122,10 @@ public boolean canMove(Position from, Position to, Board board) { return true; } + + private boolean isOtherTeam(Board board, int currentRow, int currentCol, int targetRow, int targetCol) { + Piece currentPiece = board.findPieceByPosition(Position.of(currentRow, currentCol)); + Piece targetPiece = board.findPieceByPosition(Position.of(targetRow, targetCol)); + return currentPiece.getTeam() != targetPiece.getTeam(); + } } diff --git a/src/test/java/domain/strategy/ElephantMoveStrategyTest.java b/src/test/java/domain/strategy/ElephantMoveStrategyTest.java index 7a864040db..89dead9347 100644 --- a/src/test/java/domain/strategy/ElephantMoveStrategyTest.java +++ b/src/test/java/domain/strategy/ElephantMoveStrategyTest.java @@ -52,4 +52,34 @@ class ElephantMoveStrategyTest { // then Assertions.assertFalse(strategy.canMove(from, to, board)); } + + @Test + @DisplayName("목적지에 같은 팀 기물이 있으면 이동하지 않는다.") + void 상_목적지에_같은_팀_기물이_있으면_이동_불가() { + // given + MoveStrategy strategy = new ElephantMoveStrategy(); + Board board = Board.of(); + + // when + Position from = Position.of(6, 1); + Position to = Position.of(3, 4); + + // then + Assertions.assertTrue(strategy.canMove(from, to, board)); + } + + @Test + @DisplayName("목적지에 다른 팀 기물이 있으면 이동한다.") + void 상_목적지에_다른_팀_기물이_있으면_이동_가능() { + // given + MoveStrategy strategy = new ElephantMoveStrategy(); + Board board = Board.of(); + + // when + Position from = Position.of(3, 4); + Position to = Position.of(6, 2); + + // then + Assertions.assertFalse(strategy.canMove(from, to, board)); + } } From cdf3d21597302e544d3ddbebe281260de15ec6e1 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Wed, 25 Mar 2026 20:21:25 +0900 Subject: [PATCH 16/87] =?UTF-8?q?feat:=20=EC=82=AC=20=EC=A0=84=EB=9E=B5=20?= =?UTF-8?q?=ED=8C=A8=ED=84=B4=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/GuardMoveStrategy.java | 5 ++ .../strategy/GuardMoveStrategyTest.java | 56 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 src/test/java/domain/strategy/GuardMoveStrategyTest.java diff --git a/src/main/java/domain/strategy/GuardMoveStrategy.java b/src/main/java/domain/strategy/GuardMoveStrategy.java index b724bb8284..d4b37baf4c 100644 --- a/src/main/java/domain/strategy/GuardMoveStrategy.java +++ b/src/main/java/domain/strategy/GuardMoveStrategy.java @@ -10,4 +10,9 @@ public class GuardMoveStrategy implements MoveStrategy{ public boolean canMove(Position from, Position to, Board board) { return false; } + + private boolean inRange(int row, int col) { + return ((0 <= row && row < 3) && (3 <= col && col < 6)) + || ((7 <= row && row <10) && (3 <= col && col < 6)); + } } diff --git a/src/test/java/domain/strategy/GuardMoveStrategyTest.java b/src/test/java/domain/strategy/GuardMoveStrategyTest.java new file mode 100644 index 0000000000..187b05c63a --- /dev/null +++ b/src/test/java/domain/strategy/GuardMoveStrategyTest.java @@ -0,0 +1,56 @@ +package domain.strategy; + +import domain.Board; +import domain.vo.Position; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class GuardMoveStrategyTest { + + @Test + @DisplayName("사의 목적지에 기물이 없으면 이동한다.") + void 사_정상_이동() { + // given + GuardMoveStrategy strategy = new GuardMoveStrategy(); + Board board = Board.of(); + + // when + Position position = Position.of(0, 3); + Position targetPosition = Position.of(1, 3); + + // then + Assertions.assertTrue(strategy.canMove(position, targetPosition, board)); + } + + @Test + @DisplayName("사의 목적지에 같은 팀 기물이 있으면 이동하지 않는다.") + void 사_목적지에_같은_팀_기물이_있으면_이동_불가() { + // given + GuardMoveStrategy strategy = new GuardMoveStrategy(); + Board board = Board.of(); + + // when + Position position = Position.of(0, 3); + Position targetPosition = Position.of(0, 2); + + // then + Assertions.assertFalse(strategy.canMove(position, targetPosition, board)); + } + + + @Test + @DisplayName("사의 목적지에 다른 팀 기물이 있으면 이동한다.") + void 사_목적지에_다른_팀_기물이_있으면_정상_이동() { + // given + GuardMoveStrategy strategy = new GuardMoveStrategy(); + Board board = Board.of(); + + // when + Position position = Position.of(0, 3); + Position targetPosition = Position.of(6, 0); + + // then + Assertions.assertTrue(strategy.canMove(position, targetPosition, board)); + } +} From 4aaaa4d10e5376dea9e231ea8adf0282d346fc0a Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Thu, 26 Mar 2026 11:36:15 +0900 Subject: [PATCH 17/87] =?UTF-8?q?refactor:=20=EC=B0=A8=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=EC=A0=84=EB=9E=B5=EC=9D=84=20dx,dy=20=ED=85=8C?= =?UTF-8?q?=ED=81=AC=EB=8B=89=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Board.java | 20 ++++-- .../domain/strategy/ChariotMoveStrategy.java | 71 +++++++++---------- .../domain/strategy/ElephantMoveStrategy.java | 23 +++--- src/test/java/domain/BoardTest.java | 2 +- .../strategy/ElephantMoveStrategyTest.java | 2 +- .../strategy/GuardMoveStrategyTest.java | 4 +- 6 files changed, 57 insertions(+), 65 deletions(-) diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index e030438de4..2eacab4396 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -5,6 +5,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.Optional; public class Board { @@ -52,7 +53,7 @@ public static Board of() { } public void straightMove(final Position from, final Position to) { - Piece fromPiece = findPieceByPosition(from); + Piece fromPiece = findPieceByPosition(from).get(); board.put(to, fromPiece); } @@ -60,12 +61,17 @@ public boolean isExistPosition(Position tempPosition) { return board.containsKey(tempPosition); } -// public void diagonalMove(final Position from, final Position to) { -// Piece fromPiece = findPieceByPosition(from); -// board.put(to, fromPiece); -// } + public Optional findPieceByPosition(final Position position) { + return Optional.ofNullable(board.get(position)); + } + + public boolean isAnotherTeam(Position from, Position to) { + if (findPieceByPosition(to).isEmpty()) { + return false; + } - public Piece findPieceByPosition(final Position position) { - return board.get(position); + Piece targetPiece = findPieceByPosition(to).get(); + Piece currentPiece = findPieceByPosition(from).get(); + return currentPiece.getTeam() == targetPiece.getTeam(); } } diff --git a/src/main/java/domain/strategy/ChariotMoveStrategy.java b/src/main/java/domain/strategy/ChariotMoveStrategy.java index d677017046..5575958d72 100644 --- a/src/main/java/domain/strategy/ChariotMoveStrategy.java +++ b/src/main/java/domain/strategy/ChariotMoveStrategy.java @@ -1,64 +1,57 @@ package domain.strategy; import domain.Board; -import domain.Piece; import domain.vo.Position; public class ChariotMoveStrategy implements MoveStrategy{ @Override public boolean canMove(Position from, Position to, Board board) { - int currentRow = from.getRow(); - int currentCol = from.getCol(); - int targetRow = to.getRow(); - int targetCol = to.getCol(); - - if (checkNotStraightPath(currentCol, targetCol, currentRow, targetRow)) + if (isNotStraightPath(from, to)) return false; - if (currentCol == targetCol) { - int min = Math.min(currentRow, targetRow) + 1; - int max = Math.max(currentRow, targetRow); - - if (checkClearPath(board, min, max, currentCol)) - return false; - - if (board.isExistPosition(Position.of(targetRow, targetCol))) { - return isOtherTeam(board, currentRow, currentCol, targetRow, targetCol); + int nx = 0, ny = 0; + if (from.getRow() == to.getRow()) { + if (from.getCol() < to.getCol()) { + ny = 1; + } + if (from.getCol() > to.getCol()) { + ny = -1; } } - if (targetRow == currentRow) { - int min = Math.min(currentCol, targetCol) + 1; - int max = Math.max(currentCol, targetCol); - - if (checkClearPath(board, min, max, currentCol)) - return false; - - if (board.isExistPosition(Position.of(targetRow, targetCol))) { - return isOtherTeam(board, currentRow, currentCol, targetRow, targetCol); + if (from.getCol() == to.getCol()) { + if (from.getRow() < to.getRow()) { + nx = 1; + } + if (from.getRow() > to.getRow()) { + nx = -1; } } - return true; - } + int row = from.getRow(); + int col = from.getCol(); + while (true) { + row += nx; + col += ny; - private boolean checkNotStraightPath(int currentCol, int targetCol, int currentRow, int targetRow) { - return currentCol != targetCol && currentRow != targetRow; - } + if (row == to.getRow() && col == to.getCol()) { + if (board.isAnotherTeam(from, to)) { + return false; + } - private boolean isOtherTeam(Board board, int currentRow, int currentCol, int targetRow, int targetCol) { - Piece currentPiece = board.findPieceByPosition(Position.of(currentRow, currentCol)); - Piece targetPiece = board.findPieceByPosition(Position.of(targetRow, targetCol)); - return currentPiece.getTeam() != targetPiece.getTeam(); - } - - private boolean checkClearPath(Board board, int min, int max, int currentCol) { - for (int temp = min; temp < max; temp++) { - if (board.isExistPosition(Position.of(temp, currentCol))) { return true; } + if (board.isExistPosition(Position.of(row, col))) { + return false; + } + } + } + + private boolean isNotStraightPath(Position from, Position to) { + if (from.getCol() != to.getCol() && from.getRow() != to.getRow()) { + return true; } return false; } diff --git a/src/main/java/domain/strategy/ElephantMoveStrategy.java b/src/main/java/domain/strategy/ElephantMoveStrategy.java index b6cb006540..b71906da0a 100644 --- a/src/main/java/domain/strategy/ElephantMoveStrategy.java +++ b/src/main/java/domain/strategy/ElephantMoveStrategy.java @@ -1,7 +1,6 @@ package domain.strategy; import domain.Board; -import domain.Piece; import domain.vo.Position; public class ElephantMoveStrategy implements MoveStrategy { @@ -25,7 +24,7 @@ public boolean canMove(Position from, Position to, Board board) { return false; } if (board.isExistPosition(Position.of(currentRow + 2, currentCol + 2))) { - return isOtherTeam(board, currentRow + 2, currentCol + 2, targetRow, targetCol); + return board.isAnotherTeam(Position.of(currentRow + 2, currentCol + 2), Position.of(targetRow, targetCol)); } return true; } @@ -34,7 +33,7 @@ public boolean canMove(Position from, Position to, Board board) { return false; } if (board.isExistPosition(Position.of(currentRow + 2, currentCol - 2))) { - return isOtherTeam(board, currentRow + 2, currentCol - 2, targetRow, targetCol); + return board.isAnotherTeam(Position.of(currentRow + 2, currentCol - 2), Position.of(targetRow, targetCol)); } return true; } @@ -50,7 +49,7 @@ public boolean canMove(Position from, Position to, Board board) { return false; } if (board.isExistPosition(Position.of(currentRow - 2, currentCol + 2))) { - return isOtherTeam(board, currentRow - 2, currentCol + 2, targetRow, targetCol); + return board.isAnotherTeam(Position.of(currentRow - 2, currentCol + 2), Position.of(targetRow, targetCol)); } return true; } @@ -59,7 +58,7 @@ public boolean canMove(Position from, Position to, Board board) { return false; } if (board.isExistPosition(Position.of(currentRow - 2, currentCol - 2))) { - return isOtherTeam(board, currentRow - 2, currentCol - 2, targetRow, targetCol); + return board.isAnotherTeam(Position.of(currentRow - 2, currentCol - 2), Position.of(targetRow, targetCol)); } return true; } @@ -78,7 +77,7 @@ public boolean canMove(Position from, Position to, Board board) { return false; } if (board.isExistPosition(Position.of(currentRow + 2, currentCol + 2))) { - return isOtherTeam(board, currentRow + 2, currentCol + 2, targetRow, targetCol); + return board.isAnotherTeam(Position.of(currentRow + 2, currentCol + 2), Position.of(targetRow, targetCol)); } return true; } @@ -87,7 +86,7 @@ public boolean canMove(Position from, Position to, Board board) { return false; } if (board.isExistPosition(Position.of(currentRow - 2, currentCol + 2))) { - return isOtherTeam(board, currentRow - 2, currentCol + 2, targetRow, targetCol); + return board.isAnotherTeam(Position.of(currentRow - 2, currentCol + 2), Position.of(targetRow, targetCol)); } return true; } @@ -104,7 +103,7 @@ public boolean canMove(Position from, Position to, Board board) { return false; } if (board.isExistPosition(Position.of(currentRow + 2, currentCol - 2))) { - return isOtherTeam(board, currentRow + 2, currentCol - 2, targetRow, targetCol); + return board.isAnotherTeam(Position.of(currentRow + 2, currentCol - 2), Position.of(targetRow, targetCol)); } return true; } @@ -113,7 +112,7 @@ public boolean canMove(Position from, Position to, Board board) { return false; } if (board.isExistPosition(Position.of(currentRow - 2, currentCol - 2))) { - return isOtherTeam(board, currentRow - 2, currentCol - 2, targetRow, targetCol); + return board.isAnotherTeam(Position.of(currentRow - 2, currentCol - 2), Position.of(targetRow, targetCol)); } return true; } @@ -122,10 +121,4 @@ public boolean canMove(Position from, Position to, Board board) { return true; } - - private boolean isOtherTeam(Board board, int currentRow, int currentCol, int targetRow, int targetCol) { - Piece currentPiece = board.findPieceByPosition(Position.of(currentRow, currentCol)); - Piece targetPiece = board.findPieceByPosition(Position.of(targetRow, targetCol)); - return currentPiece.getTeam() != targetPiece.getTeam(); - } } diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java index 6523cce427..d21e020496 100644 --- a/src/test/java/domain/BoardTest.java +++ b/src/test/java/domain/BoardTest.java @@ -30,7 +30,7 @@ class BoardTest { board.straightMove(from, to); // then - Piece findPiece = board.findPieceByPosition(to); + Piece findPiece = board.findPieceByPosition(to).get(); Assertions.assertEquals(Type.CHARIOT, findPiece.getType()); } diff --git a/src/test/java/domain/strategy/ElephantMoveStrategyTest.java b/src/test/java/domain/strategy/ElephantMoveStrategyTest.java index 89dead9347..bc42975dff 100644 --- a/src/test/java/domain/strategy/ElephantMoveStrategyTest.java +++ b/src/test/java/domain/strategy/ElephantMoveStrategyTest.java @@ -80,6 +80,6 @@ class ElephantMoveStrategyTest { Position to = Position.of(6, 2); // then - Assertions.assertFalse(strategy.canMove(from, to, board)); + Assertions.assertTrue(strategy.canMove(from, to, board)); } } diff --git a/src/test/java/domain/strategy/GuardMoveStrategyTest.java b/src/test/java/domain/strategy/GuardMoveStrategyTest.java index 187b05c63a..935965bf48 100644 --- a/src/test/java/domain/strategy/GuardMoveStrategyTest.java +++ b/src/test/java/domain/strategy/GuardMoveStrategyTest.java @@ -20,7 +20,7 @@ class GuardMoveStrategyTest { Position targetPosition = Position.of(1, 3); // then - Assertions.assertTrue(strategy.canMove(position, targetPosition, board)); + // Assertions.assertTrue(strategy.canMove(position, targetPosition, board)); } @Test @@ -51,6 +51,6 @@ class GuardMoveStrategyTest { Position targetPosition = Position.of(6, 0); // then - Assertions.assertTrue(strategy.canMove(position, targetPosition, board)); + // Assertions.assertTrue(strategy.canMove(position, targetPosition, board)); } } From 8ded06e3287378429366b2bc5331177adb466a60 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Thu, 26 Mar 2026 12:00:01 +0900 Subject: [PATCH 18/87] =?UTF-8?q?refactor:=20=EC=83=81=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EC=A0=84=EB=9E=B5=EC=97=90=20dx,dy=20=ED=85=8C?= =?UTF-8?q?=ED=81=AC=EB=8B=89=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/ElephantMoveStrategy.java | 164 +++++++----------- 1 file changed, 62 insertions(+), 102 deletions(-) diff --git a/src/main/java/domain/strategy/ElephantMoveStrategy.java b/src/main/java/domain/strategy/ElephantMoveStrategy.java index b71906da0a..53c97f1b94 100644 --- a/src/main/java/domain/strategy/ElephantMoveStrategy.java +++ b/src/main/java/domain/strategy/ElephantMoveStrategy.java @@ -7,118 +7,78 @@ public class ElephantMoveStrategy implements MoveStrategy { @Override public boolean canMove(Position from, Position to, Board board) { - int currentRow = from.getRow(); - int currentCol = from.getCol(); + // row차이 : 3 -3 2 -2 + // col차이 : 2 -2 2 -2 3 -3 3 -3 - int targetRow = to.getRow(); - int targetCol = to.getCol(); + if (isNotCorrectPath(from, to)) + return false; - if (Math.abs(currentRow - targetRow) == 3) { - if (targetRow > currentRow) { - currentRow += 1; - if (board.isExistPosition(Position.of(currentRow, currentCol))) { - return false; - } - if (currentCol < targetCol) { - if (board.isExistPosition(Position.of(currentRow + 1, currentCol + 1))) { - return false; - } - if (board.isExistPosition(Position.of(currentRow + 2, currentCol + 2))) { - return board.isAnotherTeam(Position.of(currentRow + 2, currentCol + 2), Position.of(targetRow, targetCol)); - } - return true; - } - if (currentCol > targetCol) { - if (board.isExistPosition(Position.of(currentRow + 1, currentCol - 1))) { - return false; - } - if (board.isExistPosition(Position.of(currentRow + 2, currentCol - 2))) { - return board.isAnotherTeam(Position.of(currentRow + 2, currentCol - 2), Position.of(targetRow, targetCol)); - } - return true; - } + int nx = 0, ny = 0; + if (from.getRow() - to.getRow() == 3) { // 아래 + if (from.getCol() - to.getCol() == 2) { // 왼쪽 + nx = -3; + ny = -2; } - - if (targetRow < currentRow) { - currentRow -= 1; - if (board.isExistPosition(Position.of(currentRow, currentCol))) { - return false; - } - if (currentCol < targetCol) { - if (board.isExistPosition(Position.of(currentRow - 1, currentCol + 1))) { - return false; - } - if (board.isExistPosition(Position.of(currentRow - 2, currentCol + 2))) { - return board.isAnotherTeam(Position.of(currentRow - 2, currentCol + 2), Position.of(targetRow, targetCol)); - } - return true; - } - if (currentCol > targetCol) { - if (board.isExistPosition(Position.of(currentRow - 1, currentCol - 1))) { - return false; - } - if (board.isExistPosition(Position.of(currentRow - 2, currentCol - 2))) { - return board.isAnotherTeam(Position.of(currentRow - 2, currentCol - 2), Position.of(targetRow, targetCol)); - } - return true; - } + if (from.getCol() - to.getCol() == -2) { // 오른쪽 + nx = -3; + ny = 2; + } + } + if (from.getRow() - to.getRow() == -3) { // 위 + if (from.getCol() - to.getCol() == 2) { // 왼쪽 + nx = 3; + ny = -2; + } + if (from.getCol() - to.getCol() == -2) { // 오른쪽 + nx = 3; + ny = 2; + } + } + if (from.getRow() - to.getRow() == 2) { + if (from.getCol() - to.getCol() == 3) { // 왼쪽 아래대각 아래대각 + nx = -2; + ny = -3; + } + if (from.getCol() - to.getCol() == -3) { // 오른쪽 아래대각 아래대각 + nx = -2; + ny = 3; + } + } + if (from.getRow() - to.getRow() == -2) { + if (from.getCol() - to.getCol() == 3) { // 왼쪽 위대각 위대각 + nx = 2; + ny = -3; + } + if (from.getCol() - to.getCol() == -3) { // 오른쪽 위대각 위대각 + nx = 2; + ny = 3; } } - if (Math.abs(currentRow - targetRow) == 2) { - if (targetCol > currentCol) { - currentCol += 1; - if (board.isExistPosition(Position.of(currentRow, currentCol))) { - return false; - } + int row = from.getRow(); + int col = from.getCol(); +// if (board.isExistPosition(직전)){ +// return false; +// } +// if (board.isExistPosition(첫번쨰 대각)) { +// return false; +// } - if (currentRow < targetRow) { - if (board.isExistPosition(Position.of(currentRow + 1, currentCol + 1))) { - return false; - } - if (board.isExistPosition(Position.of(currentRow + 2, currentCol + 2))) { - return board.isAnotherTeam(Position.of(currentRow + 2, currentCol + 2), Position.of(targetRow, targetCol)); - } - return true; - } - if (currentRow > targetRow) { - if (board.isExistPosition(Position.of(currentRow - 1, currentCol + 1))) { - return false; - } - if (board.isExistPosition(Position.of(currentRow - 2, currentCol + 2))) { - return board.isAnotherTeam(Position.of(currentRow - 2, currentCol + 2), Position.of(targetRow, targetCol)); - } - return true; - } - } - if (targetCol < currentCol) { - currentCol -= 1; - if (board.isExistPosition(Position.of(currentRow, currentCol))) { - return false; - } + return true; + } - if (currentRow < targetRow) { - if (board.isExistPosition(Position.of(currentRow + 1, currentCol - 1))) { - return false; - } - if (board.isExistPosition(Position.of(currentRow + 2, currentCol - 2))) { - return board.isAnotherTeam(Position.of(currentRow + 2, currentCol - 2), Position.of(targetRow, targetCol)); - } - return true; - } - if (currentRow > targetRow) { - if (board.isExistPosition(Position.of(currentRow - 1, currentCol - 1))) { - return false; - } - if (board.isExistPosition(Position.of(currentRow - 2, currentCol - 2))) { - return board.isAnotherTeam(Position.of(currentRow - 2, currentCol - 2), Position.of(targetRow, targetCol)); - } - return true; - } + private boolean isNotCorrectPath(Position from, Position to) { + if (Math.abs(from.getRow() - to.getRow()) == 2) { + if (Math.abs(from.getCol() - to.getCol()) != 3) { + return true; } } - - return true; + if (Math.abs(from.getRow() - to.getRow()) == 3) { + if (Math.abs(from.getCol() - to.getCol()) != 2) { + return true; + } + } + return false; } } From 6c2a3307476575152e5663a8de3074a09cf06b55 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Thu, 26 Mar 2026 13:48:47 +0900 Subject: [PATCH 19/87] =?UTF-8?q?refactor:=20=EC=83=81=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EC=A0=84=EB=9E=B5=EC=97=90=20dx,dy=20=ED=85=8C?= =?UTF-8?q?=ED=81=AC=EB=8B=89=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Board.java | 4 +- .../domain/strategy/ChariotMoveStrategy.java | 5 +- .../domain/strategy/ElephantMoveStrategy.java | 49 ++++++++++++------- .../strategy/ElephantMoveStrategyTest.java | 2 +- 4 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index 2eacab4396..bbd0c27d70 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -67,11 +67,11 @@ public Optional findPieceByPosition(final Position position) { public boolean isAnotherTeam(Position from, Position to) { if (findPieceByPosition(to).isEmpty()) { - return false; + return true; } Piece targetPiece = findPieceByPosition(to).get(); Piece currentPiece = findPieceByPosition(from).get(); - return currentPiece.getTeam() == targetPiece.getTeam(); + return currentPiece.getTeam() != targetPiece.getTeam(); } } diff --git a/src/main/java/domain/strategy/ChariotMoveStrategy.java b/src/main/java/domain/strategy/ChariotMoveStrategy.java index 5575958d72..f6f6983580 100644 --- a/src/main/java/domain/strategy/ChariotMoveStrategy.java +++ b/src/main/java/domain/strategy/ChariotMoveStrategy.java @@ -38,10 +38,9 @@ public boolean canMove(Position from, Position to, Board board) { if (row == to.getRow() && col == to.getCol()) { if (board.isAnotherTeam(from, to)) { - return false; + return true; } - - return true; + return false; } if (board.isExistPosition(Position.of(row, col))) { return false; diff --git a/src/main/java/domain/strategy/ElephantMoveStrategy.java b/src/main/java/domain/strategy/ElephantMoveStrategy.java index 53c97f1b94..6aba63dec3 100644 --- a/src/main/java/domain/strategy/ElephantMoveStrategy.java +++ b/src/main/java/domain/strategy/ElephantMoveStrategy.java @@ -7,49 +7,47 @@ public class ElephantMoveStrategy implements MoveStrategy { @Override public boolean canMove(Position from, Position to, Board board) { - // row차이 : 3 -3 2 -2 - // col차이 : 2 -2 2 -2 3 -3 3 -3 if (isNotCorrectPath(from, to)) return false; int nx = 0, ny = 0; - if (from.getRow() - to.getRow() == 3) { // 아래 - if (from.getCol() - to.getCol() == 2) { // 왼쪽 + if (from.getRow() - to.getRow() == 3) { + if (from.getCol() - to.getCol() == 2) { nx = -3; ny = -2; } - if (from.getCol() - to.getCol() == -2) { // 오른쪽 + if (from.getCol() - to.getCol() == -2) { nx = -3; ny = 2; } } - if (from.getRow() - to.getRow() == -3) { // 위 - if (from.getCol() - to.getCol() == 2) { // 왼쪽 + if (from.getRow() - to.getRow() == -3) { + if (from.getCol() - to.getCol() == 2) { nx = 3; ny = -2; } - if (from.getCol() - to.getCol() == -2) { // 오른쪽 + if (from.getCol() - to.getCol() == -2) { nx = 3; ny = 2; } } if (from.getRow() - to.getRow() == 2) { - if (from.getCol() - to.getCol() == 3) { // 왼쪽 아래대각 아래대각 + if (from.getCol() - to.getCol() == 3) { nx = -2; ny = -3; } - if (from.getCol() - to.getCol() == -3) { // 오른쪽 아래대각 아래대각 + if (from.getCol() - to.getCol() == -3) { nx = -2; ny = 3; } } if (from.getRow() - to.getRow() == -2) { - if (from.getCol() - to.getCol() == 3) { // 왼쪽 위대각 위대각 + if (from.getCol() - to.getCol() == 3) { nx = 2; ny = -3; } - if (from.getCol() - to.getCol() == -3) { // 오른쪽 위대각 위대각 + if (from.getCol() - to.getCol() == -3) { nx = 2; ny = 3; } @@ -57,15 +55,28 @@ public boolean canMove(Position from, Position to, Board board) { int row = from.getRow(); int col = from.getCol(); -// if (board.isExistPosition(직전)){ -// return false; -// } -// if (board.isExistPosition(첫번쨰 대각)) { -// return false; -// } + if (Math.abs(nx) == 3) { + if (board.isExistPosition(Position.of(row + nx / 3, col))) { + return false; + } + if (board.isExistPosition(Position.of(row + nx * 2 / 3, col + ny / 2))) { + return false; + } + } + if (Math.abs(nx) == 2) { + if (board.isExistPosition(Position.of(row, col + ny / 3))) { + return false; + } + if (board.isExistPosition(Position.of(row + nx / 2, col + ny * 2 / 3))) { + return false; + } + } - return true; + if (board.isAnotherTeam(from, to)) { + return true; + } + return false; } private boolean isNotCorrectPath(Position from, Position to) { diff --git a/src/test/java/domain/strategy/ElephantMoveStrategyTest.java b/src/test/java/domain/strategy/ElephantMoveStrategyTest.java index bc42975dff..7057a68366 100644 --- a/src/test/java/domain/strategy/ElephantMoveStrategyTest.java +++ b/src/test/java/domain/strategy/ElephantMoveStrategyTest.java @@ -65,7 +65,7 @@ class ElephantMoveStrategyTest { Position to = Position.of(3, 4); // then - Assertions.assertTrue(strategy.canMove(from, to, board)); + Assertions.assertFalse(strategy.canMove(from, to, board)); } @Test From d8238dfaa82aa3f90706920f749926bca16112ce Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Thu, 26 Mar 2026 14:29:16 +0900 Subject: [PATCH 20/87] =?UTF-8?q?feat:=20=EB=A7=88=EC=9D=98=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EA=B7=9C=EC=B9=99=20=EA=B5=AC=ED=98=84=20=EB=B0=8F?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/HorseMoveStrategy.java | 26 +++++++ .../strategy/HorseMoveStrategyTest.java | 71 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 src/test/java/domain/strategy/HorseMoveStrategyTest.java diff --git a/src/main/java/domain/strategy/HorseMoveStrategy.java b/src/main/java/domain/strategy/HorseMoveStrategy.java index eff5f2362a..1eb9f1600d 100644 --- a/src/main/java/domain/strategy/HorseMoveStrategy.java +++ b/src/main/java/domain/strategy/HorseMoveStrategy.java @@ -7,6 +7,32 @@ public class HorseMoveStrategy implements MoveStrategy { @Override public boolean canMove(Position from, Position to, Board board) { + if (isNotCorrectPath(from, to)) + return false; + + int nx = to.getRow() - from.getRow(); + int ny = to.getCol() - from.getCol(); + + if (board.isExistPosition(Position.of((from.getRow() + nx / 2), (from.getCol() + ny / 2)))) { + return false; + } + if (board.isAnotherTeam(from, to)) { + return true; + } + + return false; + } + + private boolean isNotCorrectPath(Position from, Position to) { + if (Math.abs(from.getRow() - to.getRow()) == 1) { + if (Math.abs(from.getCol() - to.getCol()) != 2) { + return true; + } + } + if (Math.abs(from.getRow() - to.getRow()) == 2) { + if (Math.abs(from.getCol() - to.getCol()) != 1) + return true; + } return false; } } diff --git a/src/test/java/domain/strategy/HorseMoveStrategyTest.java b/src/test/java/domain/strategy/HorseMoveStrategyTest.java new file mode 100644 index 0000000000..a9b2edaa81 --- /dev/null +++ b/src/test/java/domain/strategy/HorseMoveStrategyTest.java @@ -0,0 +1,71 @@ +package domain.strategy; + +import domain.Board; +import domain.vo.Position; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + + +class HorseMoveStrategyTest { + + @Test + @DisplayName("초나라 마의 이동 경로에 다른 기물이 없으면 정마 이동한다.") + void 초나라_마_정마_이동() { + // given + MoveStrategy strategy = new HorseMoveStrategy(); + Board board = Board.of(); + + // when + Position from = Position.of(0, 2); + Position to = Position.of(2, 3); + + // then + Assertions.assertTrue(strategy.canMove(from, to, board)); + } + + @Test + @DisplayName("한나라 마의 이동 경로에 다른 기물이 없으면 정마 이동한다.") + void 한나라_마_정마_이동() { + // given + MoveStrategy strategy = new HorseMoveStrategy(); + Board board = Board.of(); + + // when + Position from = Position.of(9, 2); + Position to = Position.of(7, 3); + + // then + Assertions.assertTrue(strategy.canMove(from, to, board)); + } + + @Test + @DisplayName("초나라 마의 이동 경로에 기물이 있으면 이동하지 않는다.") + void 초나라_마_이동_경로에_기물이_있으면_이동_불가() { + // given + MoveStrategy strategy = new ElephantMoveStrategy(); + Board board = Board.of(); + + // when + Position from = Position.of(0, 2); + Position to = Position.of(1, 4); + + // then + Assertions.assertFalse(strategy.canMove(from, to, board)); + } + + @Test + @DisplayName("목적지에 같은 팀 기물이 있으면 이동하지 않는다.") + void 마_목적지에_같은_팀_기물이_있으면_이동_불가() { + // given + MoveStrategy strategy = new HorseMoveStrategy(); + Board board = Board.of(); + + // when + Position from = Position.of(0, 2); + Position to = Position.of(2, 1); + + // then + Assertions.assertFalse(strategy.canMove(from, to, board)); + } +} From 2d5b6f6bbab2548118fd2bb36d5bf7523fae7104 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Thu, 26 Mar 2026 14:35:51 +0900 Subject: [PATCH 21/87] =?UTF-8?q?feat:=20=EC=82=AC=EC=9D=98=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EA=B7=9C=EC=B9=99=20=EA=B5=AC=ED=98=84=20=EB=B0=8F?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/GuardMoveStrategy.java | 20 +++++++++++++------ .../strategy/GuardMoveStrategyTest.java | 10 +++++----- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/main/java/domain/strategy/GuardMoveStrategy.java b/src/main/java/domain/strategy/GuardMoveStrategy.java index d4b37baf4c..b72e36189c 100644 --- a/src/main/java/domain/strategy/GuardMoveStrategy.java +++ b/src/main/java/domain/strategy/GuardMoveStrategy.java @@ -5,14 +5,22 @@ public class GuardMoveStrategy implements MoveStrategy{ - @Override public boolean canMove(Position from, Position to, Board board) { - return false; - } + if (from.getRow() == to.getRow()) { + if (Math.abs(from.getCol() - to.getCol()) != 1) { + return false; + } + } + if (from.getCol() == to.getCol()) { + if (Math.abs(from.getRow() - to.getRow()) != 1) { + return false; + } + } - private boolean inRange(int row, int col) { - return ((0 <= row && row < 3) && (3 <= col && col < 6)) - || ((7 <= row && row <10) && (3 <= col && col < 6)); + if (board.isAnotherTeam(from, to)) { + return true; + } + return false; } } diff --git a/src/test/java/domain/strategy/GuardMoveStrategyTest.java b/src/test/java/domain/strategy/GuardMoveStrategyTest.java index 935965bf48..303869bf69 100644 --- a/src/test/java/domain/strategy/GuardMoveStrategyTest.java +++ b/src/test/java/domain/strategy/GuardMoveStrategyTest.java @@ -12,7 +12,7 @@ class GuardMoveStrategyTest { @DisplayName("사의 목적지에 기물이 없으면 이동한다.") void 사_정상_이동() { // given - GuardMoveStrategy strategy = new GuardMoveStrategy(); + MoveStrategy strategy = new GuardMoveStrategy(); Board board = Board.of(); // when @@ -20,14 +20,14 @@ class GuardMoveStrategyTest { Position targetPosition = Position.of(1, 3); // then - // Assertions.assertTrue(strategy.canMove(position, targetPosition, board)); + Assertions.assertTrue(strategy.canMove(position, targetPosition, board)); } @Test @DisplayName("사의 목적지에 같은 팀 기물이 있으면 이동하지 않는다.") void 사_목적지에_같은_팀_기물이_있으면_이동_불가() { // given - GuardMoveStrategy strategy = new GuardMoveStrategy(); + MoveStrategy strategy = new GuardMoveStrategy(); Board board = Board.of(); // when @@ -43,7 +43,7 @@ class GuardMoveStrategyTest { @DisplayName("사의 목적지에 다른 팀 기물이 있으면 이동한다.") void 사_목적지에_다른_팀_기물이_있으면_정상_이동() { // given - GuardMoveStrategy strategy = new GuardMoveStrategy(); + MoveStrategy strategy = new GuardMoveStrategy(); Board board = Board.of(); // when @@ -51,6 +51,6 @@ class GuardMoveStrategyTest { Position targetPosition = Position.of(6, 0); // then - // Assertions.assertTrue(strategy.canMove(position, targetPosition, board)); + Assertions.assertTrue(strategy.canMove(position, targetPosition, board)); } } From eaa6f0002b1c23ccf27bd47e9247c4cc90529b4a Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Thu, 26 Mar 2026 15:19:00 +0900 Subject: [PATCH 22/87] =?UTF-8?q?refactor:=20BoardFactory=EC=97=90=20Board?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EC=B1=85=EC=9E=84=20=EC=9C=84=EC=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Board.java | 42 +-------- src/main/java/domain/BoardFactory.java | 56 ++++++++++++ .../domain/strategy/CannonMoveStrategy.java | 2 + src/test/java/domain/BoardTest.java | 6 +- .../strategy/CannonMoveStrategyTest.java | 86 +++++++++++++++++++ .../strategy/ChariotMoveStrategyTest.java | 7 +- .../strategy/ElephantMoveStrategyTest.java | 11 +-- .../strategy/GuardMoveStrategyTest.java | 7 +- .../strategy/HorseMoveStrategyTest.java | 9 +- 9 files changed, 170 insertions(+), 56 deletions(-) create mode 100644 src/main/java/domain/BoardFactory.java create mode 100644 src/test/java/domain/strategy/CannonMoveStrategyTest.java diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index bbd0c27d70..b3d34c04f6 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -3,7 +3,6 @@ import domain.strategy.*; import domain.vo.Position; -import java.util.HashMap; import java.util.Map; import java.util.Optional; @@ -11,45 +10,12 @@ public class Board { private final Map board; - private Board() { - board = new HashMap<>(); - board.put(Position.of(0, 0),Piece.of(Team.CHU, Type.CHARIOT, new ChariotMoveStrategy())); - board.put(Position.of(0, 1),Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(0, 2),Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); - board.put(Position.of(0, 3),Piece.of(Team.CHU, Type.GUARD, new GuardMoveStrategy())); - board.put(Position.of(0, 5),Piece.of(Team.CHU, Type.GUARD, new GuardMoveStrategy())); - board.put(Position.of(0, 6),Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(0, 7),Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); - board.put(Position.of(0, 8),Piece.of(Team.CHU, Type.CHARIOT, new ChariotMoveStrategy())); - board.put(Position.of(1, 4),Piece.of(Team.CHU, Type.GENERAL, new GeneralMoveStrategy())); - board.put(Position.of(2, 1),Piece.of(Team.CHU, Type.CANNON, new CannonMoveStrategy())); - board.put(Position.of(2, 8),Piece.of(Team.CHU, Type.CANNON, new CannonMoveStrategy())); - board.put(Position.of(3, 0),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); - board.put(Position.of(3, 2),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); - board.put(Position.of(3, 4),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); - board.put(Position.of(3, 6),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); - board.put(Position.of(3, 8),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); - - board.put(Position.of(9, 0),Piece.of(Team.HAN, Type.CHARIOT, new ChariotMoveStrategy())); - board.put(Position.of(9, 1),Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(9, 2),Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); - board.put(Position.of(9, 3),Piece.of(Team.HAN, Type.GUARD, new GuardMoveStrategy())); - board.put(Position.of(9, 5),Piece.of(Team.HAN, Type.GUARD, new GuardMoveStrategy())); - board.put(Position.of(9, 6),Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(9, 7),Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); - board.put(Position.of(9, 8),Piece.of(Team.HAN, Type.CHARIOT, new ChariotMoveStrategy())); - board.put(Position.of(8, 4),Piece.of(Team.HAN, Type.GENERAL, new GeneralMoveStrategy())); - board.put(Position.of(7, 1),Piece.of(Team.HAN, Type.CANNON, new CannonMoveStrategy())); - board.put(Position.of(7, 8),Piece.of(Team.HAN, Type.CANNON, new CannonMoveStrategy())); - board.put(Position.of(6, 0),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); - board.put(Position.of(6, 2),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); - board.put(Position.of(6, 4),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); - board.put(Position.of(6, 6),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); - board.put(Position.of(6, 8),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); + private Board(Map board) { + this.board = board; } - public static Board of() { - return new Board(); + public static Board of(Map board) { + return new Board(board); } public void straightMove(final Position from, final Position to) { diff --git a/src/main/java/domain/BoardFactory.java b/src/main/java/domain/BoardFactory.java new file mode 100644 index 0000000000..5be56eb0fd --- /dev/null +++ b/src/main/java/domain/BoardFactory.java @@ -0,0 +1,56 @@ +package domain; + +import domain.strategy.*; +import domain.vo.Position; + +import java.util.HashMap; +import java.util.Map; + +public class BoardFactory { + + private BoardFactory() {} + + public static Board of(Map board) { + return Board.of(board); + } + + public static Board setUp() { + Map board = new HashMap<>(); + + board.put(Position.of(0, 0),Piece.of(Team.CHU, Type.CHARIOT, new ChariotMoveStrategy())); + board.put(Position.of(0, 1),Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(0, 2),Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(0, 3),Piece.of(Team.CHU, Type.GUARD, new GuardMoveStrategy())); + board.put(Position.of(0, 5),Piece.of(Team.CHU, Type.GUARD, new GuardMoveStrategy())); + board.put(Position.of(0, 6),Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(0, 7),Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(0, 8),Piece.of(Team.CHU, Type.CHARIOT, new ChariotMoveStrategy())); + board.put(Position.of(1, 4),Piece.of(Team.CHU, Type.GENERAL, new GeneralMoveStrategy())); + board.put(Position.of(2, 1),Piece.of(Team.CHU, Type.CANNON, new CannonMoveStrategy())); + board.put(Position.of(2, 8),Piece.of(Team.CHU, Type.CANNON, new CannonMoveStrategy())); + board.put(Position.of(3, 0),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(3, 2),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(3, 4),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(3, 6),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(3, 8),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); + + board.put(Position.of(9, 0),Piece.of(Team.HAN, Type.CHARIOT, new ChariotMoveStrategy())); + board.put(Position.of(9, 1),Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(9, 2),Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(9, 3),Piece.of(Team.HAN, Type.GUARD, new GuardMoveStrategy())); + board.put(Position.of(9, 5),Piece.of(Team.HAN, Type.GUARD, new GuardMoveStrategy())); + board.put(Position.of(9, 6),Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(9, 7),Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(9, 8),Piece.of(Team.HAN, Type.CHARIOT, new ChariotMoveStrategy())); + board.put(Position.of(8, 4),Piece.of(Team.HAN, Type.GENERAL, new GeneralMoveStrategy())); + board.put(Position.of(7, 1),Piece.of(Team.HAN, Type.CANNON, new CannonMoveStrategy())); + board.put(Position.of(7, 8),Piece.of(Team.HAN, Type.CANNON, new CannonMoveStrategy())); + board.put(Position.of(6, 0),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(6, 2),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(6, 4),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(6, 6),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(6, 8),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); + + return Board.of(board); + } +} diff --git a/src/main/java/domain/strategy/CannonMoveStrategy.java b/src/main/java/domain/strategy/CannonMoveStrategy.java index cbb227e5d0..ae71b4461a 100644 --- a/src/main/java/domain/strategy/CannonMoveStrategy.java +++ b/src/main/java/domain/strategy/CannonMoveStrategy.java @@ -7,6 +7,8 @@ public class CannonMoveStrategy implements MoveStrategy { @Override public boolean canMove(Position from, Position to, Board board) { + + return false; } } diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java index d21e020496..908e4672d3 100644 --- a/src/test/java/domain/BoardTest.java +++ b/src/test/java/domain/BoardTest.java @@ -15,14 +15,14 @@ class BoardTest { // given // when // then - assertDoesNotThrow(Board::of); + assertDoesNotThrow(() -> BoardFactory.setUp()); } @Test @DisplayName("기물의 직선 이동 경로에 다른 기물이 없으면 이동한다.") void 기물_직선_이동() { // given - Board board = Board.of(); + Board board = BoardFactory.setUp(); // when Position from = Position.of(0, 0); @@ -38,7 +38,7 @@ class BoardTest { @DisplayName("기물의 대각선 이동 경로에 다른 기물이 없으면 이동한다.") void 기물_대각선_이동() { // given - Board board = Board.of(); + Board board = BoardFactory.setUp(); Position to = Position.of(3, 3); // when diff --git a/src/test/java/domain/strategy/CannonMoveStrategyTest.java b/src/test/java/domain/strategy/CannonMoveStrategyTest.java new file mode 100644 index 0000000000..381ad933e9 --- /dev/null +++ b/src/test/java/domain/strategy/CannonMoveStrategyTest.java @@ -0,0 +1,86 @@ +package domain.strategy; + +import domain.Board; +import domain.BoardFactory; +import domain.vo.Position; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class CannonMoveStrategyTest { + + @Test + @DisplayName("초나라 포의 이동 경로에 다른 기물이 없으면 정상 이동한다.") + void 초나라_포_정상_이동() { + // given + MoveStrategy strategy = new CannonMoveStrategy(); + Board board = BoardFactory.setUp(); + + // when + Position from = Position.of(2, 1); + Position to = Position.of(3, 3); + + // then + Assertions.assertTrue(strategy.canMove(from, to, board)); + } + + @Test + @DisplayName("한나라 포의 이동 경로에 다른 기물이 없으면 정상 이동한다.") + void 한나라_포_정상_이동() { + // given + MoveStrategy strategy = new ElephantMoveStrategy(); + Board board = BoardFactory.setUp(); + + // when + Position from = Position.of(9, 1); + Position to = Position.of(6, 3); + + // then + Assertions.assertTrue(strategy.canMove(from, to, board)); + } + + @Test + @DisplayName("초나라 포의 이동 경로에 기물이 있으면 이동하지 않는다.") + void 초나라_포_이동_경로에_기물이_있으면_이동_불가() { + // given + MoveStrategy strategy = new ElephantMoveStrategy(); + Board board = BoardFactory.setUp(); + + // when + Position from = Position.of(0, 1); + Position to = Position.of(2, 4); + + // then + Assertions.assertFalse(strategy.canMove(from, to, board)); + } + + @Test + @DisplayName("목적지에 같은 팀 기물이 있으면 이동하지 않는다.") + void 포_목적지에_같은_팀_기물이_있으면_이동_불가() { + // given + MoveStrategy strategy = new ElephantMoveStrategy(); + Board board = BoardFactory.setUp(); + + // when + Position from = Position.of(6, 1); + Position to = Position.of(3, 4); + + // then + Assertions.assertFalse(strategy.canMove(from, to, board)); + } + + @Test + @DisplayName("목적지에 다른 팀 기물이 있으면 이동한다.") + void 포_목적지에_다른_팀_기물이_있으면_이동_가능() { + // given + MoveStrategy strategy = new ElephantMoveStrategy(); + Board board = BoardFactory.setUp(); + + // when + Position from = Position.of(3, 4); + Position to = Position.of(6, 2); + + // then + Assertions.assertTrue(strategy.canMove(from, to, board)); + } +} diff --git a/src/test/java/domain/strategy/ChariotMoveStrategyTest.java b/src/test/java/domain/strategy/ChariotMoveStrategyTest.java index 53c6691f10..ce1f69eff7 100644 --- a/src/test/java/domain/strategy/ChariotMoveStrategyTest.java +++ b/src/test/java/domain/strategy/ChariotMoveStrategyTest.java @@ -1,6 +1,7 @@ package domain.strategy; import domain.Board; +import domain.BoardFactory; import domain.vo.Position; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; @@ -13,7 +14,7 @@ class ChariotMoveStrategyTest { void 차_직선_이동() { // given ChariotMoveStrategy strategy = new ChariotMoveStrategy(); - Board board = Board.of(); + Board board = BoardFactory.setUp(); // when Position from = Position.of(0, 0); @@ -28,7 +29,7 @@ class ChariotMoveStrategyTest { void 차_목적지에_같은_팀_기물이_있으면_이동_불가() { // given ChariotMoveStrategy strategy = new ChariotMoveStrategy(); - Board board = Board.of(); + Board board = BoardFactory.setUp(); // when Position from = Position.of(0, 0); @@ -43,7 +44,7 @@ class ChariotMoveStrategyTest { void 차_목적지에_다른_팀_기물이_있으면_이동_가능() { // given ChariotMoveStrategy strategy = new ChariotMoveStrategy(); - Board board = Board.of(); + Board board = BoardFactory.setUp(); // when Position from = Position.of(3, 0); diff --git a/src/test/java/domain/strategy/ElephantMoveStrategyTest.java b/src/test/java/domain/strategy/ElephantMoveStrategyTest.java index 7057a68366..5f0c51d0d7 100644 --- a/src/test/java/domain/strategy/ElephantMoveStrategyTest.java +++ b/src/test/java/domain/strategy/ElephantMoveStrategyTest.java @@ -1,6 +1,7 @@ package domain.strategy; import domain.Board; +import domain.BoardFactory; import domain.vo.Position; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; @@ -13,7 +14,7 @@ class ElephantMoveStrategyTest { void 초나라_상_정상_이동() { // given MoveStrategy strategy = new ElephantMoveStrategy(); - Board board = Board.of(); + Board board = BoardFactory.setUp(); // when Position from = Position.of(0, 1); @@ -28,7 +29,7 @@ class ElephantMoveStrategyTest { void 한나라_상_정상_이동() { // given MoveStrategy strategy = new ElephantMoveStrategy(); - Board board = Board.of(); + Board board = BoardFactory.setUp(); // when Position from = Position.of(9, 1); @@ -43,7 +44,7 @@ class ElephantMoveStrategyTest { void 초나라_상_이동_경로에_기물이_있으면_이동_불가() { // given MoveStrategy strategy = new ElephantMoveStrategy(); - Board board = Board.of(); + Board board = BoardFactory.setUp(); // when Position from = Position.of(0, 1); @@ -58,7 +59,7 @@ class ElephantMoveStrategyTest { void 상_목적지에_같은_팀_기물이_있으면_이동_불가() { // given MoveStrategy strategy = new ElephantMoveStrategy(); - Board board = Board.of(); + Board board = BoardFactory.setUp(); // when Position from = Position.of(6, 1); @@ -73,7 +74,7 @@ class ElephantMoveStrategyTest { void 상_목적지에_다른_팀_기물이_있으면_이동_가능() { // given MoveStrategy strategy = new ElephantMoveStrategy(); - Board board = Board.of(); + Board board = BoardFactory.setUp(); // when Position from = Position.of(3, 4); diff --git a/src/test/java/domain/strategy/GuardMoveStrategyTest.java b/src/test/java/domain/strategy/GuardMoveStrategyTest.java index 303869bf69..2266400f68 100644 --- a/src/test/java/domain/strategy/GuardMoveStrategyTest.java +++ b/src/test/java/domain/strategy/GuardMoveStrategyTest.java @@ -1,6 +1,7 @@ package domain.strategy; import domain.Board; +import domain.BoardFactory; import domain.vo.Position; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; @@ -13,7 +14,7 @@ class GuardMoveStrategyTest { void 사_정상_이동() { // given MoveStrategy strategy = new GuardMoveStrategy(); - Board board = Board.of(); + Board board = BoardFactory.setUp(); // when Position position = Position.of(0, 3); @@ -28,7 +29,7 @@ class GuardMoveStrategyTest { void 사_목적지에_같은_팀_기물이_있으면_이동_불가() { // given MoveStrategy strategy = new GuardMoveStrategy(); - Board board = Board.of(); + Board board = BoardFactory.setUp(); // when Position position = Position.of(0, 3); @@ -44,7 +45,7 @@ class GuardMoveStrategyTest { void 사_목적지에_다른_팀_기물이_있으면_정상_이동() { // given MoveStrategy strategy = new GuardMoveStrategy(); - Board board = Board.of(); + Board board = BoardFactory.setUp(); // when Position position = Position.of(0, 3); diff --git a/src/test/java/domain/strategy/HorseMoveStrategyTest.java b/src/test/java/domain/strategy/HorseMoveStrategyTest.java index a9b2edaa81..b4713f2562 100644 --- a/src/test/java/domain/strategy/HorseMoveStrategyTest.java +++ b/src/test/java/domain/strategy/HorseMoveStrategyTest.java @@ -1,6 +1,7 @@ package domain.strategy; import domain.Board; +import domain.BoardFactory; import domain.vo.Position; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; @@ -14,7 +15,7 @@ class HorseMoveStrategyTest { void 초나라_마_정마_이동() { // given MoveStrategy strategy = new HorseMoveStrategy(); - Board board = Board.of(); + Board board = BoardFactory.setUp(); // when Position from = Position.of(0, 2); @@ -29,7 +30,7 @@ class HorseMoveStrategyTest { void 한나라_마_정마_이동() { // given MoveStrategy strategy = new HorseMoveStrategy(); - Board board = Board.of(); + Board board = BoardFactory.setUp(); // when Position from = Position.of(9, 2); @@ -44,7 +45,7 @@ class HorseMoveStrategyTest { void 초나라_마_이동_경로에_기물이_있으면_이동_불가() { // given MoveStrategy strategy = new ElephantMoveStrategy(); - Board board = Board.of(); + Board board = BoardFactory.setUp(); // when Position from = Position.of(0, 2); @@ -59,7 +60,7 @@ class HorseMoveStrategyTest { void 마_목적지에_같은_팀_기물이_있으면_이동_불가() { // given MoveStrategy strategy = new HorseMoveStrategy(); - Board board = Board.of(); + Board board = BoardFactory.setUp(); // when Position from = Position.of(0, 2); From 4b6478f224c21d3fbd382a06270ebc0ef38ccdb2 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Thu, 26 Mar 2026 15:58:28 +0900 Subject: [PATCH 23/87] =?UTF-8?q?feat:=20=ED=8F=AC=EC=9D=98=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EC=A0=84=EB=9E=B5=20=EA=B5=AC=ED=98=84=20=EB=B0=8F?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/CannonMoveStrategy.java | 56 +++++++++ .../strategy/CannonMoveStrategyTest.java | 116 ++++++++++++++---- 2 files changed, 146 insertions(+), 26 deletions(-) diff --git a/src/main/java/domain/strategy/CannonMoveStrategy.java b/src/main/java/domain/strategy/CannonMoveStrategy.java index ae71b4461a..420541bb1f 100644 --- a/src/main/java/domain/strategy/CannonMoveStrategy.java +++ b/src/main/java/domain/strategy/CannonMoveStrategy.java @@ -1,14 +1,70 @@ package domain.strategy; import domain.Board; +import domain.Type; import domain.vo.Position; public class CannonMoveStrategy implements MoveStrategy { @Override public boolean canMove(Position from, Position to, Board board) { + if (isNotCorrectPath(from, to)) + return false; + int nx = 0, ny = 0; + if (from.getRow() < to.getRow()) { + nx = 1; + } + if (from.getRow() > to.getRow()) { + nx = -1; + } + if (from.getCol() < to.getCol()) { + ny = 1; + } + if (from.getCol() > to.getCol()) { + ny = -1; + } + int pieceCount = 0; + int row = from.getRow(); + int col = from.getCol(); + while (true) { + row += nx; + col += ny; + + if (row == to.getRow() && col == to.getCol()) { + if (!isCannon(board, to.getRow(), to.getCol()) + && board.isAnotherTeam(from, to) + && pieceCount == 1) { + return true; + } + + return false; + } + + if (board.isExistPosition(Position.of(row, col))) { + if (isCannon(board, row, col)) { + return false; + } + + pieceCount += 1; + } + + if (pieceCount > 1) { + return false; + } + } + } + + private boolean isCannon(Board board, int row, int col) { + if (board.findPieceByPosition(Position.of(row, col)).isEmpty()) return false; + return board.findPieceByPosition(Position.of(row, col)).get().getType() == Type.CANNON; + } + + private boolean isNotCorrectPath(Position from, Position to) { + if (from.getRow() != to.getRow() && from.getCol() != to.getCol()) { + return true; + } return false; } } diff --git a/src/test/java/domain/strategy/CannonMoveStrategyTest.java b/src/test/java/domain/strategy/CannonMoveStrategyTest.java index 381ad933e9..e0c5781eed 100644 --- a/src/test/java/domain/strategy/CannonMoveStrategyTest.java +++ b/src/test/java/domain/strategy/CannonMoveStrategyTest.java @@ -1,54 +1,68 @@ package domain.strategy; -import domain.Board; -import domain.BoardFactory; +import domain.*; import domain.vo.Position; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.HashMap; +import java.util.Map; + class CannonMoveStrategyTest { @Test - @DisplayName("초나라 포의 이동 경로에 다른 기물이 없으면 정상 이동한다.") + @DisplayName("초나라 포의 이동 경로에 포를 제외한 기물이 1개 있으면 정상 이동한다.") void 초나라_포_정상_이동() { // given MoveStrategy strategy = new CannonMoveStrategy(); - Board board = BoardFactory.setUp(); + Map boardMapper = new HashMap<>(); + boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); + + Board board = BoardFactory.of(boardMapper); // when Position from = Position.of(2, 1); - Position to = Position.of(3, 3); + Position to = Position.of(4, 1); // then Assertions.assertTrue(strategy.canMove(from, to, board)); } @Test - @DisplayName("한나라 포의 이동 경로에 다른 기물이 없으면 정상 이동한다.") - void 한나라_포_정상_이동() { + @DisplayName("한나라 포의 이동 경로에 다른 기물이 없으면 이동하지 못한다.") + void 포의_이동_경로에_다른_기물이_없으면_이동하지_못한다() { // given - MoveStrategy strategy = new ElephantMoveStrategy(); - Board board = BoardFactory.setUp(); + MoveStrategy strategy = new CannonMoveStrategy(); + Map boardMapper = new HashMap<>(); + boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); + + Board board = BoardFactory.of(boardMapper); // when - Position from = Position.of(9, 1); - Position to = Position.of(6, 3); + Position from = Position.of(2, 1); + Position to = Position.of(5, 1); // then - Assertions.assertTrue(strategy.canMove(from, to, board)); + Assertions.assertFalse(strategy.canMove(from, to, board)); } @Test - @DisplayName("초나라 포의 이동 경로에 기물이 있으면 이동하지 않는다.") - void 초나라_포_이동_경로에_기물이_있으면_이동_불가() { + @DisplayName("초나라 포의 이동 경로에 기물이 둘 이상 있으면 이동하지 않는다.") + void 초나라_포_이동_경로에_기물이_둘_이상_있으면_이동_불가() { // given - MoveStrategy strategy = new ElephantMoveStrategy(); - Board board = BoardFactory.setUp(); + MoveStrategy strategy = new CannonMoveStrategy(); + Map boardMapper = new HashMap<>(); + boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); + boardMapper.put(Position.of(4, 1), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); + + Board board = BoardFactory.of(boardMapper); // when - Position from = Position.of(0, 1); - Position to = Position.of(2, 4); + Position from = Position.of(2, 1); + Position to = Position.of(5, 1); // then Assertions.assertFalse(strategy.canMove(from, to, board)); @@ -58,12 +72,37 @@ class CannonMoveStrategyTest { @DisplayName("목적지에 같은 팀 기물이 있으면 이동하지 않는다.") void 포_목적지에_같은_팀_기물이_있으면_이동_불가() { // given - MoveStrategy strategy = new ElephantMoveStrategy(); - Board board = BoardFactory.setUp(); + MoveStrategy strategy = new CannonMoveStrategy(); + Map boardMapper = new HashMap<>(); + boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); + boardMapper.put(Position.of(5, 1), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); + + Board board = BoardFactory.of(boardMapper); + + // when + Position from = Position.of(2, 1); + Position to = Position.of(5, 1); + + // then + Assertions.assertFalse(strategy.canMove(from, to, board)); + } + + @Test + @DisplayName("목적지에 포가 있으면 이동하지 않는다.") + void 목적지에_포가_있으면_이동하지_않는다() { + // given + MoveStrategy strategy = new CannonMoveStrategy(); + Map boardMapper = new HashMap<>(); + boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); + boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.CANNON, strategy)); + + Board board = BoardFactory.of(boardMapper); // when - Position from = Position.of(6, 1); - Position to = Position.of(3, 4); + Position from = Position.of(2, 1); + Position to = Position.of(5, 1); // then Assertions.assertFalse(strategy.canMove(from, to, board)); @@ -73,14 +112,39 @@ class CannonMoveStrategyTest { @DisplayName("목적지에 다른 팀 기물이 있으면 이동한다.") void 포_목적지에_다른_팀_기물이_있으면_이동_가능() { // given - MoveStrategy strategy = new ElephantMoveStrategy(); - Board board = BoardFactory.setUp(); + MoveStrategy strategy = new CannonMoveStrategy(); + Map boardMapper = new HashMap<>(); + boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); + boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.SOLIDER, new FixedMoveStrategy())); + + Board board = BoardFactory.of(boardMapper); // when - Position from = Position.of(3, 4); - Position to = Position.of(6, 2); + Position from = Position.of(2, 1); + Position to = Position.of(5, 1); // then Assertions.assertTrue(strategy.canMove(from, to, board)); } + + @Test + @DisplayName("포의 이동 경로에 포가 존재하면 이동하지 못한다.") + void 포의_이동_경로에_포가_있으면_이동_불가() { + // given + MoveStrategy strategy = new CannonMoveStrategy(); + Map boardMapper = new HashMap<>(); + boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); + boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.SOLIDER, new FixedMoveStrategy())); + + Board board = BoardFactory.of(boardMapper); + + // when + Position from = Position.of(2, 1); + Position to = Position.of(5, 1); + + // then + Assertions.assertFalse(strategy.canMove(from, to, board)); + } } From f4eeb5bae46510e7f6a0177f9d9918757285cc0d Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Thu, 26 Mar 2026 16:24:18 +0900 Subject: [PATCH 24/87] =?UTF-8?q?feat:=20=EA=B6=81=EC=9D=98=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EC=A0=84=EB=9E=B5=20=EA=B5=AC=ED=98=84=20=EB=B0=8F?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/GeneralMoveStrategy.java | 20 ++++++ .../strategy/GeneralMoveStrategyTest.java | 70 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 src/test/java/domain/strategy/GeneralMoveStrategyTest.java diff --git a/src/main/java/domain/strategy/GeneralMoveStrategy.java b/src/main/java/domain/strategy/GeneralMoveStrategy.java index 59912a2ade..0c2b2b9f40 100644 --- a/src/main/java/domain/strategy/GeneralMoveStrategy.java +++ b/src/main/java/domain/strategy/GeneralMoveStrategy.java @@ -7,6 +7,26 @@ public class GeneralMoveStrategy implements MoveStrategy { @Override public boolean canMove(Position from, Position to, Board board) { + if (isNotCorrectPath(from, to)) + return false; + + if (board.isAnotherTeam(from, to)) { + return true; + } + return false; + } + + private boolean isNotCorrectPath(Position from, Position to) { + if (from.getRow() == to.getRow()) { + if (Math.abs(from.getCol() - to.getCol()) != 1) { + return true; + } + } + if (from.getCol() == to.getCol()) { + if (Math.abs(from.getRow() - to.getRow()) != 1) { + return true; + } + } return false; } } diff --git a/src/test/java/domain/strategy/GeneralMoveStrategyTest.java b/src/test/java/domain/strategy/GeneralMoveStrategyTest.java new file mode 100644 index 0000000000..e0f7d8f9ed --- /dev/null +++ b/src/test/java/domain/strategy/GeneralMoveStrategyTest.java @@ -0,0 +1,70 @@ +package domain.strategy; + +import domain.*; +import domain.vo.Position; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +class GeneralMoveStrategyTest { + + @Test + @DisplayName("궁의 목적지에 기물이 없으면 이동한다.") + void 궁_정상_이동() { + // given + MoveStrategy strategy = new GeneralMoveStrategy(); + Map boardMapper = new HashMap<>(); + boardMapper.put(Position.of(1, 4), Piece.of(Team.CHU, Type.GENERAL, strategy)); + + Board board = BoardFactory.of(boardMapper); + + // when + Position from = Position.of(1, 4); + Position to = Position.of(1, 5); + + // then + Assertions.assertTrue(strategy.canMove(from, to, board)); + } + + @Test + @DisplayName("궁의 목적지에 같은 팀 기물이 있으면 이동하지 않는다.") + void 궁_목적지에_같은_팀_기물이_있으면_이동_불가() { + // given + MoveStrategy strategy = new GeneralMoveStrategy(); + Map boardMapper = new HashMap<>(); + boardMapper.put(Position.of(1, 4), Piece.of(Team.CHU, Type.GENERAL, strategy)); + boardMapper.put(Position.of(1, 5), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); + + Board board = BoardFactory.of(boardMapper); + + // when + Position from = Position.of(1, 4); + Position to = Position.of(1, 5); + + // then + Assertions.assertFalse(strategy.canMove(from, to, board)); + } + + + @Test + @DisplayName("궁의 목적지에 다른 팀 기물이 있으면 이동한다.") + void 궁_목적지에_다른_팀_기물이_있으면_정상_이동() { + // given + MoveStrategy strategy = new GeneralMoveStrategy(); + Map boardMapper = new HashMap<>(); + boardMapper.put(Position.of(1, 4), Piece.of(Team.CHU, Type.GENERAL, strategy)); + boardMapper.put(Position.of(1, 5), Piece.of(Team.HAN, Type.SOLIDER, new FixedMoveStrategy())); + + Board board = BoardFactory.of(boardMapper); + + // when + Position from = Position.of(1, 4); + Position to = Position.of(1, 5); + + // then + Assertions.assertTrue(strategy.canMove(from, to, board)); + } +} From 4d638e9b6010866676288b5787142ba3d38b36a8 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Thu, 26 Mar 2026 16:52:18 +0900 Subject: [PATCH 25/87] =?UTF-8?q?feat:=20=EC=A1=B8=EC=9D=98=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EA=B7=9C=EC=B9=99=20=EA=B5=AC=ED=98=84=20=EB=B0=8F?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/SoldierMoveStrategy.java | 41 +++++++ .../strategy/SoldierMoveStrategyTest.java | 106 ++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 src/test/java/domain/strategy/SoldierMoveStrategyTest.java diff --git a/src/main/java/domain/strategy/SoldierMoveStrategy.java b/src/main/java/domain/strategy/SoldierMoveStrategy.java index 077d201d11..43418f2af9 100644 --- a/src/main/java/domain/strategy/SoldierMoveStrategy.java +++ b/src/main/java/domain/strategy/SoldierMoveStrategy.java @@ -1,12 +1,53 @@ package domain.strategy; import domain.Board; +import domain.Team; import domain.vo.Position; public class SoldierMoveStrategy implements MoveStrategy { @Override public boolean canMove(Position from, Position to, Board board) { + if (isNotCorrectPath(from, to)) + return false; + + if (isWithdraw(from, to, board)) + return false; + + if (board.isAnotherTeam(from, to)) { + return true; + } + + return false; + } + + private boolean isWithdraw(Position from, Position to, Board board) { + if (board.findPieceByPosition(from).get().getTeam() == Team.CHU) { + if (from.getRow() - to.getRow() == 1) { + return true; + } + } + + if (board.findPieceByPosition(from).get().getTeam() == Team.HAN) { + if (from.getRow() - to.getRow() == -1) { + return true; + } + } + return false; + } + + private boolean isNotCorrectPath(Position from, Position to) { + if (from.getRow() == to.getRow()) { + if (Math.abs(from.getCol() - to.getCol()) != 1) { + return true; + } + } + + if (from.getCol() == to.getCol()) { + if (Math.abs(from.getRow() - to.getRow()) != 1) { + return true; + } + } return false; } } diff --git a/src/test/java/domain/strategy/SoldierMoveStrategyTest.java b/src/test/java/domain/strategy/SoldierMoveStrategyTest.java new file mode 100644 index 0000000000..dc223c108f --- /dev/null +++ b/src/test/java/domain/strategy/SoldierMoveStrategyTest.java @@ -0,0 +1,106 @@ +package domain.strategy; + +import domain.*; +import domain.vo.Position; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +class SoldierMoveStrategyTest { + + @Test + @DisplayName("졸의 목적지에 기물이 없으면 이동한다.") + void 졸_정상_이동() { + // given + MoveStrategy strategy = new SoldierMoveStrategy(); + Map boardMapper = new HashMap<>(); + boardMapper.put(Position.of(3, 4), Piece.of(Team.CHU, Type.SOLIDER, strategy)); + + Board board = BoardFactory.of(boardMapper); + + // when + Position position = Position.of(3, 4); + Position targetPosition = Position.of(4, 4); + + // then + Assertions.assertTrue(strategy.canMove(position, targetPosition, board)); + } + + @Test + @DisplayName("졸의 목적지에 같은 팀 기물이 있으면 이동하지 않는다.") + void 졸_목적지에_같은_팀_기물이_있으면_이동_불가() { + // given + MoveStrategy strategy = new SoldierMoveStrategy(); + Map boardMapper = new HashMap<>(); + boardMapper.put(Position.of(3, 4), Piece.of(Team.CHU, Type.SOLIDER, strategy)); + boardMapper.put(Position.of(4, 4), Piece.of(Team.CHU, Type.SOLIDER, strategy)); + + Board board = BoardFactory.of(boardMapper); + + // when + Position position = Position.of(3, 4); + Position targetPosition = Position.of(4, 4); + + // then + Assertions.assertFalse(strategy.canMove(position, targetPosition, board)); + } + + + @Test + @DisplayName("졸의 목적지에 다른 팀 기물이 있으면 이동한다.") + void 졸_목적지에_다른_팀_기물이_있으면_정상_이동() { + // given + MoveStrategy strategy = new SoldierMoveStrategy(); + Map boardMapper = new HashMap<>(); + boardMapper.put(Position.of(3, 4), Piece.of(Team.CHU, Type.SOLIDER, strategy)); + boardMapper.put(Position.of(4, 4), Piece.of(Team.HAN, Type.SOLIDER, strategy)); + + Board board = BoardFactory.of(boardMapper); + + // when + Position position = Position.of(3, 4); + Position targetPosition = Position.of(4, 4); + + // then + Assertions.assertTrue(strategy.canMove(position, targetPosition, board)); + } + + @Test + @DisplayName("초나라 졸의 이동 경로가 후퇴이면 이동할 수 없다.") + void 초나라_졸의_이동_경로가_후퇴이면_이동_불가() { + // given + MoveStrategy strategy = new SoldierMoveStrategy(); + Map boardMapper = new HashMap<>(); + boardMapper.put(Position.of(3, 4), Piece.of(Team.CHU, Type.SOLIDER, strategy)); + + Board board = BoardFactory.of(boardMapper); + + // when + Position position = Position.of(3, 4); + Position targetPosition = Position.of(2, 4); + + // then + Assertions.assertFalse(strategy.canMove(position, targetPosition, board)); + } + + @Test + @DisplayName("한나라 졸의 이동 경로가 후퇴이면 이동할 수 없다.") + void 한나라_졸의_이동_경로가_후퇴이면_이동_불가() { + // given + MoveStrategy strategy = new SoldierMoveStrategy(); + Map boardMapper = new HashMap<>(); + boardMapper.put(Position.of(6, 4), Piece.of(Team.HAN, Type.SOLIDER, strategy)); + + Board board = BoardFactory.of(boardMapper); + + // when + Position position = Position.of(6, 4); + Position targetPosition = Position.of(7, 4); + + // then + Assertions.assertFalse(strategy.canMove(position, targetPosition, board)); + } +} From 9c39a8ca87f50fd60279ae80cf6c0d96154a7b8b Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Thu, 26 Mar 2026 17:24:57 +0900 Subject: [PATCH 26/87] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EB=A7=A4=EA=B0=9C=EB=B3=80=EC=88=98=20=EB=B6=88=EB=B3=80?= =?UTF-8?q?=ED=99=94=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Board.java | 8 ++++---- src/main/java/domain/BoardFactory.java | 2 +- src/main/java/domain/Team.java | 4 ---- src/main/java/domain/Type.java | 4 ---- src/main/java/domain/strategy/ChariotMoveStrategy.java | 2 +- src/main/java/domain/strategy/GuardMoveStrategy.java | 2 +- src/main/java/domain/vo/Position.java | 6 +++--- 7 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index b3d34c04f6..fe86592c56 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -10,11 +10,11 @@ public class Board { private final Map board; - private Board(Map board) { + private Board(final Map board) { this.board = board; } - public static Board of(Map board) { + public static Board of(final Map board) { return new Board(board); } @@ -23,7 +23,7 @@ public void straightMove(final Position from, final Position to) { board.put(to, fromPiece); } - public boolean isExistPosition(Position tempPosition) { + public boolean isExistPosition(final Position tempPosition) { return board.containsKey(tempPosition); } @@ -31,7 +31,7 @@ public Optional findPieceByPosition(final Position position) { return Optional.ofNullable(board.get(position)); } - public boolean isAnotherTeam(Position from, Position to) { + public boolean isAnotherTeam(final Position from, final Position to) { if (findPieceByPosition(to).isEmpty()) { return true; } diff --git a/src/main/java/domain/BoardFactory.java b/src/main/java/domain/BoardFactory.java index 5be56eb0fd..abf9191355 100644 --- a/src/main/java/domain/BoardFactory.java +++ b/src/main/java/domain/BoardFactory.java @@ -10,7 +10,7 @@ public class BoardFactory { private BoardFactory() {} - public static Board of(Map board) { + public static Board of(final Map board) { return Board.of(board); } diff --git a/src/main/java/domain/Team.java b/src/main/java/domain/Team.java index 0ea187ebef..a2184791ef 100644 --- a/src/main/java/domain/Team.java +++ b/src/main/java/domain/Team.java @@ -9,8 +9,4 @@ public enum Team { Team(String nation) { this.nation = nation; } - - public Team getNation() { - return this; - } } diff --git a/src/main/java/domain/Type.java b/src/main/java/domain/Type.java index 40c055f976..591a0e2578 100644 --- a/src/main/java/domain/Type.java +++ b/src/main/java/domain/Type.java @@ -14,8 +14,4 @@ public enum Type { Type(String name) { this.name = name; } - - public Type getType() { - return this; - } } diff --git a/src/main/java/domain/strategy/ChariotMoveStrategy.java b/src/main/java/domain/strategy/ChariotMoveStrategy.java index f6f6983580..523e052366 100644 --- a/src/main/java/domain/strategy/ChariotMoveStrategy.java +++ b/src/main/java/domain/strategy/ChariotMoveStrategy.java @@ -3,7 +3,7 @@ import domain.Board; import domain.vo.Position; -public class ChariotMoveStrategy implements MoveStrategy{ +public class ChariotMoveStrategy implements MoveStrategy { @Override public boolean canMove(Position from, Position to, Board board) { diff --git a/src/main/java/domain/strategy/GuardMoveStrategy.java b/src/main/java/domain/strategy/GuardMoveStrategy.java index b72e36189c..81b1c31825 100644 --- a/src/main/java/domain/strategy/GuardMoveStrategy.java +++ b/src/main/java/domain/strategy/GuardMoveStrategy.java @@ -3,7 +3,7 @@ import domain.Board; import domain.vo.Position; -public class GuardMoveStrategy implements MoveStrategy{ +public class GuardMoveStrategy implements MoveStrategy { @Override public boolean canMove(Position from, Position to, Board board) { diff --git a/src/main/java/domain/vo/Position.java b/src/main/java/domain/vo/Position.java index 2b6ed562ed..d9ad8254b8 100644 --- a/src/main/java/domain/vo/Position.java +++ b/src/main/java/domain/vo/Position.java @@ -13,18 +13,18 @@ private Position(final int row, final int col) { this.col = col; } - private void validate(int row, int col) { + private void validate(final int row, final int col) { validateRowInRange(row); validateColInRange(col); } - private void validateColInRange(int col) { + private void validateColInRange(final int col) { if (0 > col || col > 8) { throw new IllegalArgumentException("[ERROR] 열이 0~8 범위를 벗어났습니다."); } } - private void validateRowInRange(int row) { + private void validateRowInRange(final int row) { if (0 > row || row > 9) { throw new IllegalArgumentException("[ERROR] 행이 0~9 범위를 벗어났습니다."); } From cc703aa32d3a31d6d4ce1c78dbbdab15e68b4e2a Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Thu, 26 Mar 2026 17:28:19 +0900 Subject: [PATCH 27/87] =?UTF-8?q?refactor:=20=EC=83=81=EC=9D=98=20?= =?UTF-8?q?=EC=B5=9C=EC=A2=85=20=EB=AA=A9=EC=A0=81=EC=A7=80=20=EC=B6=94?= =?UTF-8?q?=EC=B6=9C=ED=95=98=EB=8A=94=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EB=8B=A8=EC=88=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/ElephantMoveStrategy.java | 43 +------------------ 1 file changed, 2 insertions(+), 41 deletions(-) diff --git a/src/main/java/domain/strategy/ElephantMoveStrategy.java b/src/main/java/domain/strategy/ElephantMoveStrategy.java index 6aba63dec3..841b1f5175 100644 --- a/src/main/java/domain/strategy/ElephantMoveStrategy.java +++ b/src/main/java/domain/strategy/ElephantMoveStrategy.java @@ -11,47 +11,8 @@ public boolean canMove(Position from, Position to, Board board) { if (isNotCorrectPath(from, to)) return false; - int nx = 0, ny = 0; - if (from.getRow() - to.getRow() == 3) { - if (from.getCol() - to.getCol() == 2) { - nx = -3; - ny = -2; - } - if (from.getCol() - to.getCol() == -2) { - nx = -3; - ny = 2; - } - } - if (from.getRow() - to.getRow() == -3) { - if (from.getCol() - to.getCol() == 2) { - nx = 3; - ny = -2; - } - if (from.getCol() - to.getCol() == -2) { - nx = 3; - ny = 2; - } - } - if (from.getRow() - to.getRow() == 2) { - if (from.getCol() - to.getCol() == 3) { - nx = -2; - ny = -3; - } - if (from.getCol() - to.getCol() == -3) { - nx = -2; - ny = 3; - } - } - if (from.getRow() - to.getRow() == -2) { - if (from.getCol() - to.getCol() == 3) { - nx = 2; - ny = -3; - } - if (from.getCol() - to.getCol() == -3) { - nx = 2; - ny = 3; - } - } + int nx = to.getRow() - from.getRow(); + int ny = to.getCol() - from.getCol(); int row = from.getRow(); int col = from.getCol(); From a8aedbede364e72da14b3d62a7936f242147aa9a Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Thu, 26 Mar 2026 17:45:28 +0900 Subject: [PATCH 28/87] =?UTF-8?q?refactor:=20=ED=8F=AC=EC=9D=98=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=EA=B0=80=EB=8A=A5=20=EC=97=AC=EB=B6=80=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=20=EC=A1=B0=EA=B1=B4=EB=AC=B8=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/CannonMoveStrategy.java | 53 ++++++++++++------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/src/main/java/domain/strategy/CannonMoveStrategy.java b/src/main/java/domain/strategy/CannonMoveStrategy.java index 420541bb1f..c042717663 100644 --- a/src/main/java/domain/strategy/CannonMoveStrategy.java +++ b/src/main/java/domain/strategy/CannonMoveStrategy.java @@ -11,19 +11,8 @@ public boolean canMove(Position from, Position to, Board board) { if (isNotCorrectPath(from, to)) return false; - int nx = 0, ny = 0; - if (from.getRow() < to.getRow()) { - nx = 1; - } - if (from.getRow() > to.getRow()) { - nx = -1; - } - if (from.getCol() < to.getCol()) { - ny = 1; - } - if (from.getCol() > to.getCol()) { - ny = -1; - } + int nx = determineNx(from, to); + int ny = determineNy(from, to); int pieceCount = 0; int row = from.getRow(); @@ -33,13 +22,7 @@ public boolean canMove(Position from, Position to, Board board) { col += ny; if (row == to.getRow() && col == to.getCol()) { - if (!isCannon(board, to.getRow(), to.getCol()) - && board.isAnotherTeam(from, to) - && pieceCount == 1) { - return true; - } - - return false; + return isCannonValidTarget(from, to, board, pieceCount); } if (board.isExistPosition(Position.of(row, col))) { @@ -56,6 +39,36 @@ public boolean canMove(Position from, Position to, Board board) { } } + private boolean isCannonValidTarget(Position from, Position to, Board board, int pieceCount) { + if (!isCannon(board, to.getRow(), to.getCol()) + && board.isAnotherTeam(from, to) + && pieceCount == 1) { + return true; + } + return false; + } + + private int determineNx(Position from, Position to) { + if (from.getRow() < to.getRow()) { + return 1; + } + if (from.getRow() > to.getRow()) { + return -1; + } + return 0; + } + + private int determineNy(Position from, Position to) { + if (from.getCol() < to.getCol()) { + return 1; + } + if (from.getCol() > to.getCol()) { + return -1; + } + + return 0; + } + private boolean isCannon(Board board, int row, int col) { if (board.findPieceByPosition(Position.of(row, col)).isEmpty()) return false; return board.findPieceByPosition(Position.of(row, col)).get().getType() == Type.CANNON; From b2722cb09977fcfda3f374d4e43f9616d3b81a72 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Thu, 26 Mar 2026 17:52:01 +0900 Subject: [PATCH 29/87] =?UTF-8?q?refactor:=20=ED=8F=AC=EC=9D=98=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=EC=9A=94=EA=B5=AC=20=EA=B8=B0=EB=AC=BC=20?= =?UTF-8?q?=EA=B0=AF=EC=88=98=20=EB=A7=A4=EC=A7=81=EB=84=98=EB=B2=84=20?= =?UTF-8?q?=EC=83=81=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/strategy/CannonMoveStrategy.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/domain/strategy/CannonMoveStrategy.java b/src/main/java/domain/strategy/CannonMoveStrategy.java index c042717663..efaba696c5 100644 --- a/src/main/java/domain/strategy/CannonMoveStrategy.java +++ b/src/main/java/domain/strategy/CannonMoveStrategy.java @@ -6,6 +6,8 @@ public class CannonMoveStrategy implements MoveStrategy { + private static final int CANNON_REQUIRED_PIECE_COUNT = 1; + @Override public boolean canMove(Position from, Position to, Board board) { if (isNotCorrectPath(from, to)) @@ -33,7 +35,7 @@ public boolean canMove(Position from, Position to, Board board) { pieceCount += 1; } - if (pieceCount > 1) { + if (pieceCount > CANNON_REQUIRED_PIECE_COUNT) { return false; } } @@ -42,7 +44,7 @@ public boolean canMove(Position from, Position to, Board board) { private boolean isCannonValidTarget(Position from, Position to, Board board, int pieceCount) { if (!isCannon(board, to.getRow(), to.getCol()) && board.isAnotherTeam(from, to) - && pieceCount == 1) { + && pieceCount == CANNON_REQUIRED_PIECE_COUNT) { return true; } return false; From 5ab2e6c9942e553c7e1cf94e152e538cdbdd0970 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Fri, 27 Mar 2026 17:07:48 +0900 Subject: [PATCH 30/87] =?UTF-8?q?refactor:=20=EB=A7=A4=EA=B0=9C=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=EB=B6=88=EB=B3=80=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Board.java | 1 - src/main/java/domain/strategy/CannonMoveStrategy.java | 4 ++-- src/main/java/domain/strategy/ChariotMoveStrategy.java | 4 ++-- src/main/java/domain/strategy/ElephantMoveStrategy.java | 4 ++-- src/main/java/domain/strategy/GeneralMoveStrategy.java | 4 ++-- src/main/java/domain/strategy/GuardMoveStrategy.java | 2 +- src/main/java/domain/strategy/HorseMoveStrategy.java | 4 ++-- src/main/java/domain/strategy/MoveStrategy.java | 2 +- src/main/java/domain/strategy/SoldierMoveStrategy.java | 6 +++--- 9 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index fe86592c56..61e7c694f1 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -1,6 +1,5 @@ package domain; -import domain.strategy.*; import domain.vo.Position; import java.util.Map; diff --git a/src/main/java/domain/strategy/CannonMoveStrategy.java b/src/main/java/domain/strategy/CannonMoveStrategy.java index efaba696c5..da3600d050 100644 --- a/src/main/java/domain/strategy/CannonMoveStrategy.java +++ b/src/main/java/domain/strategy/CannonMoveStrategy.java @@ -9,7 +9,7 @@ public class CannonMoveStrategy implements MoveStrategy { private static final int CANNON_REQUIRED_PIECE_COUNT = 1; @Override - public boolean canMove(Position from, Position to, Board board) { + public boolean canMove(final Position from, final Position to, final Board board) { if (isNotCorrectPath(from, to)) return false; @@ -41,7 +41,7 @@ public boolean canMove(Position from, Position to, Board board) { } } - private boolean isCannonValidTarget(Position from, Position to, Board board, int pieceCount) { + private boolean isCannonValidTarget(final Position from, final Position to, final Board board, final int pieceCount) { if (!isCannon(board, to.getRow(), to.getCol()) && board.isAnotherTeam(from, to) && pieceCount == CANNON_REQUIRED_PIECE_COUNT) { diff --git a/src/main/java/domain/strategy/ChariotMoveStrategy.java b/src/main/java/domain/strategy/ChariotMoveStrategy.java index 523e052366..5deab2c67d 100644 --- a/src/main/java/domain/strategy/ChariotMoveStrategy.java +++ b/src/main/java/domain/strategy/ChariotMoveStrategy.java @@ -6,7 +6,7 @@ public class ChariotMoveStrategy implements MoveStrategy { @Override - public boolean canMove(Position from, Position to, Board board) { + public boolean canMove(final Position from, final Position to, final Board board) { if (isNotStraightPath(from, to)) return false; @@ -48,7 +48,7 @@ public boolean canMove(Position from, Position to, Board board) { } } - private boolean isNotStraightPath(Position from, Position to) { + private boolean isNotStraightPath(final Position from, final Position to) { if (from.getCol() != to.getCol() && from.getRow() != to.getRow()) { return true; } diff --git a/src/main/java/domain/strategy/ElephantMoveStrategy.java b/src/main/java/domain/strategy/ElephantMoveStrategy.java index 841b1f5175..c0ad605523 100644 --- a/src/main/java/domain/strategy/ElephantMoveStrategy.java +++ b/src/main/java/domain/strategy/ElephantMoveStrategy.java @@ -6,7 +6,7 @@ public class ElephantMoveStrategy implements MoveStrategy { @Override - public boolean canMove(Position from, Position to, Board board) { + public boolean canMove(final Position from, final Position to, final Board board) { if (isNotCorrectPath(from, to)) return false; @@ -40,7 +40,7 @@ public boolean canMove(Position from, Position to, Board board) { return false; } - private boolean isNotCorrectPath(Position from, Position to) { + private boolean isNotCorrectPath(final Position from, final Position to) { if (Math.abs(from.getRow() - to.getRow()) == 2) { if (Math.abs(from.getCol() - to.getCol()) != 3) { return true; diff --git a/src/main/java/domain/strategy/GeneralMoveStrategy.java b/src/main/java/domain/strategy/GeneralMoveStrategy.java index 0c2b2b9f40..48a134e539 100644 --- a/src/main/java/domain/strategy/GeneralMoveStrategy.java +++ b/src/main/java/domain/strategy/GeneralMoveStrategy.java @@ -6,7 +6,7 @@ public class GeneralMoveStrategy implements MoveStrategy { @Override - public boolean canMove(Position from, Position to, Board board) { + public boolean canMove(final Position from, final Position to, final Board board) { if (isNotCorrectPath(from, to)) return false; @@ -16,7 +16,7 @@ public boolean canMove(Position from, Position to, Board board) { return false; } - private boolean isNotCorrectPath(Position from, Position to) { + private boolean isNotCorrectPath(final Position from, final Position to) { if (from.getRow() == to.getRow()) { if (Math.abs(from.getCol() - to.getCol()) != 1) { return true; diff --git a/src/main/java/domain/strategy/GuardMoveStrategy.java b/src/main/java/domain/strategy/GuardMoveStrategy.java index 81b1c31825..97106a0ecd 100644 --- a/src/main/java/domain/strategy/GuardMoveStrategy.java +++ b/src/main/java/domain/strategy/GuardMoveStrategy.java @@ -6,7 +6,7 @@ public class GuardMoveStrategy implements MoveStrategy { @Override - public boolean canMove(Position from, Position to, Board board) { + public boolean canMove(final Position from, final Position to, final Board board) { if (from.getRow() == to.getRow()) { if (Math.abs(from.getCol() - to.getCol()) != 1) { return false; diff --git a/src/main/java/domain/strategy/HorseMoveStrategy.java b/src/main/java/domain/strategy/HorseMoveStrategy.java index 1eb9f1600d..9bb9c09d31 100644 --- a/src/main/java/domain/strategy/HorseMoveStrategy.java +++ b/src/main/java/domain/strategy/HorseMoveStrategy.java @@ -6,7 +6,7 @@ public class HorseMoveStrategy implements MoveStrategy { @Override - public boolean canMove(Position from, Position to, Board board) { + public boolean canMove(final Position from, final Position to, final Board board) { if (isNotCorrectPath(from, to)) return false; @@ -23,7 +23,7 @@ public boolean canMove(Position from, Position to, Board board) { return false; } - private boolean isNotCorrectPath(Position from, Position to) { + private boolean isNotCorrectPath(final Position from, final Position to) { if (Math.abs(from.getRow() - to.getRow()) == 1) { if (Math.abs(from.getCol() - to.getCol()) != 2) { return true; diff --git a/src/main/java/domain/strategy/MoveStrategy.java b/src/main/java/domain/strategy/MoveStrategy.java index f457f78b9e..5f9dcb5789 100644 --- a/src/main/java/domain/strategy/MoveStrategy.java +++ b/src/main/java/domain/strategy/MoveStrategy.java @@ -5,5 +5,5 @@ public interface MoveStrategy { - boolean canMove(Position from, Position to, Board board); + boolean canMove(final Position from, final Position to, final Board board); } diff --git a/src/main/java/domain/strategy/SoldierMoveStrategy.java b/src/main/java/domain/strategy/SoldierMoveStrategy.java index 43418f2af9..2dfe9cd8c1 100644 --- a/src/main/java/domain/strategy/SoldierMoveStrategy.java +++ b/src/main/java/domain/strategy/SoldierMoveStrategy.java @@ -7,7 +7,7 @@ public class SoldierMoveStrategy implements MoveStrategy { @Override - public boolean canMove(Position from, Position to, Board board) { + public boolean canMove(final Position from, final Position to, final Board board) { if (isNotCorrectPath(from, to)) return false; @@ -21,7 +21,7 @@ public boolean canMove(Position from, Position to, Board board) { return false; } - private boolean isWithdraw(Position from, Position to, Board board) { + private boolean isWithdraw(final Position from, final Position to, final Board board) { if (board.findPieceByPosition(from).get().getTeam() == Team.CHU) { if (from.getRow() - to.getRow() == 1) { return true; @@ -36,7 +36,7 @@ private boolean isWithdraw(Position from, Position to, Board board) { return false; } - private boolean isNotCorrectPath(Position from, Position to) { + private boolean isNotCorrectPath(final Position from, final Position to) { if (from.getRow() == to.getRow()) { if (Math.abs(from.getCol() - to.getCol()) != 1) { return true; From 8ee3b625fa1eecfb9256bb3d9a7794966f2fe385 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Fri, 27 Mar 2026 17:21:19 +0900 Subject: [PATCH 31/87] =?UTF-8?q?refactor:=20=EA=B0=99=EC=9D=80=20?= =?UTF-8?q?=ED=8C=80=20=EA=B8=B0=EB=AC=BC=EC=9D=B8=EC=A7=80=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=ED=95=98=EB=8A=94=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=B1=85=EC=9E=84=EC=9D=84=20=EB=B3=B4=EB=93=9C=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EA=B8=B0=EB=AC=BC=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Board.java | 4 ++-- src/main/java/domain/Piece.java | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index 61e7c694f1..cbf6c0fd49 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -35,8 +35,8 @@ public boolean isAnotherTeam(final Position from, final Position to) { return true; } - Piece targetPiece = findPieceByPosition(to).get(); Piece currentPiece = findPieceByPosition(from).get(); - return currentPiece.getTeam() != targetPiece.getTeam(); + Piece targetPiece = findPieceByPosition(to).get(); + return currentPiece.isAnotherTeam(targetPiece); } } diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java index 2b1cd6e5df..0c55cc7267 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/Piece.java @@ -18,6 +18,10 @@ public static Piece of(final Team team, final Type type, final MoveStrategy move return new Piece(team, type, moveStrategy); } + public boolean isAnotherTeam(Piece anotherPiece) { + return this.team != anotherPiece.team; + } + public Type getType() { return type; } From 66511888aa01d83044282b81b445e64d45dd1632 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Fri, 27 Mar 2026 17:59:29 +0900 Subject: [PATCH 32/87] =?UTF-8?q?refactor:=20isCannon=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/strategy/CannonMoveStrategy.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/domain/strategy/CannonMoveStrategy.java b/src/main/java/domain/strategy/CannonMoveStrategy.java index da3600d050..3c8364b375 100644 --- a/src/main/java/domain/strategy/CannonMoveStrategy.java +++ b/src/main/java/domain/strategy/CannonMoveStrategy.java @@ -50,6 +50,11 @@ private boolean isCannonValidTarget(final Position from, final Position to, fina return false; } + private boolean isCannon(Board board, int row, int col) { + if (board.findPieceByPosition(Position.of(row, col)).isEmpty()) return false; + return board.findPieceByPosition(Position.of(row, col)).get().getType() == Type.CANNON; + } + private int determineNx(Position from, Position to) { if (from.getRow() < to.getRow()) { return 1; @@ -71,11 +76,6 @@ private int determineNy(Position from, Position to) { return 0; } - private boolean isCannon(Board board, int row, int col) { - if (board.findPieceByPosition(Position.of(row, col)).isEmpty()) return false; - return board.findPieceByPosition(Position.of(row, col)).get().getType() == Type.CANNON; - } - private boolean isNotCorrectPath(Position from, Position to) { if (from.getRow() != to.getRow() && from.getCol() != to.getCol()) { return true; From 4138d895a5da77602617410f498ab08b16b0850c Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Fri, 27 Mar 2026 19:06:52 +0900 Subject: [PATCH 33/87] =?UTF-8?q?refacotr:=20=EB=A7=A4=EC=A7=81=EB=84=98?= =?UTF-8?q?=EB=B2=84=20=EC=A0=9C=EA=B1=B0=20=EB=B0=8F=20=EC=B6=9C=EB=A0=A5?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EC=A0=9C=EA=B1=B0,=20if=EB=AC=B8=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Board.java | 2 +- src/main/java/domain/Piece.java | 2 +- src/main/java/domain/Team.java | 10 ++---- src/main/java/domain/Type.java | 20 +++++------- .../domain/strategy/ChariotMoveStrategy.java | 14 +++------ .../domain/strategy/ElephantMoveStrategy.java | 31 ++++++------------- .../domain/strategy/GeneralMoveStrategy.java | 14 ++++----- .../domain/strategy/GuardMoveStrategy.java | 14 ++++----- .../domain/strategy/HorseMoveStrategy.java | 13 ++++---- .../domain/strategy/SoldierMoveStrategy.java | 27 +++++++--------- src/main/java/domain/vo/Position.java | 15 +++++---- src/test/java/domain/BoardTest.java | 4 +-- 12 files changed, 66 insertions(+), 100 deletions(-) diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index cbf6c0fd49..603727096b 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -17,7 +17,7 @@ public static Board of(final Map board) { return new Board(board); } - public void straightMove(final Position from, final Position to) { + public void move(final Position from, final Position to) { Piece fromPiece = findPieceByPosition(from).get(); board.put(to, fromPiece); } diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java index 0c55cc7267..1337bf2c57 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/Piece.java @@ -18,7 +18,7 @@ public static Piece of(final Team team, final Type type, final MoveStrategy move return new Piece(team, type, moveStrategy); } - public boolean isAnotherTeam(Piece anotherPiece) { + public boolean isAnotherTeam(final Piece anotherPiece) { return this.team != anotherPiece.team; } diff --git a/src/main/java/domain/Team.java b/src/main/java/domain/Team.java index a2184791ef..b856878a95 100644 --- a/src/main/java/domain/Team.java +++ b/src/main/java/domain/Team.java @@ -1,12 +1,8 @@ package domain; public enum Team { - CHU("초"), - HAN("한"); + CHU, + HAN; - private final String nation; - - Team(String nation) { - this.nation = nation; - } + Team() {} } diff --git a/src/main/java/domain/Type.java b/src/main/java/domain/Type.java index 591a0e2578..80562344df 100644 --- a/src/main/java/domain/Type.java +++ b/src/main/java/domain/Type.java @@ -1,17 +1,13 @@ package domain; public enum Type { - GENERAL("궁"), - CHARIOT("차"), - CANNON("포"), - HORSE("마"), - ELEPHANT("상"), - GUARD("사"), - SOLIDER("졸"); + GENERAL, + CHARIOT, + CANNON, + HORSE, + ELEPHANT, + GUARD, + SOLIDER; - private final String name; - - Type(String name) { - this.name = name; - } + Type() {} } diff --git a/src/main/java/domain/strategy/ChariotMoveStrategy.java b/src/main/java/domain/strategy/ChariotMoveStrategy.java index 5deab2c67d..efff63ecaf 100644 --- a/src/main/java/domain/strategy/ChariotMoveStrategy.java +++ b/src/main/java/domain/strategy/ChariotMoveStrategy.java @@ -8,7 +8,7 @@ public class ChariotMoveStrategy implements MoveStrategy { @Override public boolean canMove(final Position from, final Position to, final Board board) { - if (isNotStraightPath(from, to)) + if (isNotCorrectPath(from, to)) return false; int nx = 0, ny = 0; @@ -37,10 +37,7 @@ public boolean canMove(final Position from, final Position to, final Board board col += ny; if (row == to.getRow() && col == to.getCol()) { - if (board.isAnotherTeam(from, to)) { - return true; - } - return false; + return board.isAnotherTeam(from, to); } if (board.isExistPosition(Position.of(row, col))) { return false; @@ -48,10 +45,7 @@ public boolean canMove(final Position from, final Position to, final Board board } } - private boolean isNotStraightPath(final Position from, final Position to) { - if (from.getCol() != to.getCol() && from.getRow() != to.getRow()) { - return true; - } - return false; + private boolean isNotCorrectPath(final Position from, final Position to) { + return from.getCol() != to.getCol() && from.getRow() != to.getRow(); } } diff --git a/src/main/java/domain/strategy/ElephantMoveStrategy.java b/src/main/java/domain/strategy/ElephantMoveStrategy.java index c0ad605523..244b87cedd 100644 --- a/src/main/java/domain/strategy/ElephantMoveStrategy.java +++ b/src/main/java/domain/strategy/ElephantMoveStrategy.java @@ -17,21 +17,12 @@ public boolean canMove(final Position from, final Position to, final Board board int row = from.getRow(); int col = from.getCol(); - if (Math.abs(nx) == 3) { - if (board.isExistPosition(Position.of(row + nx / 3, col))) { - return false; - } - if (board.isExistPosition(Position.of(row + nx * 2 / 3, col + ny / 2))) { - return false; - } + if (board.isExistPosition(Position.of(row + nx / 3, col + ny / 3))) { + return false; } - if (Math.abs(nx) == 2) { - if (board.isExistPosition(Position.of(row, col + ny / 3))) { - return false; - } - if (board.isExistPosition(Position.of(row + nx / 2, col + ny * 2 / 3))) { - return false; - } + + if (board.isExistPosition(Position.of(row + nx / 3 + nx / 2, col + ny / 3 + ny / 2))) { + return false; } if (board.isAnotherTeam(from, to)) { @@ -41,15 +32,11 @@ public boolean canMove(final Position from, final Position to, final Board board } private boolean isNotCorrectPath(final Position from, final Position to) { - if (Math.abs(from.getRow() - to.getRow()) == 2) { - if (Math.abs(from.getCol() - to.getCol()) != 3) { - return true; - } + if (Math.abs(from.getRow() - to.getRow()) == 2 && Math.abs(from.getCol() - to.getCol()) != 3) { + return true; } - if (Math.abs(from.getRow() - to.getRow()) == 3) { - if (Math.abs(from.getCol() - to.getCol()) != 2) { - return true; - } + if (Math.abs(from.getRow() - to.getRow()) == 3 && Math.abs(from.getCol() - to.getCol()) != 2) { + return true; } return false; } diff --git a/src/main/java/domain/strategy/GeneralMoveStrategy.java b/src/main/java/domain/strategy/GeneralMoveStrategy.java index 48a134e539..b8822fd910 100644 --- a/src/main/java/domain/strategy/GeneralMoveStrategy.java +++ b/src/main/java/domain/strategy/GeneralMoveStrategy.java @@ -17,16 +17,14 @@ public boolean canMove(final Position from, final Position to, final Board board } private boolean isNotCorrectPath(final Position from, final Position to) { - if (from.getRow() == to.getRow()) { - if (Math.abs(from.getCol() - to.getCol()) != 1) { - return true; - } + if (from.getRow() == to.getRow() && Math.abs(from.getCol() - to.getCol()) != 1) { + return true; } - if (from.getCol() == to.getCol()) { - if (Math.abs(from.getRow() - to.getRow()) != 1) { - return true; - } + + if (from.getCol() == to.getCol() && Math.abs(from.getRow() - to.getRow()) != 1) { + return true; } + return false; } } diff --git a/src/main/java/domain/strategy/GuardMoveStrategy.java b/src/main/java/domain/strategy/GuardMoveStrategy.java index 97106a0ecd..e67045819d 100644 --- a/src/main/java/domain/strategy/GuardMoveStrategy.java +++ b/src/main/java/domain/strategy/GuardMoveStrategy.java @@ -7,20 +7,18 @@ public class GuardMoveStrategy implements MoveStrategy { @Override public boolean canMove(final Position from, final Position to, final Board board) { - if (from.getRow() == to.getRow()) { - if (Math.abs(from.getCol() - to.getCol()) != 1) { - return false; - } + if (from.getRow() == to.getRow() && Math.abs(from.getCol() - to.getCol()) != 1) { + return false; } - if (from.getCol() == to.getCol()) { - if (Math.abs(from.getRow() - to.getRow()) != 1) { - return false; - } + + if (from.getCol() == to.getCol() && Math.abs(from.getRow() - to.getRow()) != 1) { + return false; } if (board.isAnotherTeam(from, to)) { return true; } + return false; } } diff --git a/src/main/java/domain/strategy/HorseMoveStrategy.java b/src/main/java/domain/strategy/HorseMoveStrategy.java index 9bb9c09d31..6a29420999 100644 --- a/src/main/java/domain/strategy/HorseMoveStrategy.java +++ b/src/main/java/domain/strategy/HorseMoveStrategy.java @@ -24,15 +24,14 @@ public boolean canMove(final Position from, final Position to, final Board board } private boolean isNotCorrectPath(final Position from, final Position to) { - if (Math.abs(from.getRow() - to.getRow()) == 1) { - if (Math.abs(from.getCol() - to.getCol()) != 2) { - return true; - } + if (Math.abs(from.getRow() - to.getRow()) == 1 && Math.abs(from.getCol() - to.getCol()) != 2) { + return true; } - if (Math.abs(from.getRow() - to.getRow()) == 2) { - if (Math.abs(from.getCol() - to.getCol()) != 1) - return true; + + if (Math.abs(from.getRow() - to.getRow()) == 2 && Math.abs(from.getCol() - to.getCol()) != 1) { + return true; } + return false; } } diff --git a/src/main/java/domain/strategy/SoldierMoveStrategy.java b/src/main/java/domain/strategy/SoldierMoveStrategy.java index 2dfe9cd8c1..2a4d63f9b7 100644 --- a/src/main/java/domain/strategy/SoldierMoveStrategy.java +++ b/src/main/java/domain/strategy/SoldierMoveStrategy.java @@ -22,32 +22,27 @@ public boolean canMove(final Position from, final Position to, final Board board } private boolean isWithdraw(final Position from, final Position to, final Board board) { - if (board.findPieceByPosition(from).get().getTeam() == Team.CHU) { - if (from.getRow() - to.getRow() == 1) { - return true; - } + Team team = board.findPieceByPosition(from).get().getTeam(); + if (team == Team.CHU && from.getRow() - to.getRow() == 1) { + return true; } - if (board.findPieceByPosition(from).get().getTeam() == Team.HAN) { - if (from.getRow() - to.getRow() == -1) { - return true; - } + if (team == Team.HAN && from.getRow() - to.getRow() == -1) { + return true; } + return false; } private boolean isNotCorrectPath(final Position from, final Position to) { - if (from.getRow() == to.getRow()) { - if (Math.abs(from.getCol() - to.getCol()) != 1) { - return true; - } + if (from.getRow() == to.getRow() && Math.abs(from.getCol() - to.getCol()) != 1) { + return true; } - if (from.getCol() == to.getCol()) { - if (Math.abs(from.getRow() - to.getRow()) != 1) { - return true; - } + if (from.getCol() == to.getCol() && Math.abs(from.getRow() - to.getRow()) != 1) { + return true; } + return false; } } diff --git a/src/main/java/domain/vo/Position.java b/src/main/java/domain/vo/Position.java index d9ad8254b8..00e668a270 100644 --- a/src/main/java/domain/vo/Position.java +++ b/src/main/java/domain/vo/Position.java @@ -4,6 +4,9 @@ public class Position { + private static final int MAX_COLUMN = 8; + private static final int MAX_ROW = 9; + private final int row; private final int col; @@ -18,15 +21,15 @@ private void validate(final int row, final int col) { validateColInRange(col); } - private void validateColInRange(final int col) { - if (0 > col || col > 8) { - throw new IllegalArgumentException("[ERROR] 열이 0~8 범위를 벗어났습니다."); + private void validateRowInRange(final int row) { + if (0 > row || row > MAX_ROW) { + throw new IllegalArgumentException("[ERROR] 행이 0~" + MAX_ROW + " 범위를 벗어났습니다."); } } - private void validateRowInRange(final int row) { - if (0 > row || row > 9) { - throw new IllegalArgumentException("[ERROR] 행이 0~9 범위를 벗어났습니다."); + private void validateColInRange(final int col) { + if (0 > col || col > MAX_COLUMN) { + throw new IllegalArgumentException("[ERROR] 열이 0~" + MAX_COLUMN + " 범위를 벗어났습니다."); } } diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java index 908e4672d3..c42cb9f1a2 100644 --- a/src/test/java/domain/BoardTest.java +++ b/src/test/java/domain/BoardTest.java @@ -27,7 +27,7 @@ class BoardTest { // when Position from = Position.of(0, 0); Position to = Position.of(1, 0); - board.straightMove(from, to); + board.move(from, to); // then Piece findPiece = board.findPieceByPosition(to).get(); @@ -42,7 +42,7 @@ class BoardTest { Position to = Position.of(3, 3); // when - board.straightMove(Position.of(0, 1), Position.of(1, 1)); + board.move(Position.of(0, 1), Position.of(1, 1)); // board.diagonalMove(Position.of(1, 1), to); // then From 3490407fc87c33ded9c65c82c75ff499a1108b80 Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Fri, 27 Mar 2026 19:23:40 +0900 Subject: [PATCH 34/87] =?UTF-8?q?test:=20Board=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/BoardTest.java | 66 +++++++++++++++++++---------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java index c42cb9f1a2..39ddfc0a2e 100644 --- a/src/test/java/domain/BoardTest.java +++ b/src/test/java/domain/BoardTest.java @@ -1,51 +1,71 @@ package domain; import domain.vo.Position; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; class BoardTest { - @Test + @ParameterizedTest + @MethodSource("providePiece") @DisplayName("보드를 생성하면 기물들 초기화된다.") - void 보드_생성() { + void 보드_생성(int row, int col, Type expected) { // given // when + Board board = BoardFactory.setUp(); + // then - assertDoesNotThrow(() -> BoardFactory.setUp()); + Piece piece = board.findPieceByPosition(Position.of(row, col)).get(); + assertEquals(expected, piece.getType()); } @Test - @DisplayName("기물의 직선 이동 경로에 다른 기물이 없으면 이동한다.") - void 기물_직선_이동() { + @DisplayName("기물의 이동 경로에 다른 기물이 없으면 이동한다.") + void 기물_이동() { // given - Board board = BoardFactory.setUp(); + Map tempBoard = new HashMap<>(); + tempBoard.put(Position.of(0, 0), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); + tempBoard.put(Position.of(0, 3), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); + + Board board = Board.of(tempBoard); // when Position from = Position.of(0, 0); - Position to = Position.of(1, 0); + Position to = Position.of(3, 0); board.move(from, to); // then Piece findPiece = board.findPieceByPosition(to).get(); - Assertions.assertEquals(Type.CHARIOT, findPiece.getType()); + assertEquals(Type.SOLIDER, findPiece.getType()); } - @Test - @DisplayName("기물의 대각선 이동 경로에 다른 기물이 없으면 이동한다.") - void 기물_대각선_이동() { - // given - Board board = BoardFactory.setUp(); - Position to = Position.of(3, 3); - - // when - board.move(Position.of(0, 1), Position.of(1, 1)); - // board.diagonalMove(Position.of(1, 1), to); - - // then - // assertEquals(Type.ELEPHANT, board.findPieceByPosition(to).getType()); + private static Stream providePiece() { + return Stream.of( + Arguments.of(0, 0, Type.CHARIOT), + Arguments.of(0, 1, Type.ELEPHANT), + Arguments.of(0, 2, Type.HORSE), + Arguments.of(0, 3, Type.GUARD), + Arguments.of(0, 8, Type.CHARIOT), + Arguments.of(1, 4, Type.GENERAL), + Arguments.of(2, 1, Type.CANNON), + Arguments.of(3, 0, Type.SOLIDER), + Arguments.of(3, 4, Type.SOLIDER), + Arguments.of(6, 2, Type.SOLIDER), + Arguments.of(7, 1, Type.CANNON), + Arguments.of(8, 4, Type.GENERAL), + Arguments.of(9, 0, Type.CHARIOT), + Arguments.of(9, 3, Type.GUARD), + Arguments.of(9, 7, Type.HORSE), + Arguments.of(9, 8, Type.CHARIOT) + ); } } From 576bb718ce570d6c2dc16503fec82bf50880a43e Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Fri, 27 Mar 2026 19:27:50 +0900 Subject: [PATCH 35/87] =?UTF-8?q?feat:=20=EA=B8=B0=EB=AC=BC=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EC=8B=9C=20=EC=9D=B4=EC=A0=84=20=EC=9C=84=EC=B9=98?= =?UTF-8?q?=EC=97=90=20=EC=9E=88=EB=8D=98=20=EA=B8=B0=EB=AC=BC=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Board.java | 1 + src/test/java/domain/BoardTest.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index 603727096b..a4094f99cf 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -19,6 +19,7 @@ public static Board of(final Map board) { public void move(final Position from, final Position to) { Piece fromPiece = findPieceByPosition(from).get(); + board.remove(from); board.put(to, fromPiece); } diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java index 39ddfc0a2e..02029c03f0 100644 --- a/src/test/java/domain/BoardTest.java +++ b/src/test/java/domain/BoardTest.java @@ -11,7 +11,7 @@ import java.util.Map; import java.util.stream.Stream; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.*; class BoardTest { @@ -46,6 +46,7 @@ class BoardTest { // then Piece findPiece = board.findPieceByPosition(to).get(); assertEquals(Type.SOLIDER, findPiece.getType()); + assertFalse(board.isExistPosition(from)); } private static Stream providePiece() { From be6f42f998bb845e2e104af27af9ba81a5cfdf5b Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Fri, 27 Mar 2026 19:38:02 +0900 Subject: [PATCH 36/87] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EA=B3=B5=ED=86=B5=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EC=B6=9C=20=EB=B0=8F=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../strategy/CannonMoveStrategyTest.java | 4 ++-- .../strategy/ChariotMoveStrategyTest.java | 19 +++++++-------- .../strategy/GeneralMoveStrategyTest.java | 23 +++++++++---------- .../strategy/HorseMoveStrategyTest.java | 8 +++---- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/test/java/domain/strategy/CannonMoveStrategyTest.java b/src/test/java/domain/strategy/CannonMoveStrategyTest.java index e0c5781eed..bc2794b48d 100644 --- a/src/test/java/domain/strategy/CannonMoveStrategyTest.java +++ b/src/test/java/domain/strategy/CannonMoveStrategyTest.java @@ -32,7 +32,7 @@ class CannonMoveStrategyTest { @Test @DisplayName("한나라 포의 이동 경로에 다른 기물이 없으면 이동하지 못한다.") - void 포의_이동_경로에_다른_기물이_없으면_이동하지_못한다() { + void 포의_이동_경로에_다른_기물이_없으면_이동_불가() { // given MoveStrategy strategy = new CannonMoveStrategy(); Map boardMapper = new HashMap<>(); @@ -90,7 +90,7 @@ class CannonMoveStrategyTest { @Test @DisplayName("목적지에 포가 있으면 이동하지 않는다.") - void 목적지에_포가_있으면_이동하지_않는다() { + void 목적지에_포가_있으면_이동_불가() { // given MoveStrategy strategy = new CannonMoveStrategy(); Map boardMapper = new HashMap<>(); diff --git a/src/test/java/domain/strategy/ChariotMoveStrategyTest.java b/src/test/java/domain/strategy/ChariotMoveStrategyTest.java index ce1f69eff7..40e05fbf24 100644 --- a/src/test/java/domain/strategy/ChariotMoveStrategyTest.java +++ b/src/test/java/domain/strategy/ChariotMoveStrategyTest.java @@ -4,18 +4,25 @@ import domain.BoardFactory; import domain.vo.Position; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; class ChariotMoveStrategyTest { + MoveStrategy strategy; + Board board; + + @BeforeEach + void setUp() { + strategy = new ChariotMoveStrategy(); + board = BoardFactory.setUp(); + } + @Test @DisplayName("차의 직선 이동 경로에 기물이 없으면 직선 이동한다.") void 차_직선_이동() { // given - ChariotMoveStrategy strategy = new ChariotMoveStrategy(); - Board board = BoardFactory.setUp(); - // when Position from = Position.of(0, 0); Position to = Position.of(2, 0); @@ -28,9 +35,6 @@ class ChariotMoveStrategyTest { @DisplayName("이동 목적지에 같은 팀 기물이 있으면 직선 이동하지 않는다.") void 차_목적지에_같은_팀_기물이_있으면_이동_불가() { // given - ChariotMoveStrategy strategy = new ChariotMoveStrategy(); - Board board = BoardFactory.setUp(); - // when Position from = Position.of(0, 0); Position to = Position.of(3, 0); @@ -43,9 +47,6 @@ class ChariotMoveStrategyTest { @DisplayName("이동 목적지에 다른 팀 기물이 있으면 직선 이동한다.") void 차_목적지에_다른_팀_기물이_있으면_이동_가능() { // given - ChariotMoveStrategy strategy = new ChariotMoveStrategy(); - Board board = BoardFactory.setUp(); - // when Position from = Position.of(3, 0); Position to = Position.of(6, 0); diff --git a/src/test/java/domain/strategy/GeneralMoveStrategyTest.java b/src/test/java/domain/strategy/GeneralMoveStrategyTest.java index e0f7d8f9ed..60041dfa3c 100644 --- a/src/test/java/domain/strategy/GeneralMoveStrategyTest.java +++ b/src/test/java/domain/strategy/GeneralMoveStrategyTest.java @@ -3,6 +3,7 @@ import domain.*; import domain.vo.Position; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -11,14 +12,20 @@ class GeneralMoveStrategyTest { + MoveStrategy strategy; + Map boardMapper; + + @BeforeEach + void setUp() { + strategy = new GeneralMoveStrategy(); + boardMapper = new HashMap<>(); + boardMapper.put(Position.of(1, 4), Piece.of(Team.CHU, Type.GENERAL, strategy)); + } + @Test @DisplayName("궁의 목적지에 기물이 없으면 이동한다.") void 궁_정상_이동() { // given - MoveStrategy strategy = new GeneralMoveStrategy(); - Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(1, 4), Piece.of(Team.CHU, Type.GENERAL, strategy)); - Board board = BoardFactory.of(boardMapper); // when @@ -33,11 +40,7 @@ class GeneralMoveStrategyTest { @DisplayName("궁의 목적지에 같은 팀 기물이 있으면 이동하지 않는다.") void 궁_목적지에_같은_팀_기물이_있으면_이동_불가() { // given - MoveStrategy strategy = new GeneralMoveStrategy(); - Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(1, 4), Piece.of(Team.CHU, Type.GENERAL, strategy)); boardMapper.put(Position.of(1, 5), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); - Board board = BoardFactory.of(boardMapper); // when @@ -53,11 +56,7 @@ class GeneralMoveStrategyTest { @DisplayName("궁의 목적지에 다른 팀 기물이 있으면 이동한다.") void 궁_목적지에_다른_팀_기물이_있으면_정상_이동() { // given - MoveStrategy strategy = new GeneralMoveStrategy(); - Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(1, 4), Piece.of(Team.CHU, Type.GENERAL, strategy)); boardMapper.put(Position.of(1, 5), Piece.of(Team.HAN, Type.SOLIDER, new FixedMoveStrategy())); - Board board = BoardFactory.of(boardMapper); // when diff --git a/src/test/java/domain/strategy/HorseMoveStrategyTest.java b/src/test/java/domain/strategy/HorseMoveStrategyTest.java index b4713f2562..a83113d653 100644 --- a/src/test/java/domain/strategy/HorseMoveStrategyTest.java +++ b/src/test/java/domain/strategy/HorseMoveStrategyTest.java @@ -11,8 +11,8 @@ class HorseMoveStrategyTest { @Test - @DisplayName("초나라 마의 이동 경로에 다른 기물이 없으면 정마 이동한다.") - void 초나라_마_정마_이동() { + @DisplayName("초나라 마의 이동 경로에 다른 기물이 없으면 정상 이동한다.") + void 초나라_마_정상_이동() { // given MoveStrategy strategy = new HorseMoveStrategy(); Board board = BoardFactory.setUp(); @@ -26,8 +26,8 @@ class HorseMoveStrategyTest { } @Test - @DisplayName("한나라 마의 이동 경로에 다른 기물이 없으면 정마 이동한다.") - void 한나라_마_정마_이동() { + @DisplayName("한나라 마의 이동 경로에 다른 기물이 없으면 정상 이동한다.") + void 한나라_마_정상_이동() { // given MoveStrategy strategy = new HorseMoveStrategy(); Board board = BoardFactory.setUp(); From 9a633e491de5478a99f127c56106ca848dcc180f Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Sat, 28 Mar 2026 22:32:17 +0900 Subject: [PATCH 37/87] =?UTF-8?q?feat:=20Board=20=EC=BD=98=EC=86=94=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 10 ++++++++++ src/main/java/JanggiController.java | 15 +++++++++++++++ src/main/java/domain/Board.java | 4 ++++ src/main/java/domain/BoardFactory.java | 11 +++++++---- src/main/java/domain/Piece.java | 8 ++++++++ src/main/java/domain/Team.java | 14 +++++++++++--- src/main/java/domain/Type.java | 26 +++++++++++++++++--------- src/main/java/view/OutputView.java | 24 ++++++++++++++++++++++++ 8 files changed, 96 insertions(+), 16 deletions(-) create mode 100644 src/main/java/Application.java create mode 100644 src/main/java/JanggiController.java create mode 100644 src/main/java/view/OutputView.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 0000000000..2d1ad82dbf --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,10 @@ +import view.OutputView; + +public class Application { + + public static void main(String[] args) { + OutputView outputView = new OutputView(); + JanggiController janggiController = new JanggiController(outputView); + janggiController.run(); + } +} diff --git a/src/main/java/JanggiController.java b/src/main/java/JanggiController.java new file mode 100644 index 0000000000..a1d5c411ef --- /dev/null +++ b/src/main/java/JanggiController.java @@ -0,0 +1,15 @@ +import domain.BoardFactory; +import view.OutputView; + +public class JanggiController { + + private final OutputView outputView; + + public JanggiController(OutputView outputView) { + this.outputView = outputView; + } + + public void run() { + outputView.printBoard(BoardFactory.setUp().getBoard()); + } +} diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index a4094f99cf..0ab0981c03 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -40,4 +40,8 @@ public boolean isAnotherTeam(final Position from, final Position to) { Piece targetPiece = findPieceByPosition(to).get(); return currentPiece.isAnotherTeam(targetPiece); } + + public Map getBoard() { + return Map.copyOf(board); + } } diff --git a/src/main/java/domain/BoardFactory.java b/src/main/java/domain/BoardFactory.java index abf9191355..5d25736124 100644 --- a/src/main/java/domain/BoardFactory.java +++ b/src/main/java/domain/BoardFactory.java @@ -3,8 +3,9 @@ import domain.strategy.*; import domain.vo.Position; -import java.util.HashMap; +import java.util.Comparator; import java.util.Map; +import java.util.TreeMap; public class BoardFactory { @@ -15,7 +16,9 @@ public static Board of(final Map board) { } public static Board setUp() { - Map board = new HashMap<>(); + Map board = new TreeMap<>(Comparator + .comparingInt(Position::getRow).reversed() + .thenComparingInt(Position::getCol)); board.put(Position.of(0, 0),Piece.of(Team.CHU, Type.CHARIOT, new ChariotMoveStrategy())); board.put(Position.of(0, 1),Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); @@ -27,7 +30,7 @@ public static Board setUp() { board.put(Position.of(0, 8),Piece.of(Team.CHU, Type.CHARIOT, new ChariotMoveStrategy())); board.put(Position.of(1, 4),Piece.of(Team.CHU, Type.GENERAL, new GeneralMoveStrategy())); board.put(Position.of(2, 1),Piece.of(Team.CHU, Type.CANNON, new CannonMoveStrategy())); - board.put(Position.of(2, 8),Piece.of(Team.CHU, Type.CANNON, new CannonMoveStrategy())); + board.put(Position.of(2, 7),Piece.of(Team.CHU, Type.CANNON, new CannonMoveStrategy())); board.put(Position.of(3, 0),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); board.put(Position.of(3, 2),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); board.put(Position.of(3, 4),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); @@ -44,7 +47,7 @@ public static Board setUp() { board.put(Position.of(9, 8),Piece.of(Team.HAN, Type.CHARIOT, new ChariotMoveStrategy())); board.put(Position.of(8, 4),Piece.of(Team.HAN, Type.GENERAL, new GeneralMoveStrategy())); board.put(Position.of(7, 1),Piece.of(Team.HAN, Type.CANNON, new CannonMoveStrategy())); - board.put(Position.of(7, 8),Piece.of(Team.HAN, Type.CANNON, new CannonMoveStrategy())); + board.put(Position.of(7, 7),Piece.of(Team.HAN, Type.CANNON, new CannonMoveStrategy())); board.put(Position.of(6, 0),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); board.put(Position.of(6, 2),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); board.put(Position.of(6, 4),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java index 1337bf2c57..5d3e4d2da2 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/Piece.java @@ -26,7 +26,15 @@ public Type getType() { return type; } + public String getTypeName() { + return type.getName(); + } + public Team getTeam() { return team; } + + public String getTeamName() { + return team.getName(); + } } diff --git a/src/main/java/domain/Team.java b/src/main/java/domain/Team.java index b856878a95..87a3bc9c8d 100644 --- a/src/main/java/domain/Team.java +++ b/src/main/java/domain/Team.java @@ -1,8 +1,16 @@ package domain; public enum Team { - CHU, - HAN; + CHU("초"), + HAN("한"); - Team() {} + private final String name; + + Team(final String name) { + this.name = name; + } + + public String getName() { + return name; + } } diff --git a/src/main/java/domain/Type.java b/src/main/java/domain/Type.java index 80562344df..8bd0fa62ec 100644 --- a/src/main/java/domain/Type.java +++ b/src/main/java/domain/Type.java @@ -1,13 +1,21 @@ package domain; public enum Type { - GENERAL, - CHARIOT, - CANNON, - HORSE, - ELEPHANT, - GUARD, - SOLIDER; - - Type() {} + GENERAL("궁"), + CHARIOT("차"), + CANNON("포"), + HORSE("마"), + ELEPHANT("상"), + GUARD("사"), + SOLIDER("졸"); + + private final String name; + + Type(final String name) { + this.name = name; + } + + public String getName() { + return name; + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 0000000000..b3e892cc5d --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,24 @@ +package view; + +import domain.Piece; +import domain.vo.Position; + +import java.util.Map; + +public class OutputView { + + public void printBoard(Map board) { + for (int row = 9; row >= 0; row--) { + for (int col = 0; col <= 8; col++) { + Position position = Position.of(row, col); + if (board.containsKey(position)) { + Piece piece = board.get(position); + System.out.print(piece.getTypeName() + "/" + piece.getTeamName() + " "); + } else { + System.out.print("x "); + } + } + System.out.println(); + } + } +} From 7013f16574c4a7d35e325a6cb6cfcc30c0be7269 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Sat, 28 Mar 2026 22:35:25 +0900 Subject: [PATCH 38/87] =?UTF-8?q?docs:=20=EA=B5=AC=ED=98=84=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EB=AC=B8=EC=84=9C=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 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f843025f43..c5ab81cf1a 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ - [ ] ### 출력 기능 -- [ ] 9 x 10 장기판에 기물을 기본 세팅하여 출력한다. +- [x] 9 x 10 장기판에 기물을 기본 세팅하여 출력한다. - '상마', '상마' 순서로 출력한다. - 기물이 없는 경우 'x' 로 출력한다. From 57d22bd0648e07c5630bef8558a6f2a7be46cf39 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Sat, 28 Mar 2026 23:18:32 +0900 Subject: [PATCH 39/87] =?UTF-8?q?feat:=20=EA=B8=B0=EB=AC=BC=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EB=B0=8F=20=EC=9E=AC=EC=8B=9C=EB=8F=84=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=EA=B0=92=20=EA=B2=80=EC=A6=9D=20=EB=B0=8F=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +-- src/main/java/Application.java | 4 +-- src/main/java/JanggiController.java | 16 ++++++++- src/main/java/view/InputView.java | 52 +++++++++++++++++++++++++++++ src/main/java/view/OutputView.java | 2 ++ 5 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 src/main/java/view/InputView.java diff --git a/README.md b/README.md index c5ab81cf1a..b027433c7e 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ - 기물이 없는 경우 'x' 로 출력한다. ### 핵심 기능 -- [ ] 장기판 초기화 +- [x] 장기판 초기화 - '상마', '상마' 순서로 초기화한다. -- [ ] 기물의 이동을 구현한다. +- [x] 기물의 이동을 구현한다. - 이동 경로에 다른 기물이 존재하지 않을 때만 그대로 이동할 수 있다. - 이동 경로에 같은 팀 기물이 존재한다면 이동하지 못한다. - 이동 경로에 다른 팀 기물이 존재한다면 해당 기물을 잡을 수 있다. diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 2d1ad82dbf..d68927d8b5 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,10 +1,10 @@ +import view.InputView; import view.OutputView; public class Application { public static void main(String[] args) { - OutputView outputView = new OutputView(); - JanggiController janggiController = new JanggiController(outputView); + JanggiController janggiController = new JanggiController(new InputView(), new OutputView()); janggiController.run(); } } diff --git a/src/main/java/JanggiController.java b/src/main/java/JanggiController.java index a1d5c411ef..f514803a31 100644 --- a/src/main/java/JanggiController.java +++ b/src/main/java/JanggiController.java @@ -1,15 +1,29 @@ import domain.BoardFactory; +import domain.vo.Position; +import view.InputView; import view.OutputView; public class JanggiController { + private final InputView inputView; private final OutputView outputView; - public JanggiController(OutputView outputView) { + public JanggiController(InputView inputView, OutputView outputView) { + this.inputView = inputView; this.outputView = outputView; } public void run() { outputView.printBoard(BoardFactory.setUp().getBoard()); + + Position position = inputView.readPosition(); + + while (true) { + if (!inputView.readRetryCommand()) { + break; + } + + inputView.readPosition(); + } } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 0000000000..66832e4fc2 --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,52 @@ +package view; + +import domain.Piece; +import domain.vo.Position; +import java.util.Scanner; + +public class InputView { + + private static final String POSITION_PATTERN = "^\\d+\\s+\\d+$"; + final Scanner scanner = new Scanner(System.in); + + public Position readPosition() { + System.out.println("기물의 위치를 입력해주세요. (예: 0 0)"); + + String input = scanner.nextLine(); + try { + validatePositionFormat(input); + + String[] tokens = input.split(" "); + return Position.of(Integer.parseInt(tokens[0]), Integer.parseInt(tokens[1])); + } catch (Exception e) { + System.out.println(e.getMessage()); + return readPosition(); + } + } + + public Boolean readRetryCommand() { + System.out.println("계속 하시겠습니까?(y/n)"); + + String input = scanner.nextLine(); + try { + validateRetryCommand(input); + } catch (Exception e) { + System.out.println(e.getMessage()); + return readRetryCommand(); + } + + return input.equals("y"); + } + + private void validateRetryCommand(final String input) { + if (!input.equals("y") && !input.equals("n")) { + throw new IllegalArgumentException("[ERROR] y 또는 n만 입력 가능합니다."); + } + } + + private void validatePositionFormat(final String input) { + if (!input.matches(POSITION_PATTERN)) { + throw new IllegalArgumentException("[ERROR] 입력 형식이 잘못되었습니다. '숫자 공백 숫자' 형식이어야 합니다."); + } + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index b3e892cc5d..c0503b61d1 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -20,5 +20,7 @@ public void printBoard(Map board) { } System.out.println(); } + + System.out.println(); } } From ca87635264ebe440a429d4f51e250cb8c0f3beb0 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Sun, 29 Mar 2026 10:19:44 +0900 Subject: [PATCH 40/87] =?UTF-8?q?feat:=20=EA=B8=B0=EB=AC=BC=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EB=B0=8F?= =?UTF-8?q?=20=EC=9D=B4=EB=8F=99=20=EC=9C=84=EC=B9=98=20=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/JanggiController.java | 25 ++++++++++++++++++------- src/main/java/domain/Board.java | 8 +++++++- src/main/java/domain/Piece.java | 5 +++++ src/main/java/view/InputView.java | 17 ++++++++++++++++- src/main/java/view/OutputView.java | 1 + 5 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/main/java/JanggiController.java b/src/main/java/JanggiController.java index f514803a31..3ea4320d8a 100644 --- a/src/main/java/JanggiController.java +++ b/src/main/java/JanggiController.java @@ -1,3 +1,4 @@ +import domain.Board; import domain.BoardFactory; import domain.vo.Position; import view.InputView; @@ -14,16 +15,26 @@ public JanggiController(InputView inputView, OutputView outputView) { } public void run() { - outputView.printBoard(BoardFactory.setUp().getBoard()); + Board board = BoardFactory.setUp(); + outputView.printBoard(board.getBoard()); - Position position = inputView.readPosition(); + movePosition(board); - while (true) { - if (!inputView.readRetryCommand()) { - break; - } + while (inputView.readRetryCommand()) { + movePosition(board); + } + } + + private void movePosition(Board board) { + try { + Position position = inputView.readPosition(); + Position targetPosition = inputView.readTargetPosition(); - inputView.readPosition(); + board.move(position, targetPosition); + outputView.printBoard(board.getBoard()); + } catch (Exception e) { + System.out.println(e.getMessage()); + movePosition(board); } } } diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index 0ab0981c03..9085a8354b 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -18,7 +18,13 @@ public static Board of(final Map board) { } public void move(final Position from, final Position to) { - Piece fromPiece = findPieceByPosition(from).get(); + Piece fromPiece = findPieceByPosition(from) + .orElseThrow(() -> new IllegalArgumentException("[ERROR] 해당 위치에 기물이 존재하지 않습니다.")); + + if (!fromPiece.canMovePiece(from, to, this)) { + throw new IllegalArgumentException("[ERROR] 해당 위치로 움직일 수 없습니다."); + } + board.remove(from); board.put(to, fromPiece); } diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java index 5d3e4d2da2..2edbdec368 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/Piece.java @@ -1,6 +1,7 @@ package domain; import domain.strategy.MoveStrategy; +import domain.vo.Position; public class Piece { @@ -22,6 +23,10 @@ public boolean isAnotherTeam(final Piece anotherPiece) { return this.team != anotherPiece.team; } + public boolean canMovePiece(Position from, Position to, Board board) { + return moveStrategy.canMove(from, to, board); + } + public Type getType() { return type; } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 66832e4fc2..fb0ba7611a 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -10,7 +10,22 @@ public class InputView { final Scanner scanner = new Scanner(System.in); public Position readPosition() { - System.out.println("기물의 위치를 입력해주세요. (예: 0 0)"); + System.out.println("움직일 기물의 위치를 입력해주세요. (예: 0 0)"); + + String input = scanner.nextLine(); + try { + validatePositionFormat(input); + + String[] tokens = input.split(" "); + return Position.of(Integer.parseInt(tokens[0]), Integer.parseInt(tokens[1])); + } catch (Exception e) { + System.out.println(e.getMessage()); + return readPosition(); + } + } + + public Position readTargetPosition() { + System.out.println("기물을 움직일 위치를 입력해주세요. (예: 0 0)"); String input = scanner.nextLine(); try { diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index c0503b61d1..4ae75aeff9 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -8,6 +8,7 @@ public class OutputView { public void printBoard(Map board) { + System.out.println(); for (int row = 9; row >= 0; row--) { for (int col = 0; col <= 8; col++) { Position position = Position.of(row, col); From f099fbad80b10fe4a2682fef3c8250db117bf18a Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Sun, 29 Mar 2026 10:30:26 +0900 Subject: [PATCH 41/87] =?UTF-8?q?feat:=20=EC=BD=98=EC=86=94=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=20=EA=B5=AD=EA=B0=80=EB=B3=84=20=EC=83=89=20=EA=B5=AC?= =?UTF-8?q?=EB=B6=84=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/OutputView.java | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 4ae75aeff9..b250c837ba 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -6,22 +6,34 @@ import java.util.Map; public class OutputView { + private static final String RESET_COLOR = "\u001B[0m"; + private static final String CHU_COLOR = "\u001B[32m"; + private static final String HAN_COLOR = "\u001B[31m"; + + private static final int MAX_COL = 8; + private static final int MAX_ROW = 9; public void printBoard(Map board) { System.out.println(); - for (int row = 9; row >= 0; row--) { - for (int col = 0; col <= 8; col++) { + for (int row = MAX_ROW; row >= 0; row--) { + for (int col = 0; col <= MAX_COL; col++) { Position position = Position.of(row, col); if (board.containsKey(position)) { Piece piece = board.get(position); - System.out.print(piece.getTypeName() + "/" + piece.getTeamName() + " "); + String color = getNationColor(piece); + System.out.print(color + piece.getTypeName() + RESET_COLOR + " "); } else { - System.out.print("x "); + System.out.print("x "); } } System.out.println(); + System.out.println(); } System.out.println(); } + + private static String getNationColor(Piece piece) { + return piece.getTeam().name().equals("CHU") ? CHU_COLOR : HAN_COLOR; + } } From 9ab7557474ae576d796da7b4a081ca59198700ea Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Sun, 29 Mar 2026 10:41:16 +0900 Subject: [PATCH 42/87] =?UTF-8?q?docs:=20README.md=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=EC=82=AC=ED=95=AD=20=EC=B2=B4=ED=81=AC=20?= =?UTF-8?q?=EB=B0=8F=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b027433c7e..eb2f790f35 100644 --- a/README.md +++ b/README.md @@ -4,34 +4,40 @@ ## 구현 기능 내용 ### 입력 기능 -- [ ] +- [x] 움직일 기물의 위치를 입력받는다. +- [x] 기물이 움직일 위치를 입력받는다. ### 출력 기능 - [x] 9 x 10 장기판에 기물을 기본 세팅하여 출력한다. - '상마', '상마' 순서로 출력한다. - 기물이 없는 경우 'x' 로 출력한다. + - 한나라는 빨간색, 초나라는 초록색으로 기물의 종류를 출력한다. ### 핵심 기능 - [x] 장기판 초기화 - '상마', '상마' 순서로 초기화한다. - [x] 기물의 이동을 구현한다. - - 이동 경로에 다른 기물이 존재하지 않을 때만 그대로 이동할 수 있다. - - 이동 경로에 같은 팀 기물이 존재한다면 이동하지 못한다. - - 이동 경로에 다른 팀 기물이 존재한다면 해당 기물을 잡을 수 있다. + - 이동 경로에 기물이 존재하지 않을 때만 그대로 이동할 수 있다. + - 목적지에 같은 팀 기물이 존재한다면 이동하지 못한다. + - 목적지에 다른 팀 기물이 존재한다면 해당 기물을 잡을 수 있다. - 이동할 기물이 포이고 이동 경로에 포를 제외한 다른 기물이 있다면 기물을 넘어서 이동할 수 있다. ### 예외 기능 -- [ ] 장기판을 벗어나면 예외를 발생한다. -- [ ] 졸/병이 후퇴하면 예외를 발생한다. -- [ ] 포가 포를 넘으려고 하면 예외를 발생한다. +- [x] 장기판을 벗어나면 예외를 발생한다. +- [x] 졸/병이 후퇴하면 예외를 발생한다. +- [x] 포가 포를 넘으려고 하면 예외를 발생한다. +- [x] 위치를 입력받을 때, 숫자 공백 숫자 포맷으로 입력하지 않으면 예외를 발생한다. ## 프로그램 흐름도 1. 장기판 초기화 +2. 기물 이동 입력 +3. 기물 이동 후 장기판 출력 +4. 추가 진행 여부 확인 +5. 종료 ## 기물의 이동 규칙 1. 차 - 상하좌우 방향으로 기물이 없는 곳까지 원하는 만큼 이동할 수 있다. -- 궁성 내부에 위치한 경우 대각선 이동도 가능한다. - 이동 경로 중간에 다른 기물이 존재하면 이동할 수 없다. 2. 마 @@ -43,10 +49,10 @@ - 이동 경로 중간에 다른 기물이 존재하면 이동할 수 없다. 4. 사 -- 상하좌우 대각선 방향으로 한 칸 이동할 수 있다. +- 상하좌우 방향으로 한 칸 이동할 수 있다. 5. 궁 -- 상하좌우 대각선 방향으로 한 칸 이동할 수 있다. +- 상하좌우 방향으로 한 칸 이동할 수 있다. 6. 포 - 상하좌우 방향으로 이동할 수 있다. From 5d64486e8d2aa671933611a53e40f21826914d0d Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Sun, 29 Mar 2026 10:59:41 +0900 Subject: [PATCH 43/87] =?UTF-8?q?feat:=20=ED=95=9C=EB=82=98=EB=9D=BC?= =?UTF-8?q?=EC=9D=B8=20=EA=B2=BD=EC=9A=B0=20=EC=A1=B8=20=EB=8C=80=EC=8B=A0?= =?UTF-8?q?=20=EB=B3=91=20=EC=B6=9C=EB=A0=A5=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/OutputView.java | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index b250c837ba..8817ff05c5 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -6,10 +6,16 @@ import java.util.Map; public class OutputView { + private static final String RESET_COLOR = "\u001B[0m"; private static final String CHU_COLOR = "\u001B[32m"; private static final String HAN_COLOR = "\u001B[31m"; + private static final String CHU_SOLDIER = "졸"; + private static final String HAN_SOLDIER = "병"; + private static final String CHU_NATION_NAME = "초"; + private static final String HAN_NATION_NAME = "한"; + private static final int MAX_COL = 8; private static final int MAX_ROW = 9; @@ -20,8 +26,12 @@ public void printBoard(Map board) { Position position = Position.of(row, col); if (board.containsKey(position)) { Piece piece = board.get(position); + String color = getNationColor(piece); - System.out.print(color + piece.getTypeName() + RESET_COLOR + " "); + String type = piece.getTypeName(); + type = matchSoldierName(type, piece); + + System.out.print(color + type + RESET_COLOR + " "); } else { System.out.print("x "); } @@ -34,6 +44,15 @@ public void printBoard(Map board) { } private static String getNationColor(Piece piece) { - return piece.getTeam().name().equals("CHU") ? CHU_COLOR : HAN_COLOR; + if(piece.getTeamName().equals(CHU_NATION_NAME)) + return CHU_COLOR; + return HAN_COLOR; + } + + private String matchSoldierName(String type, Piece piece) { + if (type.equals(CHU_SOLDIER) && piece.getTeamName().equals(HAN_NATION_NAME)) { + type = HAN_SOLDIER; + } + return type; } } From 4b0cffe40e99177369284456ebd13efc5588e2bc Mon Sep 17 00:00:00 2001 From: Huiyeongkim Date: Sun, 29 Mar 2026 11:02:48 +0900 Subject: [PATCH 44/87] =?UTF-8?q?refactor:=20=EC=A1=B8=20=EC=98=A4?= =?UTF-8?q?=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/JanggiController.java | 1 + src/main/java/domain/BoardFactory.java | 20 +++++++++---------- src/main/java/domain/Type.java | 2 +- src/main/java/view/InputView.java | 5 ++++- src/test/java/domain/BoardTest.java | 12 +++++------ .../strategy/CannonMoveStrategyTest.java | 18 ++++++++--------- .../strategy/GeneralMoveStrategyTest.java | 4 ++-- .../strategy/SoldierMoveStrategyTest.java | 14 ++++++------- 8 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/main/java/JanggiController.java b/src/main/java/JanggiController.java index 3ea4320d8a..66a730721e 100644 --- a/src/main/java/JanggiController.java +++ b/src/main/java/JanggiController.java @@ -34,6 +34,7 @@ private void movePosition(Board board) { outputView.printBoard(board.getBoard()); } catch (Exception e) { System.out.println(e.getMessage()); + System.out.println(); movePosition(board); } } diff --git a/src/main/java/domain/BoardFactory.java b/src/main/java/domain/BoardFactory.java index 5d25736124..ccf497d51a 100644 --- a/src/main/java/domain/BoardFactory.java +++ b/src/main/java/domain/BoardFactory.java @@ -31,11 +31,11 @@ public static Board setUp() { board.put(Position.of(1, 4),Piece.of(Team.CHU, Type.GENERAL, new GeneralMoveStrategy())); board.put(Position.of(2, 1),Piece.of(Team.CHU, Type.CANNON, new CannonMoveStrategy())); board.put(Position.of(2, 7),Piece.of(Team.CHU, Type.CANNON, new CannonMoveStrategy())); - board.put(Position.of(3, 0),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); - board.put(Position.of(3, 2),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); - board.put(Position.of(3, 4),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); - board.put(Position.of(3, 6),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); - board.put(Position.of(3, 8),Piece.of(Team.CHU, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(3, 0),Piece.of(Team.CHU, Type.SOLDIER, new SoldierMoveStrategy())); + board.put(Position.of(3, 2),Piece.of(Team.CHU, Type.SOLDIER, new SoldierMoveStrategy())); + board.put(Position.of(3, 4),Piece.of(Team.CHU, Type.SOLDIER, new SoldierMoveStrategy())); + board.put(Position.of(3, 6),Piece.of(Team.CHU, Type.SOLDIER, new SoldierMoveStrategy())); + board.put(Position.of(3, 8),Piece.of(Team.CHU, Type.SOLDIER, new SoldierMoveStrategy())); board.put(Position.of(9, 0),Piece.of(Team.HAN, Type.CHARIOT, new ChariotMoveStrategy())); board.put(Position.of(9, 1),Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); @@ -48,11 +48,11 @@ public static Board setUp() { board.put(Position.of(8, 4),Piece.of(Team.HAN, Type.GENERAL, new GeneralMoveStrategy())); board.put(Position.of(7, 1),Piece.of(Team.HAN, Type.CANNON, new CannonMoveStrategy())); board.put(Position.of(7, 7),Piece.of(Team.HAN, Type.CANNON, new CannonMoveStrategy())); - board.put(Position.of(6, 0),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); - board.put(Position.of(6, 2),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); - board.put(Position.of(6, 4),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); - board.put(Position.of(6, 6),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); - board.put(Position.of(6, 8),Piece.of(Team.HAN, Type.SOLIDER, new SoldierMoveStrategy())); + board.put(Position.of(6, 0),Piece.of(Team.HAN, Type.SOLDIER, new SoldierMoveStrategy())); + board.put(Position.of(6, 2),Piece.of(Team.HAN, Type.SOLDIER, new SoldierMoveStrategy())); + board.put(Position.of(6, 4),Piece.of(Team.HAN, Type.SOLDIER, new SoldierMoveStrategy())); + board.put(Position.of(6, 6),Piece.of(Team.HAN, Type.SOLDIER, new SoldierMoveStrategy())); + board.put(Position.of(6, 8),Piece.of(Team.HAN, Type.SOLDIER, new SoldierMoveStrategy())); return Board.of(board); } diff --git a/src/main/java/domain/Type.java b/src/main/java/domain/Type.java index 8bd0fa62ec..97e75c020d 100644 --- a/src/main/java/domain/Type.java +++ b/src/main/java/domain/Type.java @@ -7,7 +7,7 @@ public enum Type { HORSE("마"), ELEPHANT("상"), GUARD("사"), - SOLIDER("졸"); + SOLDIER("졸"); private final String name; diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index fb0ba7611a..a17052c645 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,7 +1,7 @@ package view; -import domain.Piece; import domain.vo.Position; + import java.util.Scanner; public class InputView { @@ -20,6 +20,7 @@ public Position readPosition() { return Position.of(Integer.parseInt(tokens[0]), Integer.parseInt(tokens[1])); } catch (Exception e) { System.out.println(e.getMessage()); + System.out.println(); return readPosition(); } } @@ -35,6 +36,7 @@ public Position readTargetPosition() { return Position.of(Integer.parseInt(tokens[0]), Integer.parseInt(tokens[1])); } catch (Exception e) { System.out.println(e.getMessage()); + System.out.println(); return readPosition(); } } @@ -47,6 +49,7 @@ public Boolean readRetryCommand() { validateRetryCommand(input); } catch (Exception e) { System.out.println(e.getMessage()); + System.out.println(); return readRetryCommand(); } diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java index 02029c03f0..24846b47d2 100644 --- a/src/test/java/domain/BoardTest.java +++ b/src/test/java/domain/BoardTest.java @@ -33,8 +33,8 @@ class BoardTest { void 기물_이동() { // given Map tempBoard = new HashMap<>(); - tempBoard.put(Position.of(0, 0), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); - tempBoard.put(Position.of(0, 3), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); + tempBoard.put(Position.of(0, 0), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); + tempBoard.put(Position.of(0, 3), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); Board board = Board.of(tempBoard); @@ -45,7 +45,7 @@ class BoardTest { // then Piece findPiece = board.findPieceByPosition(to).get(); - assertEquals(Type.SOLIDER, findPiece.getType()); + assertEquals(Type.SOLDIER, findPiece.getType()); assertFalse(board.isExistPosition(from)); } @@ -58,9 +58,9 @@ private static Stream providePiece() { Arguments.of(0, 8, Type.CHARIOT), Arguments.of(1, 4, Type.GENERAL), Arguments.of(2, 1, Type.CANNON), - Arguments.of(3, 0, Type.SOLIDER), - Arguments.of(3, 4, Type.SOLIDER), - Arguments.of(6, 2, Type.SOLIDER), + Arguments.of(3, 0, Type.SOLDIER), + Arguments.of(3, 4, Type.SOLDIER), + Arguments.of(6, 2, Type.SOLDIER), Arguments.of(7, 1, Type.CANNON), Arguments.of(8, 4, Type.GENERAL), Arguments.of(9, 0, Type.CHARIOT), diff --git a/src/test/java/domain/strategy/CannonMoveStrategyTest.java b/src/test/java/domain/strategy/CannonMoveStrategyTest.java index bc2794b48d..ed2fb79b1a 100644 --- a/src/test/java/domain/strategy/CannonMoveStrategyTest.java +++ b/src/test/java/domain/strategy/CannonMoveStrategyTest.java @@ -18,7 +18,7 @@ class CannonMoveStrategyTest { MoveStrategy strategy = new CannonMoveStrategy(); Map boardMapper = new HashMap<>(); boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); Board board = BoardFactory.of(boardMapper); @@ -55,8 +55,8 @@ class CannonMoveStrategyTest { MoveStrategy strategy = new CannonMoveStrategy(); Map boardMapper = new HashMap<>(); boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); - boardMapper.put(Position.of(4, 1), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); + boardMapper.put(Position.of(4, 1), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); Board board = BoardFactory.of(boardMapper); @@ -75,8 +75,8 @@ class CannonMoveStrategyTest { MoveStrategy strategy = new CannonMoveStrategy(); Map boardMapper = new HashMap<>(); boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); - boardMapper.put(Position.of(5, 1), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); + boardMapper.put(Position.of(5, 1), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); Board board = BoardFactory.of(boardMapper); @@ -95,7 +95,7 @@ class CannonMoveStrategyTest { MoveStrategy strategy = new CannonMoveStrategy(); Map boardMapper = new HashMap<>(); boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.CANNON, strategy)); Board board = BoardFactory.of(boardMapper); @@ -115,8 +115,8 @@ class CannonMoveStrategyTest { MoveStrategy strategy = new CannonMoveStrategy(); Map boardMapper = new HashMap<>(); boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); - boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.SOLIDER, new FixedMoveStrategy())); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); + boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.SOLDIER, new FixedMoveStrategy())); Board board = BoardFactory.of(boardMapper); @@ -136,7 +136,7 @@ class CannonMoveStrategyTest { Map boardMapper = new HashMap<>(); boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); - boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.SOLIDER, new FixedMoveStrategy())); + boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.SOLDIER, new FixedMoveStrategy())); Board board = BoardFactory.of(boardMapper); diff --git a/src/test/java/domain/strategy/GeneralMoveStrategyTest.java b/src/test/java/domain/strategy/GeneralMoveStrategyTest.java index 60041dfa3c..dcbe9b5e75 100644 --- a/src/test/java/domain/strategy/GeneralMoveStrategyTest.java +++ b/src/test/java/domain/strategy/GeneralMoveStrategyTest.java @@ -40,7 +40,7 @@ void setUp() { @DisplayName("궁의 목적지에 같은 팀 기물이 있으면 이동하지 않는다.") void 궁_목적지에_같은_팀_기물이_있으면_이동_불가() { // given - boardMapper.put(Position.of(1, 5), Piece.of(Team.CHU, Type.SOLIDER, new FixedMoveStrategy())); + boardMapper.put(Position.of(1, 5), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); Board board = BoardFactory.of(boardMapper); // when @@ -56,7 +56,7 @@ void setUp() { @DisplayName("궁의 목적지에 다른 팀 기물이 있으면 이동한다.") void 궁_목적지에_다른_팀_기물이_있으면_정상_이동() { // given - boardMapper.put(Position.of(1, 5), Piece.of(Team.HAN, Type.SOLIDER, new FixedMoveStrategy())); + boardMapper.put(Position.of(1, 5), Piece.of(Team.HAN, Type.SOLDIER, new FixedMoveStrategy())); Board board = BoardFactory.of(boardMapper); // when diff --git a/src/test/java/domain/strategy/SoldierMoveStrategyTest.java b/src/test/java/domain/strategy/SoldierMoveStrategyTest.java index dc223c108f..7bee744fc4 100644 --- a/src/test/java/domain/strategy/SoldierMoveStrategyTest.java +++ b/src/test/java/domain/strategy/SoldierMoveStrategyTest.java @@ -17,7 +17,7 @@ class SoldierMoveStrategyTest { // given MoveStrategy strategy = new SoldierMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(3, 4), Piece.of(Team.CHU, Type.SOLIDER, strategy)); + boardMapper.put(Position.of(3, 4), Piece.of(Team.CHU, Type.SOLDIER, strategy)); Board board = BoardFactory.of(boardMapper); @@ -35,8 +35,8 @@ class SoldierMoveStrategyTest { // given MoveStrategy strategy = new SoldierMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(3, 4), Piece.of(Team.CHU, Type.SOLIDER, strategy)); - boardMapper.put(Position.of(4, 4), Piece.of(Team.CHU, Type.SOLIDER, strategy)); + boardMapper.put(Position.of(3, 4), Piece.of(Team.CHU, Type.SOLDIER, strategy)); + boardMapper.put(Position.of(4, 4), Piece.of(Team.CHU, Type.SOLDIER, strategy)); Board board = BoardFactory.of(boardMapper); @@ -55,8 +55,8 @@ class SoldierMoveStrategyTest { // given MoveStrategy strategy = new SoldierMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(3, 4), Piece.of(Team.CHU, Type.SOLIDER, strategy)); - boardMapper.put(Position.of(4, 4), Piece.of(Team.HAN, Type.SOLIDER, strategy)); + boardMapper.put(Position.of(3, 4), Piece.of(Team.CHU, Type.SOLDIER, strategy)); + boardMapper.put(Position.of(4, 4), Piece.of(Team.HAN, Type.SOLDIER, strategy)); Board board = BoardFactory.of(boardMapper); @@ -74,7 +74,7 @@ class SoldierMoveStrategyTest { // given MoveStrategy strategy = new SoldierMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(3, 4), Piece.of(Team.CHU, Type.SOLIDER, strategy)); + boardMapper.put(Position.of(3, 4), Piece.of(Team.CHU, Type.SOLDIER, strategy)); Board board = BoardFactory.of(boardMapper); @@ -92,7 +92,7 @@ class SoldierMoveStrategyTest { // given MoveStrategy strategy = new SoldierMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(6, 4), Piece.of(Team.HAN, Type.SOLIDER, strategy)); + boardMapper.put(Position.of(6, 4), Piece.of(Team.HAN, Type.SOLDIER, strategy)); Board board = BoardFactory.of(boardMapper); From b354278c21cf94410eba6327cef9541b15b6a172 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Mon, 30 Mar 2026 21:48:10 +0900 Subject: [PATCH 45/87] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=EC=96=B4=20?= =?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 1 + src/main/java/JanggiController.java | 41 --------- .../java/controller/JanggiController.java | 71 ++++++++++++++++ src/main/java/domain/BoardFactory.java | 84 ++++++++++++++++++- src/main/java/view/InputView.java | 9 +- src/main/java/view/OutputView.java | 21 ++++- src/test/java/domain/BoardTest.java | 11 +++ src/test/java/domain/FixedMoveStrategy.java | 4 +- 8 files changed, 192 insertions(+), 50 deletions(-) delete mode 100644 src/main/java/JanggiController.java create mode 100644 src/main/java/controller/JanggiController.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index d68927d8b5..528a3ad0d0 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,3 +1,4 @@ +import controller.JanggiController; import view.InputView; import view.OutputView; diff --git a/src/main/java/JanggiController.java b/src/main/java/JanggiController.java deleted file mode 100644 index 66a730721e..0000000000 --- a/src/main/java/JanggiController.java +++ /dev/null @@ -1,41 +0,0 @@ -import domain.Board; -import domain.BoardFactory; -import domain.vo.Position; -import view.InputView; -import view.OutputView; - -public class JanggiController { - - private final InputView inputView; - private final OutputView outputView; - - public JanggiController(InputView inputView, OutputView outputView) { - this.inputView = inputView; - this.outputView = outputView; - } - - public void run() { - Board board = BoardFactory.setUp(); - outputView.printBoard(board.getBoard()); - - movePosition(board); - - while (inputView.readRetryCommand()) { - movePosition(board); - } - } - - private void movePosition(Board board) { - try { - Position position = inputView.readPosition(); - Position targetPosition = inputView.readTargetPosition(); - - board.move(position, targetPosition); - outputView.printBoard(board.getBoard()); - } catch (Exception e) { - System.out.println(e.getMessage()); - System.out.println(); - movePosition(board); - } - } -} diff --git a/src/main/java/controller/JanggiController.java b/src/main/java/controller/JanggiController.java new file mode 100644 index 0000000000..ebd43a0474 --- /dev/null +++ b/src/main/java/controller/JanggiController.java @@ -0,0 +1,71 @@ +package controller; + +import domain.Board; +import domain.BoardFactory; +import domain.Team; +import domain.vo.Position; +import view.InputView; +import view.OutputView; + +public class JanggiController { + + private final InputView inputView; + private final OutputView outputView; + + public JanggiController(InputView inputView, OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + } + + public void run() { + Board board = BoardFactory.setUp(); + String hanArrangement = inputView.readArrangement(Team.HAN); + String chuArrangement = inputView.readArrangement(Team.CHU); + + board = applyArrangement(hanArrangement, board, Team.HAN); + board = applyArrangement(chuArrangement, board, Team.CHU); + + outputView.printBoard(board.getBoard()); + + int turnCount = 0; + movePosition(board, turnCount); + + while (inputView.readRetryCommand()) { + movePosition(board, turnCount); + } + } + + private static Board applyArrangement(String arrangement, Board board, Team team) { + if (arrangement.equals("1")) { + return BoardFactory.setUpLeftElephantFormation(board.getBoard(), team); + } + if (arrangement.equals("2")) { + return BoardFactory.setUpRightElephantFormation(board.getBoard(), team); + } + if (arrangement.equals("3")) { + return BoardFactory.setUpInnerElephantFormation(board.getBoard(), team); + } + if (arrangement.equals("4")) { + return BoardFactory.setUpOuterElephantFormation(board.getBoard(), team); + } + return board; + } + + private void movePosition(Board board, int turnCount) { + try { + outputView.printCurrentTurn(turnCount); + turnCount += 1; + + Position position = inputView.readPosition(); + Position targetPosition = inputView.readTargetPosition(); + + board.move(position, targetPosition); + outputView.printBoard(board.getBoard()); + } catch (Exception e) { + System.out.println(e.getMessage()); + System.out.println(); + turnCount -= 1; + movePosition(board, turnCount); + } + } +} diff --git a/src/main/java/domain/BoardFactory.java b/src/main/java/domain/BoardFactory.java index ccf497d51a..da65fe97cc 100644 --- a/src/main/java/domain/BoardFactory.java +++ b/src/main/java/domain/BoardFactory.java @@ -9,16 +9,94 @@ public class BoardFactory { + private static final Comparator POSITION_COMPARATOR = Comparator + .comparingInt(Position::getRow).reversed() + .thenComparingInt(Position::getCol); + private BoardFactory() {} public static Board of(final Map board) { return Board.of(board); } + public static Board setUpLeftElephantFormation(Map initialBoard, Team team) { + Map board = new TreeMap<>(POSITION_COMPARATOR); + board.putAll(initialBoard); + if (team == Team.CHU) { + board.put(Position.of(0, 1), Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(0, 6), Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(0, 2), Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(0, 7), Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); + } + if (team == Team.HAN) { + board.put(Position.of(9, 2), Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(9, 7), Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(9, 1), Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(9, 6), Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); + } + + return Board.of(board); + } + + public static Board setUpRightElephantFormation(Map initialBoard, Team team) { + Map board = new TreeMap<>(POSITION_COMPARATOR); + board.putAll(initialBoard); + if (team == Team.CHU) { + board.put(Position.of(0, 2), Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(0, 7), Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(0, 1), Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(0, 6), Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); + } + if (team == Team.HAN) { + board.put(Position.of(9, 1), Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(9, 6), Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(9, 2), Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(9, 7), Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); + } + + return Board.of(board); + } + + public static Board setUpInnerElephantFormation(Map initialBoard, Team team) { + Map board = new TreeMap<>(POSITION_COMPARATOR); + board.putAll(initialBoard); + if (team == Team.CHU) { + board.put(Position.of(0, 2), Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(0, 6), Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(0, 1), Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(0, 7), Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); + } + if (team == Team.HAN) { + board.put(Position.of(9, 2), Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(9, 6), Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(9, 1), Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(9, 7), Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); + } + + return Board.of(board); + } + + public static Board setUpOuterElephantFormation(Map initialBoard, Team team) { + Map board = new TreeMap<>(POSITION_COMPARATOR); + board.putAll(initialBoard); + if (team == Team.CHU) { + board.put(Position.of(0, 1), Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(0, 7), Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(0, 2), Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(0, 6), Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); + } + if (team == Team.HAN) { + board.put(Position.of(9, 1), Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(9, 7), Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); + board.put(Position.of(9, 2), Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(9, 6), Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); + } + + return Board.of(board); + } + public static Board setUp() { - Map board = new TreeMap<>(Comparator - .comparingInt(Position::getRow).reversed() - .thenComparingInt(Position::getCol)); + Map board = new TreeMap<>(POSITION_COMPARATOR); board.put(Position.of(0, 0),Piece.of(Team.CHU, Type.CHARIOT, new ChariotMoveStrategy())); board.put(Position.of(0, 1),Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index a17052c645..a763284d34 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,5 +1,6 @@ package view; +import domain.Team; import domain.vo.Position; import java.util.Scanner; @@ -8,7 +9,7 @@ public class InputView { private static final String POSITION_PATTERN = "^\\d+\\s+\\d+$"; final Scanner scanner = new Scanner(System.in); - + public Position readPosition() { System.out.println("움직일 기물의 위치를 입력해주세요. (예: 0 0)"); @@ -56,6 +57,12 @@ public Boolean readRetryCommand() { return input.equals("y"); } + public String readArrangement(Team team) { + System.out.println(team.getName() + "나라의 판차림 방식을 선택해주세요.(1: 상마상마, 2: 마상마상, 3: 마상상마, 4: 상마마상"); + + return scanner.nextLine(); + } + private void validateRetryCommand(final String input) { if (!input.equals("y") && !input.equals("n")) { throw new IllegalArgumentException("[ERROR] y 또는 n만 입력 가능합니다."); diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 8817ff05c5..1af9f571e0 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -21,7 +21,14 @@ public class OutputView { public void printBoard(Map board) { System.out.println(); + System.out.print(" "); + for (int col = 0; col <= MAX_COL; col++) { + System.out.print(col + " "); + } + System.out.println(); + for (int row = MAX_ROW; row >= 0; row--) { + System.out.print(row + " "); for (int col = 0; col <= MAX_COL; col++) { Position position = Position.of(row, col); if (board.containsKey(position)) { @@ -31,18 +38,26 @@ public void printBoard(Map board) { String type = piece.getTypeName(); type = matchSoldierName(type, piece); - System.out.print(color + type + RESET_COLOR + " "); + System.out.print(color + type + RESET_COLOR + " "); } else { - System.out.print("x "); + System.out.print("· "); } } System.out.println(); - System.out.println(); } System.out.println(); } + public void printCurrentTurn(int turnCount) { + if (turnCount % 2 == 0) { + System.out.println("현재는 한나라 차례입니다."); + } + if (turnCount % 2 != 0) { + System.out.println("현재는 초나라 차례입니다."); + } + } + private static String getNationColor(Piece piece) { if(piece.getTeamName().equals(CHU_NATION_NAME)) return CHU_COLOR; diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java index 24846b47d2..4cc6ab1a95 100644 --- a/src/test/java/domain/BoardTest.java +++ b/src/test/java/domain/BoardTest.java @@ -28,6 +28,17 @@ class BoardTest { assertEquals(expected, piece.getType()); } + @Test + @DisplayName("판차림을 선택해도 예외가 발생하지 않는다.") + void 판차림_선택_예외_테스트() { + // given + Board board = BoardFactory.setUp(); + + // when & then + assertDoesNotThrow(() -> BoardFactory.setUpOuterElephantFormation(board.getBoard(), Team.HAN)); + assertDoesNotThrow(() -> BoardFactory.setUpLeftElephantFormation(board.getBoard(), Team.CHU)); + } + @Test @DisplayName("기물의 이동 경로에 다른 기물이 없으면 이동한다.") void 기물_이동() { diff --git a/src/test/java/domain/FixedMoveStrategy.java b/src/test/java/domain/FixedMoveStrategy.java index 63d1a9ea55..c880828175 100644 --- a/src/test/java/domain/FixedMoveStrategy.java +++ b/src/test/java/domain/FixedMoveStrategy.java @@ -5,8 +5,8 @@ public class FixedMoveStrategy implements MoveStrategy { - @Override + @Override public boolean canMove(Position from, Position to, Board board) { - return false; + return true; } } From 14f7a2c3c193c8427bcd6d46eea6276bb9aa8b92 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 1 Apr 2026 14:36:51 +0900 Subject: [PATCH 46/87] =?UTF-8?q?feat:=20=EC=9C=84=EC=B9=98=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EB=A9=94=EC=86=8C=EB=93=9C=EC=97=90=EC=84=9C=20tur?= =?UTF-8?q?nCount=EB=A5=BC=20=EB=B0=98=ED=99=98=ED=95=98=EC=97=AC=20?= =?UTF-8?q?=EC=9E=AC=ED=95=A0=EB=8B=B9=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/JanggiController.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/controller/JanggiController.java b/src/main/java/controller/JanggiController.java index ebd43a0474..e6d156db98 100644 --- a/src/main/java/controller/JanggiController.java +++ b/src/main/java/controller/JanggiController.java @@ -28,10 +28,10 @@ public void run() { outputView.printBoard(board.getBoard()); int turnCount = 0; - movePosition(board, turnCount); + turnCount = movePosition(board, turnCount); while (inputView.readRetryCommand()) { - movePosition(board, turnCount); + turnCount = movePosition(board, turnCount); } } @@ -51,21 +51,21 @@ private static Board applyArrangement(String arrangement, Board board, Team team return board; } - private void movePosition(Board board, int turnCount) { + private int movePosition(Board board, int turnCount) { try { outputView.printCurrentTurn(turnCount); - turnCount += 1; Position position = inputView.readPosition(); Position targetPosition = inputView.readTargetPosition(); board.move(position, targetPosition); outputView.printBoard(board.getBoard()); + return turnCount += 1; } catch (Exception e) { System.out.println(e.getMessage()); System.out.println(); - turnCount -= 1; movePosition(board, turnCount); } + return turnCount; } } From 5fcf7c36a060a160ab549cf71745ba495c17a23f Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 1 Apr 2026 15:22:45 +0900 Subject: [PATCH 47/87] =?UTF-8?q?test:=20=EC=82=AC=EC=9D=98=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9D=B4=EB=8F=99=20?= =?UTF-8?q?=EC=A2=8C=ED=91=9C=EA=B0=92=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../strategy/GuardMoveStrategyTest.java | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/test/java/domain/strategy/GuardMoveStrategyTest.java b/src/test/java/domain/strategy/GuardMoveStrategyTest.java index 2266400f68..226fe0bb9d 100644 --- a/src/test/java/domain/strategy/GuardMoveStrategyTest.java +++ b/src/test/java/domain/strategy/GuardMoveStrategyTest.java @@ -2,7 +2,12 @@ import domain.Board; import domain.BoardFactory; +import domain.Piece; +import domain.Team; +import domain.Type; import domain.vo.Position; +import java.util.LinkedHashMap; +import java.util.Map; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -28,15 +33,18 @@ class GuardMoveStrategyTest { @DisplayName("사의 목적지에 같은 팀 기물이 있으면 이동하지 않는다.") void 사_목적지에_같은_팀_기물이_있으면_이동_불가() { // given - MoveStrategy strategy = new GuardMoveStrategy(); - Board board = BoardFactory.setUp(); + MoveStrategy guardMoveStrategy = new GuardMoveStrategy(); + Map PositionPiecePair = new LinkedHashMap<>(); + PositionPiecePair.put(Position.of(0, 3), Piece.of(Team.CHU, Type.GUARD, guardMoveStrategy)); + PositionPiecePair.put(Position.of(0, 2), Piece.of(Team.CHU, Type.GUARD, guardMoveStrategy)); + Board board = Board.of(PositionPiecePair); // when Position position = Position.of(0, 3); Position targetPosition = Position.of(0, 2); // then - Assertions.assertFalse(strategy.canMove(position, targetPosition, board)); + Assertions.assertFalse(guardMoveStrategy.canMove(position, targetPosition, board)); } @@ -44,14 +52,18 @@ class GuardMoveStrategyTest { @DisplayName("사의 목적지에 다른 팀 기물이 있으면 이동한다.") void 사_목적지에_다른_팀_기물이_있으면_정상_이동() { // given - MoveStrategy strategy = new GuardMoveStrategy(); - Board board = BoardFactory.setUp(); + MoveStrategy guardMoveStrategy = new GuardMoveStrategy(); + MoveStrategy soldierMoveStrategy = new SoldierMoveStrategy(); + Map PositionPiecePair = new LinkedHashMap<>(); + PositionPiecePair.put(Position.of(0, 3), Piece.of(Team.CHU, Type.GUARD, guardMoveStrategy)); + PositionPiecePair.put(Position.of(1, 3), Piece.of(Team.HAN, Type.SOLDIER, soldierMoveStrategy)); + Board board = Board.of(PositionPiecePair); // when Position position = Position.of(0, 3); - Position targetPosition = Position.of(6, 0); + Position targetPosition = Position.of(1, 3); // then - Assertions.assertTrue(strategy.canMove(position, targetPosition, board)); + Assertions.assertTrue(guardMoveStrategy.canMove(position, targetPosition, board)); } } From 9aabd6059b16ec4df5ec4841866bf5e2eaff8a4e Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 1 Apr 2026 16:23:53 +0900 Subject: [PATCH 48/87] =?UTF-8?q?feat:=20=EC=82=AC=EC=9D=98=20=EB=8C=80?= =?UTF-8?q?=EA=B0=81=EC=84=A0,=20=EC=9E=A5=EA=B1=B0=EB=A6=AC=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EC=A0=9C=ED=95=9C=20=EC=A1=B0=EA=B1=B4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ src/main/java/domain/strategy/GuardMoveStrategy.java | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/README.md b/README.md index eb2f790f35..e9fa6ae3ae 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,8 @@ 5. 종료 ## 기물의 이동 규칙 +(사이클1에서는 궁성은 구현하지 않기 때문에 대각선 이동은 사이클 2에서 진행한다.) + 1. 차 - 상하좌우 방향으로 기물이 없는 곳까지 원하는 만큼 이동할 수 있다. - 이동 경로 중간에 다른 기물이 존재하면 이동할 수 없다. diff --git a/src/main/java/domain/strategy/GuardMoveStrategy.java b/src/main/java/domain/strategy/GuardMoveStrategy.java index e67045819d..e492f49af4 100644 --- a/src/main/java/domain/strategy/GuardMoveStrategy.java +++ b/src/main/java/domain/strategy/GuardMoveStrategy.java @@ -7,6 +7,10 @@ public class GuardMoveStrategy implements MoveStrategy { @Override public boolean canMove(final Position from, final Position to, final Board board) { + if (Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) != 1) { + return false; + } + if (from.getRow() == to.getRow() && Math.abs(from.getCol() - to.getCol()) != 1) { return false; } From 707e12ff42d58a843cd3c77c8e485282c029d677 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 1 Apr 2026 16:32:50 +0900 Subject: [PATCH 49/87] =?UTF-8?q?feat:=20=EC=A1=B8=20=EB=8C=80=EA=B0=81?= =?UTF-8?q?=EC=84=A0=20=EC=9D=B4=EB=8F=99=20=EC=A0=9C=ED=95=9C=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/SoldierMoveStrategy.java | 8 +++++ .../strategy/GuardMoveStrategyTest.java | 29 +++++++++++++++---- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/main/java/domain/strategy/SoldierMoveStrategy.java b/src/main/java/domain/strategy/SoldierMoveStrategy.java index 2a4d63f9b7..96cae1bba9 100644 --- a/src/main/java/domain/strategy/SoldierMoveStrategy.java +++ b/src/main/java/domain/strategy/SoldierMoveStrategy.java @@ -18,6 +18,10 @@ public boolean canMove(final Position from, final Position to, final Board board return true; } + if (!board.isExistPosition(to)) { + return true; + } + return false; } @@ -35,6 +39,10 @@ private boolean isWithdraw(final Position from, final Position to, final Board b } private boolean isNotCorrectPath(final Position from, final Position to) { + if (Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) != 1) { + return true; + } + if (from.getRow() == to.getRow() && Math.abs(from.getCol() - to.getCol()) != 1) { return true; } diff --git a/src/test/java/domain/strategy/GuardMoveStrategyTest.java b/src/test/java/domain/strategy/GuardMoveStrategyTest.java index 226fe0bb9d..6ec0241346 100644 --- a/src/test/java/domain/strategy/GuardMoveStrategyTest.java +++ b/src/test/java/domain/strategy/GuardMoveStrategyTest.java @@ -39,10 +39,10 @@ class GuardMoveStrategyTest { PositionPiecePair.put(Position.of(0, 2), Piece.of(Team.CHU, Type.GUARD, guardMoveStrategy)); Board board = Board.of(PositionPiecePair); - // when Position position = Position.of(0, 3); Position targetPosition = Position.of(0, 2); + // when // then Assertions.assertFalse(guardMoveStrategy.canMove(position, targetPosition, board)); } @@ -54,16 +54,33 @@ class GuardMoveStrategyTest { // given MoveStrategy guardMoveStrategy = new GuardMoveStrategy(); MoveStrategy soldierMoveStrategy = new SoldierMoveStrategy(); - Map PositionPiecePair = new LinkedHashMap<>(); - PositionPiecePair.put(Position.of(0, 3), Piece.of(Team.CHU, Type.GUARD, guardMoveStrategy)); - PositionPiecePair.put(Position.of(1, 3), Piece.of(Team.HAN, Type.SOLDIER, soldierMoveStrategy)); - Board board = Board.of(PositionPiecePair); + Map positionPiecePair = new LinkedHashMap<>(); + positionPiecePair.put(Position.of(0, 3), Piece.of(Team.CHU, Type.GUARD, guardMoveStrategy)); + positionPiecePair.put(Position.of(1, 3), Piece.of(Team.HAN, Type.SOLDIER, soldierMoveStrategy)); + Board board = Board.of(positionPiecePair); - // when Position position = Position.of(0, 3); Position targetPosition = Position.of(1, 3); + // when // then Assertions.assertTrue(guardMoveStrategy.canMove(position, targetPosition, board)); } + + @Test + @DisplayName("사가 궁성 외부 대각선으로 이동하면 예외를 발생한다.") + void 사_궁성_밖_대각선_이동_불가() { + // given + MoveStrategy guardMoveStrategy = new GuardMoveStrategy(); + Map positionPiecePair = new LinkedHashMap<>(); + positionPiecePair.put(Position.of(0, 3), Piece.of(Team.CHU, Type.GUARD, guardMoveStrategy)); + Board board = Board.of(positionPiecePair); + + Position position = Position.of(0, 3); + Position targetPosition = Position.of(1, 2); + + // when + // then + Assertions.assertFalse(guardMoveStrategy.canMove(position, targetPosition, board)); + } } From 7df921357f0f965c649286fc97347a11542e683e Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 1 Apr 2026 17:06:48 +0900 Subject: [PATCH 50/87] =?UTF-8?q?feat:=20=EA=B0=81=20=EB=82=98=EB=9D=BC?= =?UTF-8?q?=EC=9D=98=20=EC=B0=A8=EB=A1=80=EC=97=90=20=EC=9E=90=EC=8B=A0?= =?UTF-8?q?=EC=9D=98=20=EB=82=98=EB=9D=BC=20=EA=B8=B0=EB=AC=BC=EB=A7=8C=20?= =?UTF-8?q?=EC=9B=80=EC=A7=81=EC=9D=BC=20=EC=88=98=20=EC=9E=88=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/JanggiController.java | 6 +++--- src/main/java/domain/Board.java | 6 +++++- src/main/java/domain/Team.java | 7 +++++++ src/test/java/domain/BoardTest.java | 2 +- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/main/java/controller/JanggiController.java b/src/main/java/controller/JanggiController.java index e6d156db98..ea8bb1d79b 100644 --- a/src/main/java/controller/JanggiController.java +++ b/src/main/java/controller/JanggiController.java @@ -58,14 +58,14 @@ private int movePosition(Board board, int turnCount) { Position position = inputView.readPosition(); Position targetPosition = inputView.readTargetPosition(); - board.move(position, targetPosition); + Team currentTeam = Team.from(turnCount); + board.move(position, targetPosition, currentTeam); outputView.printBoard(board.getBoard()); return turnCount += 1; } catch (Exception e) { System.out.println(e.getMessage()); System.out.println(); - movePosition(board, turnCount); + return movePosition(board, turnCount); } - return turnCount; } } diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index 9085a8354b..2321684172 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -17,10 +17,14 @@ public static Board of(final Map board) { return new Board(board); } - public void move(final Position from, final Position to) { + public void move(final Position from, final Position to, final Team currentTeam) { Piece fromPiece = findPieceByPosition(from) .orElseThrow(() -> new IllegalArgumentException("[ERROR] 해당 위치에 기물이 존재하지 않습니다.")); + if (fromPiece.getTeam() != currentTeam) { + throw new IllegalArgumentException("[ERROR] 상대편의 기물은 움직일 수 없습니다."); + } + if (!fromPiece.canMovePiece(from, to, this)) { throw new IllegalArgumentException("[ERROR] 해당 위치로 움직일 수 없습니다."); } diff --git a/src/main/java/domain/Team.java b/src/main/java/domain/Team.java index 87a3bc9c8d..6747774ca1 100644 --- a/src/main/java/domain/Team.java +++ b/src/main/java/domain/Team.java @@ -13,4 +13,11 @@ public enum Team { public String getName() { return name; } + + public static Team from(final int turnCount) { + if (turnCount % 2 == 0) { + return HAN; + } + return CHU; + } } diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java index 4cc6ab1a95..4f21e4ca4d 100644 --- a/src/test/java/domain/BoardTest.java +++ b/src/test/java/domain/BoardTest.java @@ -52,7 +52,7 @@ class BoardTest { // when Position from = Position.of(0, 0); Position to = Position.of(3, 0); - board.move(from, to); + board.move(from, to, Team.CHU); // then Piece findPiece = board.findPieceByPosition(to).get(); From a6789f05b76afdc39dc3b3adddd118cfe8a77752 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 1 Apr 2026 17:19:58 +0900 Subject: [PATCH 51/87] =?UTF-8?q?fix:=20=EA=B8=B0=EB=AC=BC=EC=9D=84=20?= =?UTF-8?q?=EC=9B=80=EC=A7=81=EC=9D=BC=20=EC=9C=84=EC=B9=98=EB=A5=BC=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=ED=95=98=EB=8B=A4=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=8B=9C=20=EB=8B=A4=EC=8B=9C=20=EA=B7=B8=20=EC=9C=84=EC=B9=98?= =?UTF-8?q?=EB=B6=80=ED=84=B0=20=EC=9E=85=EB=A0=A5=EB=B0=9B=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/InputView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index a763284d34..e601c50a7c 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -38,7 +38,7 @@ public Position readTargetPosition() { } catch (Exception e) { System.out.println(e.getMessage()); System.out.println(); - return readPosition(); + return readTargetPosition(); } } From 6d6c76ce3e2dcbf0d01a6850f41c9de9bf39da7d Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 1 Apr 2026 19:47:13 +0900 Subject: [PATCH 52/87] =?UTF-8?q?fix:=20=EB=A7=88=EC=99=80=20=EC=83=81?= =?UTF-8?q?=EC=9D=98=20=EC=9E=98=EB=AA=BB=EB=90=9C=20=EC=9D=B4=EB=8F=99=20?= =?UTF-8?q?=EA=B7=9C=EC=B9=99=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/domain/strategy/ElephantMoveStrategy.java | 11 ++++------- src/main/java/domain/strategy/HorseMoveStrategy.java | 11 +++-------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/main/java/domain/strategy/ElephantMoveStrategy.java b/src/main/java/domain/strategy/ElephantMoveStrategy.java index 244b87cedd..e989bd4f43 100644 --- a/src/main/java/domain/strategy/ElephantMoveStrategy.java +++ b/src/main/java/domain/strategy/ElephantMoveStrategy.java @@ -32,12 +32,9 @@ public boolean canMove(final Position from, final Position to, final Board board } private boolean isNotCorrectPath(final Position from, final Position to) { - if (Math.abs(from.getRow() - to.getRow()) == 2 && Math.abs(from.getCol() - to.getCol()) != 3) { - return true; - } - if (Math.abs(from.getRow() - to.getRow()) == 3 && Math.abs(from.getCol() - to.getCol()) != 2) { - return true; - } - return false; + int rowDiff = Math.abs(from.getRow() - to.getRow()); + int colDiff = Math.abs(from.getCol() - to.getCol()); + + return !((rowDiff == 3 && colDiff == 2) || (rowDiff == 2 && colDiff == 3)); } } diff --git a/src/main/java/domain/strategy/HorseMoveStrategy.java b/src/main/java/domain/strategy/HorseMoveStrategy.java index 6a29420999..31175147c7 100644 --- a/src/main/java/domain/strategy/HorseMoveStrategy.java +++ b/src/main/java/domain/strategy/HorseMoveStrategy.java @@ -24,14 +24,9 @@ public boolean canMove(final Position from, final Position to, final Board board } private boolean isNotCorrectPath(final Position from, final Position to) { - if (Math.abs(from.getRow() - to.getRow()) == 1 && Math.abs(from.getCol() - to.getCol()) != 2) { - return true; - } - - if (Math.abs(from.getRow() - to.getRow()) == 2 && Math.abs(from.getCol() - to.getCol()) != 1) { - return true; - } + int rowDiff = Math.abs(from.getRow() - to.getRow()); + int colDiff = Math.abs(from.getCol() - to.getCol()); - return false; + return !((rowDiff == 1 && colDiff == 2) || (rowDiff == 2 && colDiff == 1)); } } From 5703b5d24ebddcc96bb43cd5e75dc82f155007bb Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 1 Apr 2026 19:57:42 +0900 Subject: [PATCH 53/87] =?UTF-8?q?refactor:=20=EA=B8=B0=EB=AC=BC=EC=9D=98?= =?UTF-8?q?=20=EC=9D=B4=EB=8F=99=20=EC=8B=9C=20=EC=9E=85=EB=A0=A5=EC=9D=84?= =?UTF-8?q?=20=EC=9E=AC=EA=B7=80=EC=97=90=EC=84=9C=20=EB=B0=98=EB=B3=B5?= =?UTF-8?q?=EB=AC=B8=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/JanggiController.java | 25 ++++++++++--------- src/main/java/view/InputView.java | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/main/java/controller/JanggiController.java b/src/main/java/controller/JanggiController.java index ea8bb1d79b..a99ea440f0 100644 --- a/src/main/java/controller/JanggiController.java +++ b/src/main/java/controller/JanggiController.java @@ -52,20 +52,21 @@ private static Board applyArrangement(String arrangement, Board board, Team team } private int movePosition(Board board, int turnCount) { - try { - outputView.printCurrentTurn(turnCount); + while (true) { + try { + outputView.printCurrentTurn(turnCount); - Position position = inputView.readPosition(); - Position targetPosition = inputView.readTargetPosition(); + Position position = inputView.readPosition(); + Position targetPosition = inputView.readTargetPosition(); - Team currentTeam = Team.from(turnCount); - board.move(position, targetPosition, currentTeam); - outputView.printBoard(board.getBoard()); - return turnCount += 1; - } catch (Exception e) { - System.out.println(e.getMessage()); - System.out.println(); - return movePosition(board, turnCount); + Team currentTeam = Team.from(turnCount); + board.move(position, targetPosition, currentTeam); + outputView.printBoard(board.getBoard()); + return turnCount += 1; + } catch (Exception e) { + System.out.println(e.getMessage()); + System.out.println(); + } } } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index e601c50a7c..11dfa778e6 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -58,7 +58,7 @@ public Boolean readRetryCommand() { } public String readArrangement(Team team) { - System.out.println(team.getName() + "나라의 판차림 방식을 선택해주세요.(1: 상마상마, 2: 마상마상, 3: 마상상마, 4: 상마마상"); + System.out.println(team.getName() + "나라의 판차림 방식을 선택해주세요.(1: 상마상마, 2: 마상마상, 3: 마상상마, 4: 상마마상)"); return scanner.nextLine(); } From 13d9085f3344318206f716c2239e68c2fd545766 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 1 Apr 2026 20:47:50 +0900 Subject: [PATCH 54/87] =?UTF-8?q?feat:=20=EC=83=81=EC=B0=A8=EB=A6=BC=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20=EC=8B=9C=20enum=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EB=AC=B8=EC=9E=90=EC=97=B4=EB=A1=9C=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=EB=B0=8F=20?= =?UTF-8?q?=EC=9E=AC=EC=9E=85=EB=A0=A5=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/JanggiController.java | 44 +++++++++++++++---- src/main/java/domain/Formation.java | 24 ++++++++++ src/main/java/view/InputView.java | 2 +- 3 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 src/main/java/domain/Formation.java diff --git a/src/main/java/controller/JanggiController.java b/src/main/java/controller/JanggiController.java index a99ea440f0..1bfc2c393f 100644 --- a/src/main/java/controller/JanggiController.java +++ b/src/main/java/controller/JanggiController.java @@ -2,6 +2,7 @@ import domain.Board; import domain.BoardFactory; +import domain.Formation; import domain.Team; import domain.vo.Position; import view.InputView; @@ -19,11 +20,8 @@ public JanggiController(InputView inputView, OutputView outputView) { public void run() { Board board = BoardFactory.setUp(); - String hanArrangement = inputView.readArrangement(Team.HAN); - String chuArrangement = inputView.readArrangement(Team.CHU); - - board = applyArrangement(hanArrangement, board, Team.HAN); - board = applyArrangement(chuArrangement, board, Team.CHU); + board = readHanFormation(board); + board = readChuFormation(board); outputView.printBoard(board.getBoard()); @@ -35,19 +33,47 @@ public void run() { } } + private Board readChuFormation(Board board) { + while (true) { + try { + String chuArrangement = inputView.readArrangement(Team.CHU); + board = applyArrangement(chuArrangement, board, Team.CHU); + return board; + } catch (Exception e) { + System.out.println(e.getMessage()); + System.out.println(); + } + } + } + + private Board readHanFormation(Board board) { + while (true) { + try { + String hanArrangement = inputView.readArrangement(Team.HAN); + board = applyArrangement(hanArrangement, board, Team.HAN); + + return board; + } catch (Exception e) { + System.out.println(e.getMessage()); + System.out.println(); + } + } + } + private static Board applyArrangement(String arrangement, Board board, Team team) { - if (arrangement.equals("1")) { + if (Formation.from(arrangement) == Formation.SANG_MA_SANG_MA) { return BoardFactory.setUpLeftElephantFormation(board.getBoard(), team); } - if (arrangement.equals("2")) { + if (Formation.from(arrangement) == Formation.MA_SANG_MA_SANG) { return BoardFactory.setUpRightElephantFormation(board.getBoard(), team); } - if (arrangement.equals("3")) { + if (Formation.from(arrangement) == Formation.MA_SANG_SANG_MA) { return BoardFactory.setUpInnerElephantFormation(board.getBoard(), team); } - if (arrangement.equals("4")) { + if (Formation.from(arrangement) == Formation.SANG_MA_MA_SANG) { return BoardFactory.setUpOuterElephantFormation(board.getBoard(), team); } + return board; } diff --git a/src/main/java/domain/Formation.java b/src/main/java/domain/Formation.java new file mode 100644 index 0000000000..9d516bcd45 --- /dev/null +++ b/src/main/java/domain/Formation.java @@ -0,0 +1,24 @@ +package domain; + +import java.util.Arrays; + +public enum Formation { + + MA_SANG_MA_SANG("마상마상"), + SANG_MA_SANG_MA("상마상마"), + MA_SANG_SANG_MA("마상상마"), + SANG_MA_MA_SANG("상마마상"); + + private final String koreanName; + + Formation(String koreanName) { + this.koreanName = koreanName; + } + + public static Formation from(String input) { + return Arrays.stream(values()) + .filter(formation -> formation.koreanName.equals(input)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("[ERROR] 잘못된 진형 입력입니다.")); + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 11dfa778e6..1af5a84077 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -58,7 +58,7 @@ public Boolean readRetryCommand() { } public String readArrangement(Team team) { - System.out.println(team.getName() + "나라의 판차림 방식을 선택해주세요.(1: 상마상마, 2: 마상마상, 3: 마상상마, 4: 상마마상)"); + System.out.println(team.getName() + "나라의 판차림 방식을 선택해주세요.(상마상마, 마상마상, 마상상마, 상마마상)"); return scanner.nextLine(); } From 21c418a0f4ea7a546c660eb1ee52c448e47da2ca Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Thu, 2 Apr 2026 14:40:52 +0900 Subject: [PATCH 55/87] =?UTF-8?q?refactor:=20=EA=B8=B0=EB=AC=BC=EC=9D=98?= =?UTF-8?q?=20=ED=83=80=EC=9E=85=EA=B3=BC=20=EA=B8=B0=EB=AC=BC=20=EC=A0=84?= =?UTF-8?q?=EB=9E=B5=EC=9D=84=20Type=20enum=20=ED=81=B4=EB=9E=98=EC=8A=A4?= =?UTF-8?q?=EC=97=90=20=ED=95=98=EB=82=98=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/BoardFactory.java | 130 +++++++++--------- src/main/java/domain/Piece.java | 11 +- src/main/java/domain/Type.java | 32 +++-- src/main/java/domain/vo/Position.java | 10 +- src/test/java/domain/BoardTest.java | 7 +- src/test/java/domain/PieceTest.java | 2 +- .../strategy/CannonMoveStrategyTest.java | 40 +++--- .../strategy/ChariotMoveStrategyTest.java | 29 ++-- .../strategy/GeneralMoveStrategyTest.java | 6 +- .../strategy/GuardMoveStrategyTest.java | 24 ++-- .../strategy/SoldierMoveStrategyTest.java | 35 ++--- 11 files changed, 182 insertions(+), 144 deletions(-) diff --git a/src/main/java/domain/BoardFactory.java b/src/main/java/domain/BoardFactory.java index da65fe97cc..7cf0f64c2a 100644 --- a/src/main/java/domain/BoardFactory.java +++ b/src/main/java/domain/BoardFactory.java @@ -23,16 +23,16 @@ public static Board setUpLeftElephantFormation(Map initialBoard Map board = new TreeMap<>(POSITION_COMPARATOR); board.putAll(initialBoard); if (team == Team.CHU) { - board.put(Position.of(0, 1), Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(0, 6), Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(0, 2), Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); - board.put(Position.of(0, 7), Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(0, 1), Piece.of(Team.CHU, Type.ELEPHANT)); + board.put(Position.of(0, 6), Piece.of(Team.CHU, Type.ELEPHANT)); + board.put(Position.of(0, 2), Piece.of(Team.CHU, Type.HORSE)); + board.put(Position.of(0, 7), Piece.of(Team.CHU, Type.HORSE)); } if (team == Team.HAN) { - board.put(Position.of(9, 2), Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(9, 7), Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(9, 1), Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); - board.put(Position.of(9, 6), Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(9, 2), Piece.of(Team.HAN, Type.ELEPHANT)); + board.put(Position.of(9, 7), Piece.of(Team.HAN, Type.ELEPHANT)); + board.put(Position.of(9, 1), Piece.of(Team.HAN, Type.HORSE)); + board.put(Position.of(9, 6), Piece.of(Team.HAN, Type.HORSE)); } return Board.of(board); @@ -42,16 +42,16 @@ public static Board setUpRightElephantFormation(Map initialBoar Map board = new TreeMap<>(POSITION_COMPARATOR); board.putAll(initialBoard); if (team == Team.CHU) { - board.put(Position.of(0, 2), Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(0, 7), Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(0, 1), Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); - board.put(Position.of(0, 6), Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(0, 2), Piece.of(Team.CHU, Type.ELEPHANT)); + board.put(Position.of(0, 7), Piece.of(Team.CHU, Type.ELEPHANT)); + board.put(Position.of(0, 1), Piece.of(Team.CHU, Type.HORSE)); + board.put(Position.of(0, 6), Piece.of(Team.CHU, Type.HORSE)); } if (team == Team.HAN) { - board.put(Position.of(9, 1), Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(9, 6), Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(9, 2), Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); - board.put(Position.of(9, 7), Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(9, 1), Piece.of(Team.HAN, Type.ELEPHANT)); + board.put(Position.of(9, 6), Piece.of(Team.HAN, Type.ELEPHANT)); + board.put(Position.of(9, 2), Piece.of(Team.HAN, Type.HORSE)); + board.put(Position.of(9, 7), Piece.of(Team.HAN, Type.HORSE)); } return Board.of(board); @@ -61,16 +61,16 @@ public static Board setUpInnerElephantFormation(Map initialBoar Map board = new TreeMap<>(POSITION_COMPARATOR); board.putAll(initialBoard); if (team == Team.CHU) { - board.put(Position.of(0, 2), Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(0, 6), Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(0, 1), Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); - board.put(Position.of(0, 7), Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(0, 2), Piece.of(Team.CHU, Type.ELEPHANT)); + board.put(Position.of(0, 6), Piece.of(Team.CHU, Type.ELEPHANT)); + board.put(Position.of(0, 1), Piece.of(Team.CHU, Type.HORSE)); + board.put(Position.of(0, 7), Piece.of(Team.CHU, Type.HORSE)); } if (team == Team.HAN) { - board.put(Position.of(9, 2), Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(9, 6), Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(9, 1), Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); - board.put(Position.of(9, 7), Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(9, 2), Piece.of(Team.HAN, Type.ELEPHANT)); + board.put(Position.of(9, 6), Piece.of(Team.HAN, Type.ELEPHANT)); + board.put(Position.of(9, 1), Piece.of(Team.HAN, Type.HORSE)); + board.put(Position.of(9, 7), Piece.of(Team.HAN, Type.HORSE)); } return Board.of(board); @@ -80,16 +80,16 @@ public static Board setUpOuterElephantFormation(Map initialBoar Map board = new TreeMap<>(POSITION_COMPARATOR); board.putAll(initialBoard); if (team == Team.CHU) { - board.put(Position.of(0, 1), Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(0, 7), Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(0, 2), Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); - board.put(Position.of(0, 6), Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(0, 1), Piece.of(Team.CHU, Type.ELEPHANT)); + board.put(Position.of(0, 7), Piece.of(Team.CHU, Type.ELEPHANT)); + board.put(Position.of(0, 2), Piece.of(Team.CHU, Type.HORSE)); + board.put(Position.of(0, 6), Piece.of(Team.CHU, Type.HORSE)); } if (team == Team.HAN) { - board.put(Position.of(9, 1), Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(9, 7), Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(9, 2), Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); - board.put(Position.of(9, 6), Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); + board.put(Position.of(9, 1), Piece.of(Team.HAN, Type.ELEPHANT)); + board.put(Position.of(9, 7), Piece.of(Team.HAN, Type.ELEPHANT)); + board.put(Position.of(9, 2), Piece.of(Team.HAN, Type.HORSE)); + board.put(Position.of(9, 6), Piece.of(Team.HAN, Type.HORSE)); } return Board.of(board); @@ -98,39 +98,39 @@ public static Board setUpOuterElephantFormation(Map initialBoar public static Board setUp() { Map board = new TreeMap<>(POSITION_COMPARATOR); - board.put(Position.of(0, 0),Piece.of(Team.CHU, Type.CHARIOT, new ChariotMoveStrategy())); - board.put(Position.of(0, 1),Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(0, 2),Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); - board.put(Position.of(0, 3),Piece.of(Team.CHU, Type.GUARD, new GuardMoveStrategy())); - board.put(Position.of(0, 5),Piece.of(Team.CHU, Type.GUARD, new GuardMoveStrategy())); - board.put(Position.of(0, 6),Piece.of(Team.CHU, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(0, 7),Piece.of(Team.CHU, Type.HORSE, new HorseMoveStrategy())); - board.put(Position.of(0, 8),Piece.of(Team.CHU, Type.CHARIOT, new ChariotMoveStrategy())); - board.put(Position.of(1, 4),Piece.of(Team.CHU, Type.GENERAL, new GeneralMoveStrategy())); - board.put(Position.of(2, 1),Piece.of(Team.CHU, Type.CANNON, new CannonMoveStrategy())); - board.put(Position.of(2, 7),Piece.of(Team.CHU, Type.CANNON, new CannonMoveStrategy())); - board.put(Position.of(3, 0),Piece.of(Team.CHU, Type.SOLDIER, new SoldierMoveStrategy())); - board.put(Position.of(3, 2),Piece.of(Team.CHU, Type.SOLDIER, new SoldierMoveStrategy())); - board.put(Position.of(3, 4),Piece.of(Team.CHU, Type.SOLDIER, new SoldierMoveStrategy())); - board.put(Position.of(3, 6),Piece.of(Team.CHU, Type.SOLDIER, new SoldierMoveStrategy())); - board.put(Position.of(3, 8),Piece.of(Team.CHU, Type.SOLDIER, new SoldierMoveStrategy())); - - board.put(Position.of(9, 0),Piece.of(Team.HAN, Type.CHARIOT, new ChariotMoveStrategy())); - board.put(Position.of(9, 1),Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(9, 2),Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); - board.put(Position.of(9, 3),Piece.of(Team.HAN, Type.GUARD, new GuardMoveStrategy())); - board.put(Position.of(9, 5),Piece.of(Team.HAN, Type.GUARD, new GuardMoveStrategy())); - board.put(Position.of(9, 6),Piece.of(Team.HAN, Type.ELEPHANT, new ElephantMoveStrategy())); - board.put(Position.of(9, 7),Piece.of(Team.HAN, Type.HORSE, new HorseMoveStrategy())); - board.put(Position.of(9, 8),Piece.of(Team.HAN, Type.CHARIOT, new ChariotMoveStrategy())); - board.put(Position.of(8, 4),Piece.of(Team.HAN, Type.GENERAL, new GeneralMoveStrategy())); - board.put(Position.of(7, 1),Piece.of(Team.HAN, Type.CANNON, new CannonMoveStrategy())); - board.put(Position.of(7, 7),Piece.of(Team.HAN, Type.CANNON, new CannonMoveStrategy())); - board.put(Position.of(6, 0),Piece.of(Team.HAN, Type.SOLDIER, new SoldierMoveStrategy())); - board.put(Position.of(6, 2),Piece.of(Team.HAN, Type.SOLDIER, new SoldierMoveStrategy())); - board.put(Position.of(6, 4),Piece.of(Team.HAN, Type.SOLDIER, new SoldierMoveStrategy())); - board.put(Position.of(6, 6),Piece.of(Team.HAN, Type.SOLDIER, new SoldierMoveStrategy())); - board.put(Position.of(6, 8),Piece.of(Team.HAN, Type.SOLDIER, new SoldierMoveStrategy())); + board.put(Position.of(0, 0),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(0, 1),Piece.of(Team.CHU, Type.ELEPHANT)); + board.put(Position.of(0, 2),Piece.of(Team.CHU, Type.HORSE)); + board.put(Position.of(0, 3),Piece.of(Team.CHU, Type.GUARD)); + board.put(Position.of(0, 5),Piece.of(Team.CHU, Type.GUARD)); + board.put(Position.of(0, 6),Piece.of(Team.CHU, Type.ELEPHANT)); + board.put(Position.of(0, 7),Piece.of(Team.CHU, Type.HORSE)); + board.put(Position.of(0, 8),Piece.of(Team.CHU, Type.CHARIOT)); + board.put(Position.of(1, 4),Piece.of(Team.CHU, Type.GENERAL)); + board.put(Position.of(2, 1),Piece.of(Team.CHU, Type.CANNON)); + board.put(Position.of(2, 7),Piece.of(Team.CHU, Type.CANNON)); + board.put(Position.of(3, 0),Piece.of(Team.CHU, Type.SOLDIER)); + board.put(Position.of(3, 2),Piece.of(Team.CHU, Type.SOLDIER)); + board.put(Position.of(3, 4),Piece.of(Team.CHU, Type.SOLDIER)); + board.put(Position.of(3, 6),Piece.of(Team.CHU, Type.SOLDIER)); + board.put(Position.of(3, 8),Piece.of(Team.CHU, Type.SOLDIER)); + + board.put(Position.of(9, 0),Piece.of(Team.HAN, Type.CHARIOT)); + board.put(Position.of(9, 1),Piece.of(Team.HAN, Type.ELEPHANT)); + board.put(Position.of(9, 2),Piece.of(Team.HAN, Type.HORSE)); + board.put(Position.of(9, 3),Piece.of(Team.HAN, Type.GUARD)); + board.put(Position.of(9, 5),Piece.of(Team.HAN, Type.GUARD)); + board.put(Position.of(9, 6),Piece.of(Team.HAN, Type.ELEPHANT)); + board.put(Position.of(9, 7),Piece.of(Team.HAN, Type.HORSE)); + board.put(Position.of(9, 8),Piece.of(Team.HAN, Type.CHARIOT)); + board.put(Position.of(8, 4),Piece.of(Team.HAN, Type.GENERAL)); + board.put(Position.of(7, 1),Piece.of(Team.HAN, Type.CANNON)); + board.put(Position.of(7, 7),Piece.of(Team.HAN, Type.CANNON)); + board.put(Position.of(6, 0),Piece.of(Team.HAN, Type.SOLDIER)); + board.put(Position.of(6, 2),Piece.of(Team.HAN, Type.SOLDIER)); + board.put(Position.of(6, 4),Piece.of(Team.HAN, Type.SOLDIER)); + board.put(Position.of(6, 6),Piece.of(Team.HAN, Type.SOLDIER)); + board.put(Position.of(6, 8),Piece.of(Team.HAN, Type.SOLDIER)); return Board.of(board); } diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java index 2edbdec368..f5d449d35b 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/Piece.java @@ -7,16 +7,14 @@ public class Piece { private final Team team; private final Type type; - private final MoveStrategy moveStrategy; - private Piece(final Team team, final Type type, final MoveStrategy moveStrategy) { + private Piece(final Team team, final Type type) { this.team = team; this.type = type; - this.moveStrategy = moveStrategy; } - public static Piece of(final Team team, final Type type, final MoveStrategy moveStrategy) { - return new Piece(team, type, moveStrategy); + public static Piece of(final Team team, final Type type) { + return new Piece(team, type); } public boolean isAnotherTeam(final Piece anotherPiece) { @@ -24,7 +22,8 @@ public boolean isAnotherTeam(final Piece anotherPiece) { } public boolean canMovePiece(Position from, Position to, Board board) { - return moveStrategy.canMove(from, to, board); + MoveStrategy strategy = type.getStrategy(); + return strategy.canMove(from, to, board); } public Type getType() { diff --git a/src/main/java/domain/Type.java b/src/main/java/domain/Type.java index 97e75c020d..28476f94f6 100644 --- a/src/main/java/domain/Type.java +++ b/src/main/java/domain/Type.java @@ -1,18 +1,34 @@ package domain; +import domain.strategy.CannonMoveStrategy; +import domain.strategy.ChariotMoveStrategy; +import domain.strategy.ElephantMoveStrategy; +import domain.strategy.GeneralMoveStrategy; +import domain.strategy.GuardMoveStrategy; +import domain.strategy.HorseMoveStrategy; +import domain.strategy.MoveStrategy; +import domain.strategy.SoldierMoveStrategy; +import java.util.function.Supplier; + public enum Type { - GENERAL("궁"), - CHARIOT("차"), - CANNON("포"), - HORSE("마"), - ELEPHANT("상"), - GUARD("사"), - SOLDIER("졸"); + GENERAL("궁", GeneralMoveStrategy::new), + CHARIOT("차", ChariotMoveStrategy::new), + CANNON("포", CannonMoveStrategy::new), + HORSE("마", HorseMoveStrategy::new), + ELEPHANT("상", ElephantMoveStrategy::new), + GUARD("사", GuardMoveStrategy::new), + SOLDIER("졸", SoldierMoveStrategy::new); private final String name; + private final Supplier strategySupplier; - Type(final String name) { + Type(String name, Supplier strategySupplier) { this.name = name; + this.strategySupplier = strategySupplier; + } + + public MoveStrategy getStrategy() { + return strategySupplier.get(); } public String getName() { diff --git a/src/main/java/domain/vo/Position.java b/src/main/java/domain/vo/Position.java index 00e668a270..79f0f474bf 100644 --- a/src/main/java/domain/vo/Position.java +++ b/src/main/java/domain/vo/Position.java @@ -2,7 +2,7 @@ import java.util.Objects; -public class Position { +public class Position implements Comparable { private static final int MAX_COLUMN = 8; private static final int MAX_ROW = 9; @@ -56,4 +56,12 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(row, col); } + + @Override + public int compareTo(Position other) { + if (this.row != other.row) { + return Integer.compare(this.row, other.row); + } + return Integer.compare(other.col, this.col); + } } diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java index 4f21e4ca4d..294333baba 100644 --- a/src/test/java/domain/BoardTest.java +++ b/src/test/java/domain/BoardTest.java @@ -44,14 +44,15 @@ class BoardTest { void 기물_이동() { // given Map tempBoard = new HashMap<>(); - tempBoard.put(Position.of(0, 0), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); - tempBoard.put(Position.of(0, 3), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); + Piece chuSoldierPiece = Piece.of(Team.CHU, Type.SOLDIER); + tempBoard.put(Position.of(0, 0), chuSoldierPiece); + tempBoard.put(Position.of(0, 3), chuSoldierPiece); Board board = Board.of(tempBoard); // when Position from = Position.of(0, 0); - Position to = Position.of(3, 0); + Position to = Position.of(1, 0); board.move(from, to, Team.CHU); // then diff --git a/src/test/java/domain/PieceTest.java b/src/test/java/domain/PieceTest.java index 048087c053..03e8897dd4 100644 --- a/src/test/java/domain/PieceTest.java +++ b/src/test/java/domain/PieceTest.java @@ -12,6 +12,6 @@ class PieceTest { // given // when // then - Assertions.assertDoesNotThrow(() -> Piece.of(Team.CHU, Type.CHARIOT, new FixedMoveStrategy())); + Assertions.assertDoesNotThrow(() -> Piece.of(Team.CHU, Type.CHARIOT)); } } diff --git a/src/test/java/domain/strategy/CannonMoveStrategyTest.java b/src/test/java/domain/strategy/CannonMoveStrategyTest.java index ed2fb79b1a..3bdb3c299a 100644 --- a/src/test/java/domain/strategy/CannonMoveStrategyTest.java +++ b/src/test/java/domain/strategy/CannonMoveStrategyTest.java @@ -17,8 +17,8 @@ class CannonMoveStrategyTest { // given MoveStrategy strategy = new CannonMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); + boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON)); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER)); Board board = BoardFactory.of(boardMapper); @@ -34,9 +34,9 @@ class CannonMoveStrategyTest { @DisplayName("한나라 포의 이동 경로에 다른 기물이 없으면 이동하지 못한다.") void 포의_이동_경로에_다른_기물이_없으면_이동_불가() { // given - MoveStrategy strategy = new CannonMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); + Piece cannon = Piece.of(Team.CHU, Type.CANNON); + boardMapper.put(Position.of(2, 1), cannon); Board board = BoardFactory.of(boardMapper); @@ -45,7 +45,7 @@ class CannonMoveStrategyTest { Position to = Position.of(5, 1); // then - Assertions.assertFalse(strategy.canMove(from, to, board)); + Assertions.assertFalse(cannon.canMovePiece(from, to, board)); } @Test @@ -54,9 +54,9 @@ class CannonMoveStrategyTest { // given MoveStrategy strategy = new CannonMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); - boardMapper.put(Position.of(4, 1), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); + boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON)); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER)); + boardMapper.put(Position.of(4, 1), Piece.of(Team.CHU, Type.SOLDIER)); Board board = BoardFactory.of(boardMapper); @@ -74,9 +74,9 @@ class CannonMoveStrategyTest { // given MoveStrategy strategy = new CannonMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); - boardMapper.put(Position.of(5, 1), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); + boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON)); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER)); + boardMapper.put(Position.of(5, 1), Piece.of(Team.CHU, Type.SOLDIER)); Board board = BoardFactory.of(boardMapper); @@ -94,9 +94,9 @@ class CannonMoveStrategyTest { // given MoveStrategy strategy = new CannonMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); - boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.CANNON, strategy)); + boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON)); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER)); + boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.CANNON)); Board board = BoardFactory.of(boardMapper); @@ -114,9 +114,9 @@ class CannonMoveStrategyTest { // given MoveStrategy strategy = new CannonMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); - boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.SOLDIER, new FixedMoveStrategy())); + boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON)); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER)); + boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.SOLDIER)); Board board = BoardFactory.of(boardMapper); @@ -134,9 +134,9 @@ class CannonMoveStrategyTest { // given MoveStrategy strategy = new CannonMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.CANNON, strategy)); - boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.SOLDIER, new FixedMoveStrategy())); + boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON)); + boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.CANNON)); + boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.SOLDIER)); Board board = BoardFactory.of(boardMapper); diff --git a/src/test/java/domain/strategy/ChariotMoveStrategyTest.java b/src/test/java/domain/strategy/ChariotMoveStrategyTest.java index 40e05fbf24..043e784a9d 100644 --- a/src/test/java/domain/strategy/ChariotMoveStrategyTest.java +++ b/src/test/java/domain/strategy/ChariotMoveStrategyTest.java @@ -2,7 +2,14 @@ import domain.Board; import domain.BoardFactory; +import domain.Piece; +import domain.Team; +import domain.Type; import domain.vo.Position; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.TreeMap; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -10,13 +17,19 @@ class ChariotMoveStrategyTest { - MoveStrategy strategy; + Piece chariotPiece; Board board; @BeforeEach void setUp() { - strategy = new ChariotMoveStrategy(); - board = BoardFactory.setUp(); + chariotPiece = Piece.of(Team.CHU, Type.CHARIOT); + Piece horsePiece = Piece.of(Team.CHU, Type.HORSE); + Piece elephantPiece = Piece.of(Team.HAN, Type.ELEPHANT); + Map boardMapper = new HashMap<>(); + boardMapper.put(Position.of(0, 0), chariotPiece); + boardMapper.put(Position.of(3, 0), horsePiece); + boardMapper.put(Position.of(0, 3), elephantPiece); + board = BoardFactory.of(boardMapper); } @Test @@ -28,7 +41,7 @@ void setUp() { Position to = Position.of(2, 0); // then - Assertions.assertTrue(strategy.canMove(from, to, board)); + Assertions.assertTrue(chariotPiece.canMovePiece(from, to, board)); } @Test @@ -40,7 +53,7 @@ void setUp() { Position to = Position.of(3, 0); // then - Assertions.assertFalse(strategy.canMove(from, to, board)); + Assertions.assertFalse(chariotPiece.canMovePiece(from, to, board)); } @Test @@ -48,10 +61,10 @@ void setUp() { void 차_목적지에_다른_팀_기물이_있으면_이동_가능() { // given // when - Position from = Position.of(3, 0); - Position to = Position.of(6, 0); + Position from = Position.of(0, 0); + Position to = Position.of(0, 3); // then - Assertions.assertTrue(strategy.canMove(from, to, board)); + Assertions.assertTrue(chariotPiece.canMovePiece(from, to, board)); } } diff --git a/src/test/java/domain/strategy/GeneralMoveStrategyTest.java b/src/test/java/domain/strategy/GeneralMoveStrategyTest.java index dcbe9b5e75..ae1c4f26f4 100644 --- a/src/test/java/domain/strategy/GeneralMoveStrategyTest.java +++ b/src/test/java/domain/strategy/GeneralMoveStrategyTest.java @@ -19,7 +19,7 @@ class GeneralMoveStrategyTest { void setUp() { strategy = new GeneralMoveStrategy(); boardMapper = new HashMap<>(); - boardMapper.put(Position.of(1, 4), Piece.of(Team.CHU, Type.GENERAL, strategy)); + boardMapper.put(Position.of(1, 4), Piece.of(Team.CHU, Type.GENERAL)); } @Test @@ -40,7 +40,7 @@ void setUp() { @DisplayName("궁의 목적지에 같은 팀 기물이 있으면 이동하지 않는다.") void 궁_목적지에_같은_팀_기물이_있으면_이동_불가() { // given - boardMapper.put(Position.of(1, 5), Piece.of(Team.CHU, Type.SOLDIER, new FixedMoveStrategy())); + boardMapper.put(Position.of(1, 5), Piece.of(Team.CHU, Type.SOLDIER)); Board board = BoardFactory.of(boardMapper); // when @@ -56,7 +56,7 @@ void setUp() { @DisplayName("궁의 목적지에 다른 팀 기물이 있으면 이동한다.") void 궁_목적지에_다른_팀_기물이_있으면_정상_이동() { // given - boardMapper.put(Position.of(1, 5), Piece.of(Team.HAN, Type.SOLDIER, new FixedMoveStrategy())); + boardMapper.put(Position.of(1, 5), Piece.of(Team.HAN, Type.SOLDIER)); Board board = BoardFactory.of(boardMapper); // when diff --git a/src/test/java/domain/strategy/GuardMoveStrategyTest.java b/src/test/java/domain/strategy/GuardMoveStrategyTest.java index 6ec0241346..c086948e02 100644 --- a/src/test/java/domain/strategy/GuardMoveStrategyTest.java +++ b/src/test/java/domain/strategy/GuardMoveStrategyTest.java @@ -33,10 +33,10 @@ class GuardMoveStrategyTest { @DisplayName("사의 목적지에 같은 팀 기물이 있으면 이동하지 않는다.") void 사_목적지에_같은_팀_기물이_있으면_이동_불가() { // given - MoveStrategy guardMoveStrategy = new GuardMoveStrategy(); Map PositionPiecePair = new LinkedHashMap<>(); - PositionPiecePair.put(Position.of(0, 3), Piece.of(Team.CHU, Type.GUARD, guardMoveStrategy)); - PositionPiecePair.put(Position.of(0, 2), Piece.of(Team.CHU, Type.GUARD, guardMoveStrategy)); + Piece guardPiece = Piece.of(Team.CHU, Type.GUARD); + PositionPiecePair.put(Position.of(0, 3), guardPiece); + PositionPiecePair.put(Position.of(0, 2), guardPiece); Board board = Board.of(PositionPiecePair); Position position = Position.of(0, 3); @@ -44,7 +44,7 @@ class GuardMoveStrategyTest { // when // then - Assertions.assertFalse(guardMoveStrategy.canMove(position, targetPosition, board)); + Assertions.assertFalse(guardPiece.canMovePiece(position, targetPosition, board)); } @@ -52,11 +52,11 @@ class GuardMoveStrategyTest { @DisplayName("사의 목적지에 다른 팀 기물이 있으면 이동한다.") void 사_목적지에_다른_팀_기물이_있으면_정상_이동() { // given - MoveStrategy guardMoveStrategy = new GuardMoveStrategy(); - MoveStrategy soldierMoveStrategy = new SoldierMoveStrategy(); Map positionPiecePair = new LinkedHashMap<>(); - positionPiecePair.put(Position.of(0, 3), Piece.of(Team.CHU, Type.GUARD, guardMoveStrategy)); - positionPiecePair.put(Position.of(1, 3), Piece.of(Team.HAN, Type.SOLDIER, soldierMoveStrategy)); + Piece guardPiece = Piece.of(Team.CHU, Type.GUARD); + positionPiecePair.put(Position.of(0, 3), guardPiece); + Piece soldierPiece = Piece.of(Team.HAN, Type.SOLDIER); + positionPiecePair.put(Position.of(1, 3), soldierPiece); Board board = Board.of(positionPiecePair); Position position = Position.of(0, 3); @@ -64,16 +64,16 @@ class GuardMoveStrategyTest { // when // then - Assertions.assertTrue(guardMoveStrategy.canMove(position, targetPosition, board)); + Assertions.assertTrue(guardPiece.canMovePiece(position, targetPosition, board)); } @Test @DisplayName("사가 궁성 외부 대각선으로 이동하면 예외를 발생한다.") void 사_궁성_밖_대각선_이동_불가() { // given - MoveStrategy guardMoveStrategy = new GuardMoveStrategy(); Map positionPiecePair = new LinkedHashMap<>(); - positionPiecePair.put(Position.of(0, 3), Piece.of(Team.CHU, Type.GUARD, guardMoveStrategy)); + Piece guardPiece = Piece.of(Team.CHU, Type.GUARD); + positionPiecePair.put(Position.of(0, 3), guardPiece); Board board = Board.of(positionPiecePair); Position position = Position.of(0, 3); @@ -81,6 +81,6 @@ class GuardMoveStrategyTest { // when // then - Assertions.assertFalse(guardMoveStrategy.canMove(position, targetPosition, board)); + Assertions.assertFalse(guardPiece.canMovePiece(position, targetPosition, board)); } } diff --git a/src/test/java/domain/strategy/SoldierMoveStrategyTest.java b/src/test/java/domain/strategy/SoldierMoveStrategyTest.java index 7bee744fc4..a31eec9c11 100644 --- a/src/test/java/domain/strategy/SoldierMoveStrategyTest.java +++ b/src/test/java/domain/strategy/SoldierMoveStrategyTest.java @@ -15,9 +15,9 @@ class SoldierMoveStrategyTest { @DisplayName("졸의 목적지에 기물이 없으면 이동한다.") void 졸_정상_이동() { // given - MoveStrategy strategy = new SoldierMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(3, 4), Piece.of(Team.CHU, Type.SOLDIER, strategy)); + Piece soldierPiece = Piece.of(Team.CHU, Type.SOLDIER); + boardMapper.put(Position.of(3, 4), soldierPiece); Board board = BoardFactory.of(boardMapper); @@ -26,17 +26,17 @@ class SoldierMoveStrategyTest { Position targetPosition = Position.of(4, 4); // then - Assertions.assertTrue(strategy.canMove(position, targetPosition, board)); + Assertions.assertTrue(soldierPiece.canMovePiece(position, targetPosition, board)); } @Test @DisplayName("졸의 목적지에 같은 팀 기물이 있으면 이동하지 않는다.") void 졸_목적지에_같은_팀_기물이_있으면_이동_불가() { // given - MoveStrategy strategy = new SoldierMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(3, 4), Piece.of(Team.CHU, Type.SOLDIER, strategy)); - boardMapper.put(Position.of(4, 4), Piece.of(Team.CHU, Type.SOLDIER, strategy)); + Piece soldierPiece = Piece.of(Team.CHU, Type.SOLDIER); + boardMapper.put(Position.of(3, 4), soldierPiece); + boardMapper.put(Position.of(4, 4), soldierPiece); Board board = BoardFactory.of(boardMapper); @@ -45,7 +45,7 @@ class SoldierMoveStrategyTest { Position targetPosition = Position.of(4, 4); // then - Assertions.assertFalse(strategy.canMove(position, targetPosition, board)); + Assertions.assertFalse(soldierPiece.canMovePiece(position, targetPosition, board)); } @@ -53,10 +53,11 @@ class SoldierMoveStrategyTest { @DisplayName("졸의 목적지에 다른 팀 기물이 있으면 이동한다.") void 졸_목적지에_다른_팀_기물이_있으면_정상_이동() { // given - MoveStrategy strategy = new SoldierMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(3, 4), Piece.of(Team.CHU, Type.SOLDIER, strategy)); - boardMapper.put(Position.of(4, 4), Piece.of(Team.HAN, Type.SOLDIER, strategy)); + Piece chuSoldierPiece = Piece.of(Team.CHU, Type.SOLDIER); + boardMapper.put(Position.of(3, 4), chuSoldierPiece); + Piece hanSoldierPiece = Piece.of(Team.HAN, Type.SOLDIER); + boardMapper.put(Position.of(4, 4), hanSoldierPiece); Board board = BoardFactory.of(boardMapper); @@ -65,16 +66,16 @@ class SoldierMoveStrategyTest { Position targetPosition = Position.of(4, 4); // then - Assertions.assertTrue(strategy.canMove(position, targetPosition, board)); + Assertions.assertTrue(chuSoldierPiece.canMovePiece(position, targetPosition, board)); } @Test @DisplayName("초나라 졸의 이동 경로가 후퇴이면 이동할 수 없다.") void 초나라_졸의_이동_경로가_후퇴이면_이동_불가() { // given - MoveStrategy strategy = new SoldierMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(3, 4), Piece.of(Team.CHU, Type.SOLDIER, strategy)); + Piece chuSoldierPiece = Piece.of(Team.CHU, Type.SOLDIER); + boardMapper.put(Position.of(3, 4), chuSoldierPiece); Board board = BoardFactory.of(boardMapper); @@ -83,16 +84,16 @@ class SoldierMoveStrategyTest { Position targetPosition = Position.of(2, 4); // then - Assertions.assertFalse(strategy.canMove(position, targetPosition, board)); + Assertions.assertFalse(chuSoldierPiece.canMovePiece(position, targetPosition, board)); } @Test @DisplayName("한나라 졸의 이동 경로가 후퇴이면 이동할 수 없다.") void 한나라_졸의_이동_경로가_후퇴이면_이동_불가() { // given - MoveStrategy strategy = new SoldierMoveStrategy(); Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(6, 4), Piece.of(Team.HAN, Type.SOLDIER, strategy)); + Piece hanSoldierPiece = Piece.of(Team.HAN, Type.SOLDIER); + boardMapper.put(Position.of(6, 4), hanSoldierPiece); Board board = BoardFactory.of(boardMapper); @@ -101,6 +102,6 @@ class SoldierMoveStrategyTest { Position targetPosition = Position.of(7, 4); // then - Assertions.assertFalse(strategy.canMove(position, targetPosition, board)); + Assertions.assertFalse(hanSoldierPiece.canMovePiece(position, targetPosition, board)); } } From 30be12a83c46a50490136cd8f03ae0b6cf1e20e5 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Thu, 2 Apr 2026 17:27:50 +0900 Subject: [PATCH 56/87] =?UTF-8?q?refactor:=20board=EC=99=80=20strategy?= =?UTF-8?q?=EC=9D=98=20=EC=B1=85=EC=9E=84=EC=9D=84=20=EB=8D=94=20=EB=AA=85?= =?UTF-8?q?=ED=99=95=ED=9E=88=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Board.java | 27 +++--- src/main/java/domain/Piece.java | 12 ++- .../domain/strategy/CannonMoveStrategy.java | 96 ++++++++----------- .../domain/strategy/ChariotMoveStrategy.java | 64 +++++++------ .../domain/strategy/ElephantMoveStrategy.java | 38 ++++++-- .../domain/strategy/GeneralMoveStrategy.java | 25 +++-- .../domain/strategy/GuardMoveStrategy.java | 37 +++++-- .../domain/strategy/HorseMoveStrategy.java | 34 +++++-- .../java/domain/strategy/MoveStrategy.java | 11 ++- .../domain/strategy/SoldierMoveStrategy.java | 35 ++++--- src/main/java/view/OutputView.java | 2 +- src/test/java/domain/FixedMoveStrategy.java | 12 --- .../strategy/CannonMoveStrategyTest.java | 82 ++++++---------- .../strategy/ChariotMoveStrategyTest.java | 29 ++---- .../strategy/ElephantMoveStrategyTest.java | 40 ++++---- .../strategy/GeneralMoveStrategyTest.java | 32 ++----- .../strategy/GuardMoveStrategyTest.java | 40 +++----- .../strategy/HorseMoveStrategyTest.java | 35 +++---- .../strategy/SoldierMoveStrategyTest.java | 40 ++------ 19 files changed, 333 insertions(+), 358 deletions(-) delete mode 100644 src/test/java/domain/FixedMoveStrategy.java diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index 2321684172..1b5ccd7eff 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -2,6 +2,8 @@ import domain.vo.Position; +import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Optional; @@ -25,7 +27,10 @@ public void move(final Position from, final Position to, final Team currentTeam) throw new IllegalArgumentException("[ERROR] 상대편의 기물은 움직일 수 없습니다."); } - if (!fromPiece.canMovePiece(from, to, this)) { + List path = fromPiece.getPathPositions(from, to); + Map piecesOnPath = findPiecesAt(path); + + if (!fromPiece.canMovePiece(from, to, piecesOnPath)) { throw new IllegalArgumentException("[ERROR] 해당 위치로 움직일 수 없습니다."); } @@ -33,6 +38,14 @@ public void move(final Position from, final Position to, final Team currentTeam) board.put(to, fromPiece); } + private Map findPiecesAt(final List positions) { + Map result = new HashMap<>(); + for (Position pos : positions) { + findPieceByPosition(pos).ifPresent(piece -> result.put(pos, piece)); + } + return result; + } + public boolean isExistPosition(final Position tempPosition) { return board.containsKey(tempPosition); } @@ -41,17 +54,7 @@ public Optional findPieceByPosition(final Position position) { return Optional.ofNullable(board.get(position)); } - public boolean isAnotherTeam(final Position from, final Position to) { - if (findPieceByPosition(to).isEmpty()) { - return true; - } - - Piece currentPiece = findPieceByPosition(from).get(); - Piece targetPiece = findPieceByPosition(to).get(); - return currentPiece.isAnotherTeam(targetPiece); - } - public Map getBoard() { return Map.copyOf(board); } -} +} \ No newline at end of file diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java index f5d449d35b..f8c349f60f 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/Piece.java @@ -3,6 +3,9 @@ import domain.strategy.MoveStrategy; import domain.vo.Position; +import java.util.List; +import java.util.Map; + public class Piece { private final Team team; @@ -21,9 +24,14 @@ public boolean isAnotherTeam(final Piece anotherPiece) { return this.team != anotherPiece.team; } - public boolean canMovePiece(Position from, Position to, Board board) { + public List getPathPositions(final Position from, final Position to) { + MoveStrategy strategy = type.getStrategy(); + return strategy.getPath(from, to); + } + + public boolean canMovePiece(final Position from, final Position to, final Map piecesOnPath) { MoveStrategy strategy = type.getStrategy(); - return strategy.canMove(from, to, board); + return strategy.canMove(this, from, to, piecesOnPath); } public Type getType() { diff --git a/src/main/java/domain/strategy/CannonMoveStrategy.java b/src/main/java/domain/strategy/CannonMoveStrategy.java index 3c8364b375..23a09dd64a 100644 --- a/src/main/java/domain/strategy/CannonMoveStrategy.java +++ b/src/main/java/domain/strategy/CannonMoveStrategy.java @@ -1,85 +1,67 @@ package domain.strategy; -import domain.Board; +import domain.Piece; import domain.Type; import domain.vo.Position; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + public class CannonMoveStrategy implements MoveStrategy { private static final int CANNON_REQUIRED_PIECE_COUNT = 1; @Override - public boolean canMove(final Position from, final Position to, final Board board) { - if (isNotCorrectPath(from, to)) - return false; + public List getPath(final Position from, final Position to) { + if (isNotCorrectPath(from, to)) { + return List.of(); + } - int nx = determineNx(from, to); - int ny = determineNy(from, to); + List path = new ArrayList<>(); + int nx = Integer.compare(to.getRow(), from.getRow()); + int ny = Integer.compare(to.getCol(), from.getCol()); - int pieceCount = 0; - int row = from.getRow(); - int col = from.getCol(); - while (true) { + int row = from.getRow() + nx; + int col = from.getCol() + ny; + while (row != to.getRow() || col != to.getCol()) { + path.add(Position.of(row, col)); row += nx; col += ny; - - if (row == to.getRow() && col == to.getCol()) { - return isCannonValidTarget(from, to, board, pieceCount); - } - - if (board.isExistPosition(Position.of(row, col))) { - if (isCannon(board, row, col)) { - return false; - } - - pieceCount += 1; - } - - if (pieceCount > CANNON_REQUIRED_PIECE_COUNT) { - return false; - } } + path.add(to); + return path; } - private boolean isCannonValidTarget(final Position from, final Position to, final Board board, final int pieceCount) { - if (!isCannon(board, to.getRow(), to.getCol()) - && board.isAnotherTeam(from, to) - && pieceCount == CANNON_REQUIRED_PIECE_COUNT) { - return true; + @Override + public boolean canMove(final Piece mover, final Position from, final Position to, final Map piecesOnPath) { + if (isNotCorrectPath(from, to)) { + return false; } - return false; - } - private boolean isCannon(Board board, int row, int col) { - if (board.findPieceByPosition(Position.of(row, col)).isEmpty()) return false; - return board.findPieceByPosition(Position.of(row, col)).get().getType() == Type.CANNON; - } + Map intermediate = new HashMap<>(piecesOnPath); + Piece target = intermediate.remove(to); - private int determineNx(Position from, Position to) { - if (from.getRow() < to.getRow()) { - return 1; - } - if (from.getRow() > to.getRow()) { - return -1; + if (intermediate.values().stream().anyMatch(piece -> piece.getType() == Type.CANNON)) { + return false; } - return 0; - } - private int determineNy(Position from, Position to) { - if (from.getCol() < to.getCol()) { - return 1; - } - if (from.getCol() > to.getCol()) { - return -1; + if (intermediate.size() != CANNON_REQUIRED_PIECE_COUNT) { + return false; } - return 0; - } + if (target != null && target.getType() == Type.CANNON) { + return false; + } - private boolean isNotCorrectPath(Position from, Position to) { - if (from.getRow() != to.getRow() && from.getCol() != to.getCol()) { + if (target == null) { return true; } - return false; + return mover.isAnotherTeam(target); + } + + private boolean isNotCorrectPath(final Position from, final Position to) { + return from.getRow() != to.getRow() && from.getCol() != to.getCol(); } -} +} \ No newline at end of file diff --git a/src/main/java/domain/strategy/ChariotMoveStrategy.java b/src/main/java/domain/strategy/ChariotMoveStrategy.java index efff63ecaf..f57309a5bb 100644 --- a/src/main/java/domain/strategy/ChariotMoveStrategy.java +++ b/src/main/java/domain/strategy/ChariotMoveStrategy.java @@ -1,51 +1,55 @@ package domain.strategy; -import domain.Board; +import domain.Piece; import domain.vo.Position; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + public class ChariotMoveStrategy implements MoveStrategy { @Override - public boolean canMove(final Position from, final Position to, final Board board) { - - if (isNotCorrectPath(from, to)) - return false; - - int nx = 0, ny = 0; - if (from.getRow() == to.getRow()) { - if (from.getCol() < to.getCol()) { - ny = 1; - } - if (from.getCol() > to.getCol()) { - ny = -1; - } + public List getPath(final Position from, final Position to) { + if (isNotCorrectPath(from, to)) { + return List.of(); } - if (from.getCol() == to.getCol()) { - if (from.getRow() < to.getRow()) { - nx = 1; - } - if (from.getRow() > to.getRow()) { - nx = -1; - } - } + List path = new ArrayList<>(); + int nx = Integer.compare(to.getRow(), from.getRow()); + int ny = Integer.compare(to.getCol(), from.getCol()); - int row = from.getRow(); - int col = from.getCol(); - while (true) { + int row = from.getRow() + nx; + int col = from.getCol() + ny; + while (row != to.getRow() || col != to.getCol()) { + path.add(Position.of(row, col)); row += nx; col += ny; + } + path.add(to); + return path; + } - if (row == to.getRow() && col == to.getCol()) { - return board.isAnotherTeam(from, to); - } - if (board.isExistPosition(Position.of(row, col))) { + @Override + public boolean canMove(final Piece mover, final Position from, final Position to, final Map piecesOnPath) { + if (isNotCorrectPath(from, to)) { + return false; + } + + for (Position pos : piecesOnPath.keySet()) { + if (!pos.equals(to)) { return false; } } + + Piece target = piecesOnPath.get(to); + if (target == null) { + return true; + } + return mover.isAnotherTeam(target); } private boolean isNotCorrectPath(final Position from, final Position to) { return from.getCol() != to.getCol() && from.getRow() != to.getRow(); } -} +} \ No newline at end of file diff --git a/src/main/java/domain/strategy/ElephantMoveStrategy.java b/src/main/java/domain/strategy/ElephantMoveStrategy.java index e989bd4f43..e5e6e8b95a 100644 --- a/src/main/java/domain/strategy/ElephantMoveStrategy.java +++ b/src/main/java/domain/strategy/ElephantMoveStrategy.java @@ -1,34 +1,52 @@ package domain.strategy; -import domain.Board; +import domain.Piece; import domain.vo.Position; +import java.util.List; +import java.util.Map; + public class ElephantMoveStrategy implements MoveStrategy { @Override - public boolean canMove(final Position from, final Position to, final Board board) { - - if (isNotCorrectPath(from, to)) - return false; + public List getPath(final Position from, final Position to) { + if (isNotCorrectPath(from, to)) { + return List.of(); + } int nx = to.getRow() - from.getRow(); int ny = to.getCol() - from.getCol(); - int row = from.getRow(); int col = from.getCol(); - if (board.isExistPosition(Position.of(row + nx / 3, col + ny / 3))) { + Position mid1 = Position.of(row + nx / 3, col + ny / 3); + Position mid2 = Position.of(row + nx / 3 + nx / 2, col + ny / 3 + ny / 2); + return List.of(mid1, mid2, to); + } + + @Override + public boolean canMove(final Piece mover, final Position from, final Position to, final Map piecesOnPath) { + if (isNotCorrectPath(from, to)) { return false; } - if (board.isExistPosition(Position.of(row + nx / 3 + nx / 2, col + ny / 3 + ny / 2))) { + int nx = to.getRow() - from.getRow(); + int ny = to.getCol() - from.getCol(); + int row = from.getRow(); + int col = from.getCol(); + + Position mid1 = Position.of(row + nx / 3, col + ny / 3); + Position mid2 = Position.of(row + nx / 3 + nx / 2, col + ny / 3 + ny / 2); + + if (piecesOnPath.containsKey(mid1) || piecesOnPath.containsKey(mid2)) { return false; } - if (board.isAnotherTeam(from, to)) { + Piece target = piecesOnPath.get(to); + if (target == null) { return true; } - return false; + return mover.isAnotherTeam(target); } private boolean isNotCorrectPath(final Position from, final Position to) { diff --git a/src/main/java/domain/strategy/GeneralMoveStrategy.java b/src/main/java/domain/strategy/GeneralMoveStrategy.java index b8822fd910..83683c1da6 100644 --- a/src/main/java/domain/strategy/GeneralMoveStrategy.java +++ b/src/main/java/domain/strategy/GeneralMoveStrategy.java @@ -1,19 +1,32 @@ package domain.strategy; -import domain.Board; +import domain.Piece; import domain.vo.Position; +import java.util.List; +import java.util.Map; + public class GeneralMoveStrategy implements MoveStrategy { @Override - public boolean canMove(final Position from, final Position to, final Board board) { - if (isNotCorrectPath(from, to)) + public List getPath(final Position from, final Position to) { + if (isNotCorrectPath(from, to)) { + return List.of(); + } + return List.of(to); + } + + @Override + public boolean canMove(final Piece mover, final Position from, final Position to, final Map piecesOnPath) { + if (isNotCorrectPath(from, to)) { return false; + } - if (board.isAnotherTeam(from, to)) { + Piece target = piecesOnPath.get(to); + if (target == null) { return true; } - return false; + return mover.isAnotherTeam(target); } private boolean isNotCorrectPath(final Position from, final Position to) { @@ -27,4 +40,4 @@ private boolean isNotCorrectPath(final Position from, final Position to) { return false; } -} +} \ No newline at end of file diff --git a/src/main/java/domain/strategy/GuardMoveStrategy.java b/src/main/java/domain/strategy/GuardMoveStrategy.java index e492f49af4..65d6ce5f8f 100644 --- a/src/main/java/domain/strategy/GuardMoveStrategy.java +++ b/src/main/java/domain/strategy/GuardMoveStrategy.java @@ -1,28 +1,47 @@ package domain.strategy; -import domain.Board; +import domain.Piece; import domain.vo.Position; +import java.util.List; +import java.util.Map; + public class GuardMoveStrategy implements MoveStrategy { @Override - public boolean canMove(final Position from, final Position to, final Board board) { - if (Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) != 1) { - return false; + public List getPath(final Position from, final Position to) { + if (isNotCorrectPath(from, to)) { + return List.of(); } + return List.of(to); + } - if (from.getRow() == to.getRow() && Math.abs(from.getCol() - to.getCol()) != 1) { + @Override + public boolean canMove(final Piece mover, final Position from, final Position to, final Map piecesOnPath) { + if (isNotCorrectPath(from, to)) { return false; } - if (from.getCol() == to.getCol() && Math.abs(from.getRow() - to.getRow()) != 1) { - return false; + Piece target = piecesOnPath.get(to); + if (target == null) { + return true; } + return mover.isAnotherTeam(target); + } - if (board.isAnotherTeam(from, to)) { + private boolean isNotCorrectPath(final Position from, final Position to) { + if (Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) != 1) { + return true; + } + + if (from.getRow() == to.getRow() && Math.abs(from.getCol() - to.getCol()) != 1) { + return true; + } + + if (from.getCol() == to.getCol() && Math.abs(from.getRow() - to.getRow()) != 1) { return true; } return false; } -} +} \ No newline at end of file diff --git a/src/main/java/domain/strategy/HorseMoveStrategy.java b/src/main/java/domain/strategy/HorseMoveStrategy.java index 31175147c7..a9e9288b9b 100644 --- a/src/main/java/domain/strategy/HorseMoveStrategy.java +++ b/src/main/java/domain/strategy/HorseMoveStrategy.java @@ -1,26 +1,44 @@ package domain.strategy; -import domain.Board; +import domain.Piece; import domain.vo.Position; +import java.util.List; +import java.util.Map; + public class HorseMoveStrategy implements MoveStrategy { @Override - public boolean canMove(final Position from, final Position to, final Board board) { - if (isNotCorrectPath(from, to)) + public List getPath(final Position from, final Position to) { + if (isNotCorrectPath(from, to)) { + return List.of(); + } + + int nx = to.getRow() - from.getRow(); + int ny = to.getCol() - from.getCol(); + Position mid = Position.of(from.getRow() + nx / 2, from.getCol() + ny / 2); + return List.of(mid, to); + } + + @Override + public boolean canMove(final Piece mover, final Position from, final Position to, final Map piecesOnPath) { + if (isNotCorrectPath(from, to)) { return false; + } int nx = to.getRow() - from.getRow(); int ny = to.getCol() - from.getCol(); + Position mid = Position.of(from.getRow() + nx / 2, from.getCol() + ny / 2); - if (board.isExistPosition(Position.of((from.getRow() + nx / 2), (from.getCol() + ny / 2)))) { + if (piecesOnPath.containsKey(mid)) { return false; } - if (board.isAnotherTeam(from, to)) { + + Piece target = piecesOnPath.get(to); + if (target == null) { return true; } - - return false; + return mover.isAnotherTeam(target); } private boolean isNotCorrectPath(final Position from, final Position to) { @@ -29,4 +47,4 @@ private boolean isNotCorrectPath(final Position from, final Position to) { return !((rowDiff == 1 && colDiff == 2) || (rowDiff == 2 && colDiff == 1)); } -} +} \ No newline at end of file diff --git a/src/main/java/domain/strategy/MoveStrategy.java b/src/main/java/domain/strategy/MoveStrategy.java index 5f9dcb5789..af0cdceea3 100644 --- a/src/main/java/domain/strategy/MoveStrategy.java +++ b/src/main/java/domain/strategy/MoveStrategy.java @@ -1,9 +1,14 @@ package domain.strategy; -import domain.Board; +import domain.Piece; import domain.vo.Position; +import java.util.List; +import java.util.Map; + public interface MoveStrategy { - boolean canMove(final Position from, final Position to, final Board board); -} + List getPath(final Position from, final Position to); + + boolean canMove(final Piece mover, final Position from, final Position to, final Map piecesOnPath); +} \ No newline at end of file diff --git a/src/main/java/domain/strategy/SoldierMoveStrategy.java b/src/main/java/domain/strategy/SoldierMoveStrategy.java index 96cae1bba9..5efd816787 100644 --- a/src/main/java/domain/strategy/SoldierMoveStrategy.java +++ b/src/main/java/domain/strategy/SoldierMoveStrategy.java @@ -1,32 +1,41 @@ package domain.strategy; -import domain.Board; +import domain.Piece; import domain.Team; import domain.vo.Position; +import java.util.List; +import java.util.Map; + public class SoldierMoveStrategy implements MoveStrategy { @Override - public boolean canMove(final Position from, final Position to, final Board board) { - if (isNotCorrectPath(from, to)) - return false; + public List getPath(final Position from, final Position to) { + if (isNotCorrectPath(from, to)) { + return List.of(); + } + return List.of(to); + } - if (isWithdraw(from, to, board)) + @Override + public boolean canMove(final Piece mover, final Position from, final Position to, final Map piecesOnPath) { + if (isNotCorrectPath(from, to)) { return false; + } - if (board.isAnotherTeam(from, to)) { - return true; + if (isWithdraw(from, to, mover)) { + return false; } - if (!board.isExistPosition(to)) { + Piece target = piecesOnPath.get(to); + if (target == null) { return true; } - - return false; + return mover.isAnotherTeam(target); } - private boolean isWithdraw(final Position from, final Position to, final Board board) { - Team team = board.findPieceByPosition(from).get().getTeam(); + private boolean isWithdraw(final Position from, final Position to, final Piece mover) { + Team team = mover.getTeam(); if (team == Team.CHU && from.getRow() - to.getRow() == 1) { return true; } @@ -53,4 +62,4 @@ private boolean isNotCorrectPath(final Position from, final Position to) { return false; } -} +} \ No newline at end of file diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 1af9f571e0..767436ecea 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -40,7 +40,7 @@ public void printBoard(Map board) { System.out.print(color + type + RESET_COLOR + " "); } else { - System.out.print("· "); + System.out.print("+ "); } } System.out.println(); diff --git a/src/test/java/domain/FixedMoveStrategy.java b/src/test/java/domain/FixedMoveStrategy.java deleted file mode 100644 index c880828175..0000000000 --- a/src/test/java/domain/FixedMoveStrategy.java +++ /dev/null @@ -1,12 +0,0 @@ -package domain; - -import domain.strategy.MoveStrategy; -import domain.vo.Position; - -public class FixedMoveStrategy implements MoveStrategy { - - @Override - public boolean canMove(Position from, Position to, Board board) { - return true; - } -} diff --git a/src/test/java/domain/strategy/CannonMoveStrategyTest.java b/src/test/java/domain/strategy/CannonMoveStrategyTest.java index 3bdb3c299a..49a33962b7 100644 --- a/src/test/java/domain/strategy/CannonMoveStrategyTest.java +++ b/src/test/java/domain/strategy/CannonMoveStrategyTest.java @@ -6,7 +6,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.util.HashMap; import java.util.Map; class CannonMoveStrategyTest { @@ -16,36 +15,27 @@ class CannonMoveStrategyTest { void 초나라_포_정상_이동() { // given MoveStrategy strategy = new CannonMoveStrategy(); - Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER)); + Piece mover = Piece.of(Team.CHU, Type.CANNON); + Piece jumpPiece = Piece.of(Team.CHU, Type.SOLDIER); - Board board = BoardFactory.of(boardMapper); - - // when Position from = Position.of(2, 1); Position to = Position.of(4, 1); // then - Assertions.assertTrue(strategy.canMove(from, to, board)); + Assertions.assertTrue(strategy.canMove(mover, from, to, Map.of(Position.of(3, 1), jumpPiece))); } @Test @DisplayName("한나라 포의 이동 경로에 다른 기물이 없으면 이동하지 못한다.") void 포의_이동_경로에_다른_기물이_없으면_이동_불가() { // given - Map boardMapper = new HashMap<>(); Piece cannon = Piece.of(Team.CHU, Type.CANNON); - boardMapper.put(Position.of(2, 1), cannon); - - Board board = BoardFactory.of(boardMapper); - // when Position from = Position.of(2, 1); Position to = Position.of(5, 1); // then - Assertions.assertFalse(cannon.canMovePiece(from, to, board)); + Assertions.assertFalse(cannon.canMovePiece(from, to, Map.of())); } @Test @@ -53,19 +43,16 @@ class CannonMoveStrategyTest { void 초나라_포_이동_경로에_기물이_둘_이상_있으면_이동_불가() { // given MoveStrategy strategy = new CannonMoveStrategy(); - Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER)); - boardMapper.put(Position.of(4, 1), Piece.of(Team.CHU, Type.SOLDIER)); + Piece mover = Piece.of(Team.CHU, Type.CANNON); + Piece soldier1 = Piece.of(Team.CHU, Type.SOLDIER); + Piece soldier2 = Piece.of(Team.CHU, Type.SOLDIER); - Board board = BoardFactory.of(boardMapper); - - // when Position from = Position.of(2, 1); Position to = Position.of(5, 1); // then - Assertions.assertFalse(strategy.canMove(from, to, board)); + Assertions.assertFalse(strategy.canMove(mover, from, to, + Map.of(Position.of(3, 1), soldier1, Position.of(4, 1), soldier2))); } @Test @@ -73,19 +60,16 @@ class CannonMoveStrategyTest { void 포_목적지에_같은_팀_기물이_있으면_이동_불가() { // given MoveStrategy strategy = new CannonMoveStrategy(); - Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER)); - boardMapper.put(Position.of(5, 1), Piece.of(Team.CHU, Type.SOLDIER)); - - Board board = BoardFactory.of(boardMapper); + Piece mover = Piece.of(Team.CHU, Type.CANNON); + Piece jumpPiece = Piece.of(Team.CHU, Type.SOLDIER); + Piece target = Piece.of(Team.CHU, Type.SOLDIER); - // when Position from = Position.of(2, 1); Position to = Position.of(5, 1); // then - Assertions.assertFalse(strategy.canMove(from, to, board)); + Assertions.assertFalse(strategy.canMove(mover, from, to, + Map.of(Position.of(3, 1), jumpPiece, to, target))); } @Test @@ -93,19 +77,16 @@ class CannonMoveStrategyTest { void 목적지에_포가_있으면_이동_불가() { // given MoveStrategy strategy = new CannonMoveStrategy(); - Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER)); - boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.CANNON)); + Piece mover = Piece.of(Team.CHU, Type.CANNON); + Piece jumpPiece = Piece.of(Team.CHU, Type.SOLDIER); + Piece targetCannon = Piece.of(Team.HAN, Type.CANNON); - Board board = BoardFactory.of(boardMapper); - - // when Position from = Position.of(2, 1); Position to = Position.of(5, 1); // then - Assertions.assertFalse(strategy.canMove(from, to, board)); + Assertions.assertFalse(strategy.canMove(mover, from, to, + Map.of(Position.of(3, 1), jumpPiece, to, targetCannon))); } @Test @@ -113,19 +94,16 @@ class CannonMoveStrategyTest { void 포_목적지에_다른_팀_기물이_있으면_이동_가능() { // given MoveStrategy strategy = new CannonMoveStrategy(); - Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.SOLDIER)); - boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.SOLDIER)); - - Board board = BoardFactory.of(boardMapper); + Piece mover = Piece.of(Team.CHU, Type.CANNON); + Piece jumpPiece = Piece.of(Team.CHU, Type.SOLDIER); + Piece target = Piece.of(Team.HAN, Type.SOLDIER); - // when Position from = Position.of(2, 1); Position to = Position.of(5, 1); // then - Assertions.assertTrue(strategy.canMove(from, to, board)); + Assertions.assertTrue(strategy.canMove(mover, from, to, + Map.of(Position.of(3, 1), jumpPiece, to, target))); } @Test @@ -133,18 +111,14 @@ class CannonMoveStrategyTest { void 포의_이동_경로에_포가_있으면_이동_불가() { // given MoveStrategy strategy = new CannonMoveStrategy(); - Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(2, 1), Piece.of(Team.CHU, Type.CANNON)); - boardMapper.put(Position.of(3, 1), Piece.of(Team.CHU, Type.CANNON)); - boardMapper.put(Position.of(5, 1), Piece.of(Team.HAN, Type.SOLDIER)); - - Board board = BoardFactory.of(boardMapper); + Piece mover = Piece.of(Team.CHU, Type.CANNON); + Piece pathCannon = Piece.of(Team.CHU, Type.CANNON); - // when Position from = Position.of(2, 1); Position to = Position.of(5, 1); // then - Assertions.assertFalse(strategy.canMove(from, to, board)); + Assertions.assertFalse(strategy.canMove(mover, from, to, + Map.of(Position.of(3, 1), pathCannon))); } } diff --git a/src/test/java/domain/strategy/ChariotMoveStrategyTest.java b/src/test/java/domain/strategy/ChariotMoveStrategyTest.java index 043e784a9d..a47cda8456 100644 --- a/src/test/java/domain/strategy/ChariotMoveStrategyTest.java +++ b/src/test/java/domain/strategy/ChariotMoveStrategyTest.java @@ -1,70 +1,59 @@ package domain.strategy; -import domain.Board; -import domain.BoardFactory; import domain.Piece; import domain.Team; import domain.Type; import domain.vo.Position; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.TreeMap; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.Map; + class ChariotMoveStrategyTest { Piece chariotPiece; - Board board; + Piece horsePiece; + Piece elephantPiece; @BeforeEach void setUp() { chariotPiece = Piece.of(Team.CHU, Type.CHARIOT); - Piece horsePiece = Piece.of(Team.CHU, Type.HORSE); - Piece elephantPiece = Piece.of(Team.HAN, Type.ELEPHANT); - Map boardMapper = new HashMap<>(); - boardMapper.put(Position.of(0, 0), chariotPiece); - boardMapper.put(Position.of(3, 0), horsePiece); - boardMapper.put(Position.of(0, 3), elephantPiece); - board = BoardFactory.of(boardMapper); + horsePiece = Piece.of(Team.CHU, Type.HORSE); + elephantPiece = Piece.of(Team.HAN, Type.ELEPHANT); } @Test @DisplayName("차의 직선 이동 경로에 기물이 없으면 직선 이동한다.") void 차_직선_이동() { // given - // when Position from = Position.of(0, 0); Position to = Position.of(2, 0); // then - Assertions.assertTrue(chariotPiece.canMovePiece(from, to, board)); + Assertions.assertTrue(chariotPiece.canMovePiece(from, to, Map.of())); } @Test @DisplayName("이동 목적지에 같은 팀 기물이 있으면 직선 이동하지 않는다.") void 차_목적지에_같은_팀_기물이_있으면_이동_불가() { // given - // when Position from = Position.of(0, 0); Position to = Position.of(3, 0); // then - Assertions.assertFalse(chariotPiece.canMovePiece(from, to, board)); + Assertions.assertFalse(chariotPiece.canMovePiece(from, to, Map.of(to, horsePiece))); } @Test @DisplayName("이동 목적지에 다른 팀 기물이 있으면 직선 이동한다.") void 차_목적지에_다른_팀_기물이_있으면_이동_가능() { // given - // when Position from = Position.of(0, 0); Position to = Position.of(0, 3); // then - Assertions.assertTrue(chariotPiece.canMovePiece(from, to, board)); + Assertions.assertTrue(chariotPiece.canMovePiece(from, to, Map.of(to, elephantPiece))); } } diff --git a/src/test/java/domain/strategy/ElephantMoveStrategyTest.java b/src/test/java/domain/strategy/ElephantMoveStrategyTest.java index 5f0c51d0d7..8578d9f231 100644 --- a/src/test/java/domain/strategy/ElephantMoveStrategyTest.java +++ b/src/test/java/domain/strategy/ElephantMoveStrategyTest.java @@ -1,12 +1,15 @@ package domain.strategy; -import domain.Board; -import domain.BoardFactory; +import domain.Piece; +import domain.Team; +import domain.Type; import domain.vo.Position; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.Map; + class ElephantMoveStrategyTest { @Test @@ -14,14 +17,13 @@ class ElephantMoveStrategyTest { void 초나라_상_정상_이동() { // given MoveStrategy strategy = new ElephantMoveStrategy(); - Board board = BoardFactory.setUp(); + Piece mover = Piece.of(Team.CHU, Type.ELEPHANT); - // when Position from = Position.of(0, 1); Position to = Position.of(3, 3); // then - Assertions.assertTrue(strategy.canMove(from, to, board)); + Assertions.assertTrue(strategy.canMove(mover, from, to, Map.of())); } @Test @@ -29,14 +31,13 @@ class ElephantMoveStrategyTest { void 한나라_상_정상_이동() { // given MoveStrategy strategy = new ElephantMoveStrategy(); - Board board = BoardFactory.setUp(); + Piece mover = Piece.of(Team.HAN, Type.ELEPHANT); - // when Position from = Position.of(9, 1); Position to = Position.of(6, 3); // then - Assertions.assertTrue(strategy.canMove(from, to, board)); + Assertions.assertTrue(strategy.canMove(mover, from, to, Map.of())); } @Test @@ -44,14 +45,15 @@ class ElephantMoveStrategyTest { void 초나라_상_이동_경로에_기물이_있으면_이동_불가() { // given MoveStrategy strategy = new ElephantMoveStrategy(); - Board board = BoardFactory.setUp(); + Piece mover = Piece.of(Team.CHU, Type.ELEPHANT); + Piece blockingPiece = Piece.of(Team.CHU, Type.HORSE); - // when Position from = Position.of(0, 1); Position to = Position.of(2, 4); + Position mid1 = Position.of(0, 2); // then - Assertions.assertFalse(strategy.canMove(from, to, board)); + Assertions.assertFalse(strategy.canMove(mover, from, to, Map.of(mid1, blockingPiece))); } @Test @@ -59,14 +61,14 @@ class ElephantMoveStrategyTest { void 상_목적지에_같은_팀_기물이_있으면_이동_불가() { // given MoveStrategy strategy = new ElephantMoveStrategy(); - Board board = BoardFactory.setUp(); + Piece mover = Piece.of(Team.CHU, Type.ELEPHANT); + Piece target = Piece.of(Team.CHU, Type.SOLDIER); - // when - Position from = Position.of(6, 1); - Position to = Position.of(3, 4); + Position from = Position.of(0, 1); + Position to = Position.of(3, 3); // then - Assertions.assertFalse(strategy.canMove(from, to, board)); + Assertions.assertFalse(strategy.canMove(mover, from, to, Map.of(to, target))); } @Test @@ -74,13 +76,13 @@ class ElephantMoveStrategyTest { void 상_목적지에_다른_팀_기물이_있으면_이동_가능() { // given MoveStrategy strategy = new ElephantMoveStrategy(); - Board board = BoardFactory.setUp(); + Piece mover = Piece.of(Team.CHU, Type.ELEPHANT); + Piece target = Piece.of(Team.HAN, Type.SOLDIER); - // when Position from = Position.of(3, 4); Position to = Position.of(6, 2); // then - Assertions.assertTrue(strategy.canMove(from, to, board)); + Assertions.assertTrue(strategy.canMove(mover, from, to, Map.of(to, target))); } } diff --git a/src/test/java/domain/strategy/GeneralMoveStrategyTest.java b/src/test/java/domain/strategy/GeneralMoveStrategyTest.java index ae1c4f26f4..6121d83ef3 100644 --- a/src/test/java/domain/strategy/GeneralMoveStrategyTest.java +++ b/src/test/java/domain/strategy/GeneralMoveStrategyTest.java @@ -7,63 +7,51 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.util.HashMap; import java.util.Map; class GeneralMoveStrategyTest { MoveStrategy strategy; - Map boardMapper; + Piece mover; @BeforeEach void setUp() { strategy = new GeneralMoveStrategy(); - boardMapper = new HashMap<>(); - boardMapper.put(Position.of(1, 4), Piece.of(Team.CHU, Type.GENERAL)); + mover = Piece.of(Team.CHU, Type.GENERAL); } @Test @DisplayName("궁의 목적지에 기물이 없으면 이동한다.") void 궁_정상_이동() { // given - Board board = BoardFactory.of(boardMapper); - - // when Position from = Position.of(1, 4); Position to = Position.of(1, 5); - // then - Assertions.assertTrue(strategy.canMove(from, to, board)); + // when & then + Assertions.assertTrue(strategy.canMove(mover, from, to, Map.of())); } @Test @DisplayName("궁의 목적지에 같은 팀 기물이 있으면 이동하지 않는다.") void 궁_목적지에_같은_팀_기물이_있으면_이동_불가() { // given - boardMapper.put(Position.of(1, 5), Piece.of(Team.CHU, Type.SOLDIER)); - Board board = BoardFactory.of(boardMapper); - - // when Position from = Position.of(1, 4); Position to = Position.of(1, 5); + Piece target = Piece.of(Team.CHU, Type.SOLDIER); - // then - Assertions.assertFalse(strategy.canMove(from, to, board)); + // when & then + Assertions.assertFalse(strategy.canMove(mover, from, to, Map.of(to, target))); } - @Test @DisplayName("궁의 목적지에 다른 팀 기물이 있으면 이동한다.") void 궁_목적지에_다른_팀_기물이_있으면_정상_이동() { // given - boardMapper.put(Position.of(1, 5), Piece.of(Team.HAN, Type.SOLDIER)); - Board board = BoardFactory.of(boardMapper); - - // when Position from = Position.of(1, 4); Position to = Position.of(1, 5); + Piece target = Piece.of(Team.HAN, Type.SOLDIER); - // then - Assertions.assertTrue(strategy.canMove(from, to, board)); + // when & then + Assertions.assertTrue(strategy.canMove(mover, from, to, Map.of(to, target))); } } diff --git a/src/test/java/domain/strategy/GuardMoveStrategyTest.java b/src/test/java/domain/strategy/GuardMoveStrategyTest.java index c086948e02..fd741ccf27 100644 --- a/src/test/java/domain/strategy/GuardMoveStrategyTest.java +++ b/src/test/java/domain/strategy/GuardMoveStrategyTest.java @@ -1,17 +1,15 @@ package domain.strategy; -import domain.Board; -import domain.BoardFactory; import domain.Piece; import domain.Team; import domain.Type; import domain.vo.Position; -import java.util.LinkedHashMap; -import java.util.Map; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.Map; + class GuardMoveStrategyTest { @Test @@ -19,68 +17,52 @@ class GuardMoveStrategyTest { void 사_정상_이동() { // given MoveStrategy strategy = new GuardMoveStrategy(); - Board board = BoardFactory.setUp(); + Piece mover = Piece.of(Team.CHU, Type.GUARD); - // when Position position = Position.of(0, 3); Position targetPosition = Position.of(1, 3); - // then - Assertions.assertTrue(strategy.canMove(position, targetPosition, board)); + // when & then + Assertions.assertTrue(strategy.canMove(mover, position, targetPosition, Map.of())); } @Test @DisplayName("사의 목적지에 같은 팀 기물이 있으면 이동하지 않는다.") void 사_목적지에_같은_팀_기물이_있으면_이동_불가() { // given - Map PositionPiecePair = new LinkedHashMap<>(); Piece guardPiece = Piece.of(Team.CHU, Type.GUARD); - PositionPiecePair.put(Position.of(0, 3), guardPiece); - PositionPiecePair.put(Position.of(0, 2), guardPiece); - Board board = Board.of(PositionPiecePair); Position position = Position.of(0, 3); Position targetPosition = Position.of(0, 2); - // when - // then - Assertions.assertFalse(guardPiece.canMovePiece(position, targetPosition, board)); + // when & then + Assertions.assertFalse(guardPiece.canMovePiece(position, targetPosition, Map.of(targetPosition, guardPiece))); } - @Test @DisplayName("사의 목적지에 다른 팀 기물이 있으면 이동한다.") void 사_목적지에_다른_팀_기물이_있으면_정상_이동() { // given - Map positionPiecePair = new LinkedHashMap<>(); Piece guardPiece = Piece.of(Team.CHU, Type.GUARD); - positionPiecePair.put(Position.of(0, 3), guardPiece); Piece soldierPiece = Piece.of(Team.HAN, Type.SOLDIER); - positionPiecePair.put(Position.of(1, 3), soldierPiece); - Board board = Board.of(positionPiecePair); Position position = Position.of(0, 3); Position targetPosition = Position.of(1, 3); - // when - // then - Assertions.assertTrue(guardPiece.canMovePiece(position, targetPosition, board)); + // when & then + Assertions.assertTrue(guardPiece.canMovePiece(position, targetPosition, Map.of(targetPosition, soldierPiece))); } @Test @DisplayName("사가 궁성 외부 대각선으로 이동하면 예외를 발생한다.") void 사_궁성_밖_대각선_이동_불가() { // given - Map positionPiecePair = new LinkedHashMap<>(); Piece guardPiece = Piece.of(Team.CHU, Type.GUARD); - positionPiecePair.put(Position.of(0, 3), guardPiece); - Board board = Board.of(positionPiecePair); Position position = Position.of(0, 3); Position targetPosition = Position.of(1, 2); - // when - // then - Assertions.assertFalse(guardPiece.canMovePiece(position, targetPosition, board)); + // when & then + Assertions.assertFalse(guardPiece.canMovePiece(position, targetPosition, Map.of())); } } diff --git a/src/test/java/domain/strategy/HorseMoveStrategyTest.java b/src/test/java/domain/strategy/HorseMoveStrategyTest.java index a83113d653..981e6df350 100644 --- a/src/test/java/domain/strategy/HorseMoveStrategyTest.java +++ b/src/test/java/domain/strategy/HorseMoveStrategyTest.java @@ -1,12 +1,14 @@ package domain.strategy; -import domain.Board; -import domain.BoardFactory; +import domain.Piece; +import domain.Team; +import domain.Type; import domain.vo.Position; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.Map; class HorseMoveStrategyTest { @@ -15,14 +17,13 @@ class HorseMoveStrategyTest { void 초나라_마_정상_이동() { // given MoveStrategy strategy = new HorseMoveStrategy(); - Board board = BoardFactory.setUp(); + Piece mover = Piece.of(Team.CHU, Type.HORSE); - // when Position from = Position.of(0, 2); Position to = Position.of(2, 3); // then - Assertions.assertTrue(strategy.canMove(from, to, board)); + Assertions.assertTrue(strategy.canMove(mover, from, to, Map.of())); } @Test @@ -30,29 +31,29 @@ class HorseMoveStrategyTest { void 한나라_마_정상_이동() { // given MoveStrategy strategy = new HorseMoveStrategy(); - Board board = BoardFactory.setUp(); + Piece mover = Piece.of(Team.HAN, Type.HORSE); - // when Position from = Position.of(9, 2); Position to = Position.of(7, 3); // then - Assertions.assertTrue(strategy.canMove(from, to, board)); + Assertions.assertTrue(strategy.canMove(mover, from, to, Map.of())); } @Test @DisplayName("초나라 마의 이동 경로에 기물이 있으면 이동하지 않는다.") void 초나라_마_이동_경로에_기물이_있으면_이동_불가() { // given - MoveStrategy strategy = new ElephantMoveStrategy(); - Board board = BoardFactory.setUp(); + MoveStrategy strategy = new HorseMoveStrategy(); + Piece mover = Piece.of(Team.CHU, Type.HORSE); + Piece blockingPiece = Piece.of(Team.CHU, Type.SOLDIER); - // when Position from = Position.of(0, 2); - Position to = Position.of(1, 4); + Position to = Position.of(2, 3); + Position mid = Position.of(1, 2); // then - Assertions.assertFalse(strategy.canMove(from, to, board)); + Assertions.assertFalse(strategy.canMove(mover, from, to, Map.of(mid, blockingPiece))); } @Test @@ -60,13 +61,13 @@ class HorseMoveStrategyTest { void 마_목적지에_같은_팀_기물이_있으면_이동_불가() { // given MoveStrategy strategy = new HorseMoveStrategy(); - Board board = BoardFactory.setUp(); + Piece mover = Piece.of(Team.CHU, Type.HORSE); + Piece target = Piece.of(Team.CHU, Type.CANNON); - // when Position from = Position.of(0, 2); Position to = Position.of(2, 1); // then - Assertions.assertFalse(strategy.canMove(from, to, board)); + Assertions.assertFalse(strategy.canMove(mover, from, to, Map.of(to, target))); } -} +} \ No newline at end of file diff --git a/src/test/java/domain/strategy/SoldierMoveStrategyTest.java b/src/test/java/domain/strategy/SoldierMoveStrategyTest.java index a31eec9c11..90c67e8584 100644 --- a/src/test/java/domain/strategy/SoldierMoveStrategyTest.java +++ b/src/test/java/domain/strategy/SoldierMoveStrategyTest.java @@ -6,7 +6,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.util.HashMap; import java.util.Map; class SoldierMoveStrategyTest { @@ -15,93 +14,66 @@ class SoldierMoveStrategyTest { @DisplayName("졸의 목적지에 기물이 없으면 이동한다.") void 졸_정상_이동() { // given - Map boardMapper = new HashMap<>(); Piece soldierPiece = Piece.of(Team.CHU, Type.SOLDIER); - boardMapper.put(Position.of(3, 4), soldierPiece); - Board board = BoardFactory.of(boardMapper); - - // when Position position = Position.of(3, 4); Position targetPosition = Position.of(4, 4); // then - Assertions.assertTrue(soldierPiece.canMovePiece(position, targetPosition, board)); + Assertions.assertTrue(soldierPiece.canMovePiece(position, targetPosition, Map.of())); } @Test @DisplayName("졸의 목적지에 같은 팀 기물이 있으면 이동하지 않는다.") void 졸_목적지에_같은_팀_기물이_있으면_이동_불가() { // given - Map boardMapper = new HashMap<>(); Piece soldierPiece = Piece.of(Team.CHU, Type.SOLDIER); - boardMapper.put(Position.of(3, 4), soldierPiece); - boardMapper.put(Position.of(4, 4), soldierPiece); - - Board board = BoardFactory.of(boardMapper); + Piece sameTeamPiece = Piece.of(Team.CHU, Type.SOLDIER); - // when Position position = Position.of(3, 4); Position targetPosition = Position.of(4, 4); // then - Assertions.assertFalse(soldierPiece.canMovePiece(position, targetPosition, board)); + Assertions.assertFalse(soldierPiece.canMovePiece(position, targetPosition, Map.of(targetPosition, sameTeamPiece))); } - @Test @DisplayName("졸의 목적지에 다른 팀 기물이 있으면 이동한다.") void 졸_목적지에_다른_팀_기물이_있으면_정상_이동() { // given - Map boardMapper = new HashMap<>(); Piece chuSoldierPiece = Piece.of(Team.CHU, Type.SOLDIER); - boardMapper.put(Position.of(3, 4), chuSoldierPiece); Piece hanSoldierPiece = Piece.of(Team.HAN, Type.SOLDIER); - boardMapper.put(Position.of(4, 4), hanSoldierPiece); - Board board = BoardFactory.of(boardMapper); - - // when Position position = Position.of(3, 4); Position targetPosition = Position.of(4, 4); // then - Assertions.assertTrue(chuSoldierPiece.canMovePiece(position, targetPosition, board)); + Assertions.assertTrue(chuSoldierPiece.canMovePiece(position, targetPosition, Map.of(targetPosition, hanSoldierPiece))); } @Test @DisplayName("초나라 졸의 이동 경로가 후퇴이면 이동할 수 없다.") void 초나라_졸의_이동_경로가_후퇴이면_이동_불가() { // given - Map boardMapper = new HashMap<>(); Piece chuSoldierPiece = Piece.of(Team.CHU, Type.SOLDIER); - boardMapper.put(Position.of(3, 4), chuSoldierPiece); - - Board board = BoardFactory.of(boardMapper); - // when Position position = Position.of(3, 4); Position targetPosition = Position.of(2, 4); // then - Assertions.assertFalse(chuSoldierPiece.canMovePiece(position, targetPosition, board)); + Assertions.assertFalse(chuSoldierPiece.canMovePiece(position, targetPosition, Map.of())); } @Test @DisplayName("한나라 졸의 이동 경로가 후퇴이면 이동할 수 없다.") void 한나라_졸의_이동_경로가_후퇴이면_이동_불가() { // given - Map boardMapper = new HashMap<>(); Piece hanSoldierPiece = Piece.of(Team.HAN, Type.SOLDIER); - boardMapper.put(Position.of(6, 4), hanSoldierPiece); - - Board board = BoardFactory.of(boardMapper); - // when Position position = Position.of(6, 4); Position targetPosition = Position.of(7, 4); // then - Assertions.assertFalse(hanSoldierPiece.canMovePiece(position, targetPosition, board)); + Assertions.assertFalse(hanSoldierPiece.canMovePiece(position, targetPosition, Map.of())); } } From d8f08d3bda069ce2572932441b7f37b8050ae8c5 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Sat, 4 Apr 2026 16:27:59 +0900 Subject: [PATCH 57/87] =?UTF-8?q?feat:=20=EA=B8=B0=EB=AC=BC=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EC=9E=85=EB=A0=A5=EC=9D=B4=20=EB=81=9D=EB=82=98?= =?UTF-8?q?=EB=A9=B4=20=EB=A7=A4=EB=B2=88=20=EB=AC=BB=EB=8D=98=20retry=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=A0=9C=EA=B1=B0,=20=ED=95=AD=EB=B3=B5?= =?UTF-8?q?=20=EC=8B=9C=20=EA=B2=8C=EC=9E=84=20=EC=A2=85=EB=A3=8C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/JanggiController.java | 2 +- src/main/java/view/InputView.java | 26 ++++--------------- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/src/main/java/controller/JanggiController.java b/src/main/java/controller/JanggiController.java index 1bfc2c393f..500cc5a386 100644 --- a/src/main/java/controller/JanggiController.java +++ b/src/main/java/controller/JanggiController.java @@ -28,7 +28,7 @@ public void run() { int turnCount = 0; turnCount = movePosition(board, turnCount); - while (inputView.readRetryCommand()) { + while (true) { turnCount = movePosition(board, turnCount); } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 1af5a84077..f7aaa1c44a 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -42,34 +42,18 @@ public Position readTargetPosition() { } } - public Boolean readRetryCommand() { - System.out.println("계속 하시겠습니까?(y/n)"); - - String input = scanner.nextLine(); - try { - validateRetryCommand(input); - } catch (Exception e) { - System.out.println(e.getMessage()); - System.out.println(); - return readRetryCommand(); - } - - return input.equals("y"); - } - - public String readArrangement(Team team) { + public String readArrangement(final Team team) { System.out.println(team.getName() + "나라의 판차림 방식을 선택해주세요.(상마상마, 마상마상, 마상상마, 상마마상)"); return scanner.nextLine(); } - private void validateRetryCommand(final String input) { - if (!input.equals("y") && !input.equals("n")) { - throw new IllegalArgumentException("[ERROR] y 또는 n만 입력 가능합니다."); + private void validatePositionFormat(final String input) { + if (input.equals("항복")) { + System.out.println("플레이어의 항복으로 게임을 종료합니다."); + System.exit(0); } - } - private void validatePositionFormat(final String input) { if (!input.matches(POSITION_PATTERN)) { throw new IllegalArgumentException("[ERROR] 입력 형식이 잘못되었습니다. '숫자 공백 숫자' 형식이어야 합니다."); } From 92e43d7cb07df7af7e3409701b71454d9ac256f0 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Sat, 4 Apr 2026 17:15:34 +0900 Subject: [PATCH 58/87] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9D=98=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=EA=B7=9C=EC=B9=99=EC=97=90=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EC=A4=91=EB=B3=B5=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/domain/strategy/GuardMoveStrategy.java | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/main/java/domain/strategy/GuardMoveStrategy.java b/src/main/java/domain/strategy/GuardMoveStrategy.java index 65d6ce5f8f..1504f1271c 100644 --- a/src/main/java/domain/strategy/GuardMoveStrategy.java +++ b/src/main/java/domain/strategy/GuardMoveStrategy.java @@ -30,18 +30,6 @@ public boolean canMove(final Piece mover, final Position from, final Position to } private boolean isNotCorrectPath(final Position from, final Position to) { - if (Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) != 1) { - return true; - } - - if (from.getRow() == to.getRow() && Math.abs(from.getCol() - to.getCol()) != 1) { - return true; - } - - if (from.getCol() == to.getCol() && Math.abs(from.getRow() - to.getRow()) != 1) { - return true; - } - - return false; + return Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) != 1; } } \ No newline at end of file From e89eae06821d40a725266d456fe06a7ec312f355 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Sun, 5 Apr 2026 20:22:51 +0900 Subject: [PATCH 59/87] =?UTF-8?q?refactor:=20Type(enum)=EC=9D=98=20?= =?UTF-8?q?=EC=A0=84=EB=9E=B5=20=ED=95=84=EB=93=9C=EB=A5=BC=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=20=EC=B0=B8=EC=A1=B0=20=EB=B0=A9=EC=8B=9D?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=8B=A4=ED=96=89=20=EC=8B=9C=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=ED=99=94=20=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Type.java | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/main/java/domain/Type.java b/src/main/java/domain/Type.java index 28476f94f6..e231535e4c 100644 --- a/src/main/java/domain/Type.java +++ b/src/main/java/domain/Type.java @@ -8,27 +8,26 @@ import domain.strategy.HorseMoveStrategy; import domain.strategy.MoveStrategy; import domain.strategy.SoldierMoveStrategy; -import java.util.function.Supplier; public enum Type { - GENERAL("궁", GeneralMoveStrategy::new), - CHARIOT("차", ChariotMoveStrategy::new), - CANNON("포", CannonMoveStrategy::new), - HORSE("마", HorseMoveStrategy::new), - ELEPHANT("상", ElephantMoveStrategy::new), - GUARD("사", GuardMoveStrategy::new), - SOLDIER("졸", SoldierMoveStrategy::new); + GENERAL("궁", new GeneralMoveStrategy()), + CHARIOT("차", new ChariotMoveStrategy()), + CANNON("포", new CannonMoveStrategy()), + HORSE("마", new HorseMoveStrategy()), + ELEPHANT("상", new ElephantMoveStrategy()), + GUARD("사", new GuardMoveStrategy()), + SOLDIER("졸", new SoldierMoveStrategy()); private final String name; - private final Supplier strategySupplier; + private final MoveStrategy strategySupplier; - Type(String name, Supplier strategySupplier) { + Type(String name, MoveStrategy strategySupplier) { this.name = name; this.strategySupplier = strategySupplier; } public MoveStrategy getStrategy() { - return strategySupplier.get(); + return strategySupplier; } public String getName() { From 550fbca73a9ba27767747899f014c019932076f0 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Mon, 6 Apr 2026 14:07:40 +0900 Subject: [PATCH 60/87] =?UTF-8?q?docs:=20=EC=82=AC=EC=9D=B4=ED=81=B42=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EA=B8=B0=EB=8A=A5=20=EB=82=B4=EC=9A=A9=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++++++ src/main/java/domain/Type.java | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e9fa6ae3ae..4eeb8afb74 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,12 @@ - 목적지에 같은 팀 기물이 존재한다면 이동하지 못한다. - 목적지에 다른 팀 기물이 존재한다면 해당 기물을 잡을 수 있다. - 이동할 기물이 포이고 이동 경로에 포를 제외한 다른 기물이 있다면 기물을 넘어서 이동할 수 있다. +- [ ] 기물의 이동에 궁성(宮城) 영역의 규칙을 포함한다. +- [ ] 왕이 잡히는 경우 게임에서 진다. + - 왕이 잡혔을 때 게임을 종료한다. +- [ ] 현재 남아 있는 기물에 대한 점수를 구할수 있어야 한다. +- [ ] 애플리케이션을 재시작하더라도 이전에 하던 장기 게임을 다시 시작할 수 있어야 한다. + - DB를 적용할 때 도메인 객체의 변경을 최소화해야 한다. ### 예외 기능 - [x] 장기판을 벗어나면 예외를 발생한다. diff --git a/src/main/java/domain/Type.java b/src/main/java/domain/Type.java index e231535e4c..f1aaecc0bf 100644 --- a/src/main/java/domain/Type.java +++ b/src/main/java/domain/Type.java @@ -19,15 +19,15 @@ public enum Type { SOLDIER("졸", new SoldierMoveStrategy()); private final String name; - private final MoveStrategy strategySupplier; + private final MoveStrategy strategy; - Type(String name, MoveStrategy strategySupplier) { + Type(String name, MoveStrategy strategy) { this.name = name; - this.strategySupplier = strategySupplier; + this.strategy = strategy; } public MoveStrategy getStrategy() { - return strategySupplier; + return strategy; } public String getName() { From f264ebc88f55edb80b1e88659186590c23c7903c Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Tue, 7 Apr 2026 16:10:57 +0900 Subject: [PATCH 61/87] =?UTF-8?q?feat:=20=EC=A1=B8=EC=9D=98=20=EA=B6=81?= =?UTF-8?q?=EC=84=B1=20=EC=95=88=20=EC=9D=B4=EB=8F=99=20=EA=B7=9C=EC=B9=99?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +- .../domain/strategy/SoldierMoveStrategy.java | 47 +++++++++++++++++-- .../strategy/SoldierMoveStrategyTest.java | 46 +++++++++++++++--- 3 files changed, 85 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 4eeb8afb74..f0d8669efd 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,8 @@ - 목적지에 다른 팀 기물이 존재한다면 해당 기물을 잡을 수 있다. - 이동할 기물이 포이고 이동 경로에 포를 제외한 다른 기물이 있다면 기물을 넘어서 이동할 수 있다. - [ ] 기물의 이동에 궁성(宮城) 영역의 규칙을 포함한다. -- [ ] 왕이 잡히는 경우 게임에서 진다. + - +- [ ] 왕이 잡히는 경우 게임에서 진다. - 왕이 잡혔을 때 게임을 종료한다. - [ ] 현재 남아 있는 기물에 대한 점수를 구할수 있어야 한다. - [ ] 애플리케이션을 재시작하더라도 이전에 하던 장기 게임을 다시 시작할 수 있어야 한다. diff --git a/src/main/java/domain/strategy/SoldierMoveStrategy.java b/src/main/java/domain/strategy/SoldierMoveStrategy.java index 5efd816787..d4f40df022 100644 --- a/src/main/java/domain/strategy/SoldierMoveStrategy.java +++ b/src/main/java/domain/strategy/SoldierMoveStrategy.java @@ -18,11 +18,26 @@ public List getPath(final Position from, final Position to) { } @Override - public boolean canMove(final Piece mover, final Position from, final Position to, final Map piecesOnPath) { + public boolean canMove(final Piece mover, final Position from, final Position to, + final Map piecesOnPath) { if (isNotCorrectPath(from, to)) { return false; } + if ((!isInPalace(from) || !isInPalace(to))) { + if (isDiagonal(from, to)) { + return false; + } + } + + if (isInPalace(from) && isInPalace(to) && isDiagonal(from, to)) { + if (isDiagonal(from, to)) { + return canDiagonalInPalace(from, to); + } + + return false; + } + if (isWithdraw(from, to, mover)) { return false; } @@ -31,6 +46,7 @@ public boolean canMove(final Piece mover, final Position from, final Position to if (target == null) { return true; } + return mover.isAnotherTeam(target); } @@ -48,18 +64,41 @@ private boolean isWithdraw(final Position from, final Position to, final Piece m } private boolean isNotCorrectPath(final Position from, final Position to) { - if (Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) != 1) { + if (Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) > 2) { return true; } - if (from.getRow() == to.getRow() && Math.abs(from.getCol() - to.getCol()) != 1) { + if ((from.getRow() == to.getRow()) && Math.abs(from.getCol() - to.getCol()) >= 2) { return true; } - if (from.getCol() == to.getCol() && Math.abs(from.getRow() - to.getRow()) != 1) { + if ((from.getCol() == to.getCol()) && Math.abs(from.getRow() - to.getCol()) >= 2) { return true; } return false; } + + private boolean isInPalace(Position position) { + int row = position.getRow(); + int column = position.getCol(); + + return (column >= 3 && column <= 5) && ((row >= 0 && row <= 2) || (row >= 7 && row <= 9)); + } + + private boolean canDiagonalInPalace(Position from, Position to) { + if (!isDiagonal(from, to) || !isInPalace(from) || !isInPalace(to)) { + return false; + } + + return isCenterOfPalace(from) || isCenterOfPalace(to); + } + + private boolean isDiagonal(Position from, Position to) { + return Math.abs(from.getRow() - to.getRow()) == 1 && Math.abs(from.getCol() - to.getCol()) == 1; + } + + private boolean isCenterOfPalace(Position position) { + return position.getCol() == 4 && (position.getRow() == 1 || position.getRow() == 8); + } } \ No newline at end of file diff --git a/src/test/java/domain/strategy/SoldierMoveStrategyTest.java b/src/test/java/domain/strategy/SoldierMoveStrategyTest.java index 90c67e8584..df16e2e452 100644 --- a/src/test/java/domain/strategy/SoldierMoveStrategyTest.java +++ b/src/test/java/domain/strategy/SoldierMoveStrategyTest.java @@ -1,8 +1,11 @@ package domain.strategy; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + import domain.*; import domain.vo.Position; -import org.junit.jupiter.api.Assertions; +import java.util.HashMap; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -20,7 +23,7 @@ class SoldierMoveStrategyTest { Position targetPosition = Position.of(4, 4); // then - Assertions.assertTrue(soldierPiece.canMovePiece(position, targetPosition, Map.of())); + assertTrue(soldierPiece.canMovePiece(position, targetPosition, Map.of())); } @Test @@ -34,7 +37,8 @@ class SoldierMoveStrategyTest { Position targetPosition = Position.of(4, 4); // then - Assertions.assertFalse(soldierPiece.canMovePiece(position, targetPosition, Map.of(targetPosition, sameTeamPiece))); + assertFalse( + soldierPiece.canMovePiece(position, targetPosition, Map.of(targetPosition, sameTeamPiece))); } @Test @@ -48,7 +52,8 @@ class SoldierMoveStrategyTest { Position targetPosition = Position.of(4, 4); // then - Assertions.assertTrue(chuSoldierPiece.canMovePiece(position, targetPosition, Map.of(targetPosition, hanSoldierPiece))); + assertTrue( + chuSoldierPiece.canMovePiece(position, targetPosition, Map.of(targetPosition, hanSoldierPiece))); } @Test @@ -61,7 +66,7 @@ class SoldierMoveStrategyTest { Position targetPosition = Position.of(2, 4); // then - Assertions.assertFalse(chuSoldierPiece.canMovePiece(position, targetPosition, Map.of())); + assertFalse(chuSoldierPiece.canMovePiece(position, targetPosition, Map.of())); } @Test @@ -70,10 +75,39 @@ class SoldierMoveStrategyTest { // given Piece hanSoldierPiece = Piece.of(Team.HAN, Type.SOLDIER); + // when Position position = Position.of(6, 4); Position targetPosition = Position.of(7, 4); // then - Assertions.assertFalse(hanSoldierPiece.canMovePiece(position, targetPosition, Map.of())); + assertFalse(hanSoldierPiece.canMovePiece(position, targetPosition, Map.of())); + } + + @Test + @DisplayName("한나라 졸의 이동 경로가 궁성 중앙(1, 4)에서 대각선 전진방향이면 이동한다.") + void 한나라_졸의_이동_경로가_궁성_중앙에서_대각선_전진방향이면_이동한다() { + // given + Piece hanSoldierPiece = Piece.of(Team.HAN, Type.SOLDIER); + Position from = Position.of(1, 4); + Position to = Position.of(0, 3); + HashMap piecesOnPath = new HashMap<>(); + piecesOnPath.put(to, null); + + //when // then + assertTrue(hanSoldierPiece.canMovePiece(from, to, piecesOnPath)); + } + + @Test + @DisplayName("한나라 졸의 이동 경로가 궁성 밖에서 대각선 전진이면 이동할 수 없다.") + void 한나라_졸의_이동_경로가_궁성_밖에서_대각선_전진이면_이동할_수_없다() { + // given + Piece hanSoldierPiece = Piece.of(Team.HAN, Type.SOLDIER); + Position from = Position.of(6 , 4); + Position to = Position.of(5, 3); + HashMap piecesOnPath = new HashMap<>(); + piecesOnPath.put(to, null); + + // when // then + assertFalse(hanSoldierPiece.canMovePiece(from, to, piecesOnPath)); } } From badbe5528cb4f5242b70ba33f7cf7285dc252565 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Tue, 7 Apr 2026 16:53:07 +0900 Subject: [PATCH 62/87] =?UTF-8?q?feat:=20=EA=B6=81=EC=9D=98=20=EA=B6=81?= =?UTF-8?q?=EC=84=B1=20=EC=9D=B4=EB=8F=99=20=EA=B7=9C=EC=B9=99=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/GeneralMoveStrategy.java | 8 +++++ .../domain/strategy/SoldierMoveStrategy.java | 8 ++--- .../strategy/GeneralMoveStrategyTest.java | 31 ++++++++++++++----- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/main/java/domain/strategy/GeneralMoveStrategy.java b/src/main/java/domain/strategy/GeneralMoveStrategy.java index 83683c1da6..0a604dfe5f 100644 --- a/src/main/java/domain/strategy/GeneralMoveStrategy.java +++ b/src/main/java/domain/strategy/GeneralMoveStrategy.java @@ -30,6 +30,9 @@ public boolean canMove(final Piece mover, final Position from, final Position to } private boolean isNotCorrectPath(final Position from, final Position to) { + if (!palaceInRange(to)) { + return true; + } if (from.getRow() == to.getRow() && Math.abs(from.getCol() - to.getCol()) != 1) { return true; } @@ -40,4 +43,9 @@ private boolean isNotCorrectPath(final Position from, final Position to) { return false; } + + private boolean palaceInRange(final Position position) { + return (((0 <= position.getRow() && position.getRow() <= 2) || (7 <= position.getRow() && position.getRow() <= 9)) + && (3 <= position.getCol() && position.getCol() <= 5)); + } } \ No newline at end of file diff --git a/src/main/java/domain/strategy/SoldierMoveStrategy.java b/src/main/java/domain/strategy/SoldierMoveStrategy.java index d4f40df022..0ee582b5c2 100644 --- a/src/main/java/domain/strategy/SoldierMoveStrategy.java +++ b/src/main/java/domain/strategy/SoldierMoveStrategy.java @@ -79,14 +79,14 @@ private boolean isNotCorrectPath(final Position from, final Position to) { return false; } - private boolean isInPalace(Position position) { + private boolean isInPalace(final Position position) { int row = position.getRow(); int column = position.getCol(); return (column >= 3 && column <= 5) && ((row >= 0 && row <= 2) || (row >= 7 && row <= 9)); } - private boolean canDiagonalInPalace(Position from, Position to) { + private boolean canDiagonalInPalace(final Position from, final Position to) { if (!isDiagonal(from, to) || !isInPalace(from) || !isInPalace(to)) { return false; } @@ -94,11 +94,11 @@ private boolean canDiagonalInPalace(Position from, Position to) { return isCenterOfPalace(from) || isCenterOfPalace(to); } - private boolean isDiagonal(Position from, Position to) { + private boolean isDiagonal(final Position from, final Position to) { return Math.abs(from.getRow() - to.getRow()) == 1 && Math.abs(from.getCol() - to.getCol()) == 1; } - private boolean isCenterOfPalace(Position position) { + private boolean isCenterOfPalace(final Position position) { return position.getCol() == 4 && (position.getRow() == 1 || position.getRow() == 8); } } \ No newline at end of file diff --git a/src/test/java/domain/strategy/GeneralMoveStrategyTest.java b/src/test/java/domain/strategy/GeneralMoveStrategyTest.java index 6121d83ef3..91411071b5 100644 --- a/src/test/java/domain/strategy/GeneralMoveStrategyTest.java +++ b/src/test/java/domain/strategy/GeneralMoveStrategyTest.java @@ -1,8 +1,10 @@ package domain.strategy; +import static org.junit.jupiter.api.Assertions.*; + import domain.*; import domain.vo.Position; -import org.junit.jupiter.api.Assertions; +import java.util.HashMap; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -27,8 +29,8 @@ void setUp() { Position from = Position.of(1, 4); Position to = Position.of(1, 5); - // when & then - Assertions.assertTrue(strategy.canMove(mover, from, to, Map.of())); + // when // then + assertTrue(strategy.canMove(mover, from, to, Map.of())); } @Test @@ -39,8 +41,8 @@ void setUp() { Position to = Position.of(1, 5); Piece target = Piece.of(Team.CHU, Type.SOLDIER); - // when & then - Assertions.assertFalse(strategy.canMove(mover, from, to, Map.of(to, target))); + // when // then + assertFalse(strategy.canMove(mover, from, to, Map.of(to, target))); } @Test @@ -51,7 +53,22 @@ void setUp() { Position to = Position.of(1, 5); Piece target = Piece.of(Team.HAN, Type.SOLDIER); - // when & then - Assertions.assertTrue(strategy.canMove(mover, from, to, Map.of(to, target))); + // when // then + assertTrue(strategy.canMove(mover, from, to, Map.of(to, target))); + } + + @Test + @DisplayName("궁의 목적지가 궁성 밖이라면 이동하지 않는다.") + void 궁_목적지가_궁성_밖이라면_이동_불가() { + // given + Position from = Position.of(2, 3); + Position to = Position.of(2, 2); + Piece piece = Piece.of(Team.CHU, Type.GENERAL); + HashMap pieceOfPath = new HashMap<>(); + + pieceOfPath.put(to, null); + + // when // then + assertFalse(piece.canMovePiece(from, to, pieceOfPath)); } } From 345954cddc904ccdb5113bc67f1fedcce497e527 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Tue, 7 Apr 2026 20:41:04 +0900 Subject: [PATCH 63/87] =?UTF-8?q?fix:=20=EC=A1=B8=EC=9D=B4=20=EC=A0=84?= =?UTF-8?q?=EC=A7=84=ED=95=98=EC=A7=80=20=EB=AA=BB=ED=95=98=EB=8D=98=20?= =?UTF-8?q?=EA=B2=83=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/strategy/SoldierMoveStrategy.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/domain/strategy/SoldierMoveStrategy.java b/src/main/java/domain/strategy/SoldierMoveStrategy.java index 0ee582b5c2..3e95766ff6 100644 --- a/src/main/java/domain/strategy/SoldierMoveStrategy.java +++ b/src/main/java/domain/strategy/SoldierMoveStrategy.java @@ -68,11 +68,11 @@ private boolean isNotCorrectPath(final Position from, final Position to) { return true; } - if ((from.getRow() == to.getRow()) && Math.abs(from.getCol() - to.getCol()) >= 2) { + if ((from.getRow() == to.getRow()) && Math.abs(from.getCol() - to.getCol()) != 1) { return true; } - if ((from.getCol() == to.getCol()) && Math.abs(from.getRow() - to.getCol()) >= 2) { + if ((from.getCol() == to.getCol()) && Math.abs(from.getRow() - to.getRow()) != 1) { return true; } From e6def2716c418018d8deb1a17de1653bed867601 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Tue, 7 Apr 2026 22:02:48 +0900 Subject: [PATCH 64/87] =?UTF-8?q?feat:=20=EC=A1=B8=EC=9D=98=20=EA=B6=81?= =?UTF-8?q?=EC=84=B1=20=EC=95=88=20=EB=8C=80=EA=B0=81=EC=84=A0=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EA=B7=9C=EC=B9=99=20=EA=B5=AC=ED=98=84=20=EB=B0=8F?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/SoldierMoveStrategy.java | 32 +++++++++++++++++-- .../strategy/SoldierMoveStrategyTest.java | 16 +++++++++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/main/java/domain/strategy/SoldierMoveStrategy.java b/src/main/java/domain/strategy/SoldierMoveStrategy.java index 3e95766ff6..912a677e63 100644 --- a/src/main/java/domain/strategy/SoldierMoveStrategy.java +++ b/src/main/java/domain/strategy/SoldierMoveStrategy.java @@ -30,12 +30,16 @@ public boolean canMove(final Piece mover, final Position from, final Position to } } - if (isInPalace(from) && isInPalace(to) && isDiagonal(from, to)) { + if (isInPalace(from) && isInPalace(to)) { if (isDiagonal(from, to)) { return canDiagonalInPalace(from, to); } + } - return false; + if (isInPalace(from) && !isInPalace(to)) { + if (isDiagonal(from, to)) { + return false; + } } if (isWithdraw(from, to, mover)) { @@ -47,9 +51,33 @@ public boolean canMove(final Piece mover, final Position from, final Position to return true; } + if (hanSoldierCanDiagonalMoveInPalace(from, to) || chuSoldierCanDiagonalMoveInPalace(from, to)) { + return false; + } + return mover.isAnotherTeam(target); } + private boolean chuSoldierCanDiagonalMoveInPalace(Position from, Position to) { + if ((from.getRow() == 7 && from.getCol() == 4) || (from.getRow() == 8 && from.getCol() == 3) + || (from.getRow() == 8 && from.getCol() == 5)) { + if (isDiagonal(from, to)) { + return true; + } + } + return false; + } + + private boolean hanSoldierCanDiagonalMoveInPalace(Position from, Position to) { + if ((from.getRow() == 2 && from.getCol() == 4) || (from.getRow() == 1 && from.getCol() == 3) + || (from.getRow() == 1 && from.getCol() == 5)) { + if (isDiagonal(from, to)) { + return true; + } + } + return false; + } + private boolean isWithdraw(final Position from, final Position to, final Piece mover) { Team team = mover.getTeam(); if (team == Team.CHU && from.getRow() - to.getRow() == 1) { diff --git a/src/test/java/domain/strategy/SoldierMoveStrategyTest.java b/src/test/java/domain/strategy/SoldierMoveStrategyTest.java index df16e2e452..ec64496b05 100644 --- a/src/test/java/domain/strategy/SoldierMoveStrategyTest.java +++ b/src/test/java/domain/strategy/SoldierMoveStrategyTest.java @@ -102,7 +102,7 @@ class SoldierMoveStrategyTest { void 한나라_졸의_이동_경로가_궁성_밖에서_대각선_전진이면_이동할_수_없다() { // given Piece hanSoldierPiece = Piece.of(Team.HAN, Type.SOLDIER); - Position from = Position.of(6 , 4); + Position from = Position.of(6, 4); Position to = Position.of(5, 3); HashMap piecesOnPath = new HashMap<>(); piecesOnPath.put(to, null); @@ -110,4 +110,18 @@ class SoldierMoveStrategyTest { // when // then assertFalse(hanSoldierPiece.canMovePiece(from, to, piecesOnPath)); } + + @Test + @DisplayName("초나라 졸의 궁성 안에서 궁성 밖 대각선 전진이면 이동할 수 없다.") + void 초나라_졸의_궁성_안에서_궁성_밖_대각선_전진이면_이동할_수_없다() { + // given + Piece chuSoldierPiece = Piece.of(Team.CHU, Type.SOLDIER); + Position from = Position.of(8, 3); + Position to = Position.of(9, 2); + HashMap piecesOnPath = new HashMap<>(); + piecesOnPath.put(to, null); + + // when // then + assertFalse(chuSoldierPiece.canMovePiece(from, to, piecesOnPath)); + } } From bf14656fb054e4861ca95e3425f775976acda42e Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Tue, 7 Apr 2026 22:17:28 +0900 Subject: [PATCH 65/87] =?UTF-8?q?test:=20=EA=B6=81=EC=9D=98=20=EB=B6=88?= =?UTF-8?q?=EA=B0=80=EB=8A=A5=ED=95=9C=20=EB=8C=80=EA=B0=81=EC=84=A0=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/GeneralMoveStrategyTest.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/test/java/domain/strategy/GeneralMoveStrategyTest.java b/src/test/java/domain/strategy/GeneralMoveStrategyTest.java index 91411071b5..81074f2dd0 100644 --- a/src/test/java/domain/strategy/GeneralMoveStrategyTest.java +++ b/src/test/java/domain/strategy/GeneralMoveStrategyTest.java @@ -71,4 +71,19 @@ void setUp() { // when // then assertFalse(piece.canMovePiece(from, to, pieceOfPath)); } + + @Test + @DisplayName("궁의 대각선 이동이 불가능한 위치로 이동 시 이동하지 않는다.") + void 궁_대각선_이동이_불가능한_위치면_이동_불가() { + // given + Position from = Position.of(2, 4); + Position to = Position.of(1, 3); + Piece piece = Piece.of(Team.CHU, Type.GENERAL); + HashMap pieceOfPath = new HashMap<>(); + + pieceOfPath.put(to, null); + + // when // then + assertFalse(piece.canMovePiece(from, to, pieceOfPath)); + } } From 0dd4bac7aa9ca415e92dd0a0e768befeb46811ee Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Tue, 7 Apr 2026 22:36:56 +0900 Subject: [PATCH 66/87] =?UTF-8?q?feat:=20=EA=B6=81=EC=9D=98=20=EB=B6=88?= =?UTF-8?q?=EA=B0=80=EB=8A=A5=ED=95=9C=20=EB=8C=80=EA=B0=81=EC=84=A0=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=EA=B7=9C=EC=B9=99=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/GeneralMoveStrategy.java | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/main/java/domain/strategy/GeneralMoveStrategy.java b/src/main/java/domain/strategy/GeneralMoveStrategy.java index 0a604dfe5f..34769cc7a1 100644 --- a/src/main/java/domain/strategy/GeneralMoveStrategy.java +++ b/src/main/java/domain/strategy/GeneralMoveStrategy.java @@ -17,7 +17,8 @@ public List getPath(final Position from, final Position to) { } @Override - public boolean canMove(final Piece mover, final Position from, final Position to, final Map piecesOnPath) { + public boolean canMove(final Piece mover, final Position from, final Position to, + final Map piecesOnPath) { if (isNotCorrectPath(from, to)) { return false; } @@ -33,6 +34,7 @@ private boolean isNotCorrectPath(final Position from, final Position to) { if (!palaceInRange(to)) { return true; } + if (from.getRow() == to.getRow() && Math.abs(from.getCol() - to.getCol()) != 1) { return true; } @@ -41,11 +43,40 @@ private boolean isNotCorrectPath(final Position from, final Position to) { return true; } + if (hanSoldierCanDiagonalMoveInPalace(from, to) || chuSoldierCanDiagonalMoveInPalace(from, to)) { + return true; + } + return false; } private boolean palaceInRange(final Position position) { - return (((0 <= position.getRow() && position.getRow() <= 2) || (7 <= position.getRow() && position.getRow() <= 9)) + return (((0 <= position.getRow() && position.getRow() <= 2) || (7 <= position.getRow() + && position.getRow() <= 9)) && (3 <= position.getCol() && position.getCol() <= 5)); } + + private boolean chuSoldierCanDiagonalMoveInPalace(Position from, Position to) { + if ((from.getRow() == 7 && from.getCol() == 4) || (from.getRow() == 8 && from.getCol() == 3) + || (from.getRow() == 8 && from.getCol() == 5)) { + if (isDiagonal(from, to)) { + return true; + } + } + return false; + } + + private boolean hanSoldierCanDiagonalMoveInPalace(Position from, Position to) { + if ((from.getRow() == 2 && from.getCol() == 4) || (from.getRow() == 1 && from.getCol() == 3) + || (from.getRow() == 1 && from.getCol() == 5)) { + if (isDiagonal(from, to)) { + return true; + } + } + return false; + } + + private boolean isDiagonal(final Position from, final Position to) { + return Math.abs(from.getRow() - to.getRow()) == 1 && Math.abs(from.getCol() - to.getCol()) == 1; + } } \ No newline at end of file From 90dafbf80bfab8fd281cc40aba3dc092d1085d5e Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Tue, 7 Apr 2026 22:55:07 +0900 Subject: [PATCH 67/87] =?UTF-8?q?feat:=20=EC=82=AC=EC=9D=98=20=EB=B6=88?= =?UTF-8?q?=EA=B0=80=EB=8A=A5=ED=95=9C=20=EB=8C=80=EA=B0=81=EC=84=A0=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=EA=B7=9C=EC=B9=99=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/GuardMoveStrategy.java | 29 +++++++++++++ .../strategy/GuardMoveStrategyTest.java | 43 +++++++++++++------ 2 files changed, 59 insertions(+), 13 deletions(-) diff --git a/src/main/java/domain/strategy/GuardMoveStrategy.java b/src/main/java/domain/strategy/GuardMoveStrategy.java index 1504f1271c..73550493eb 100644 --- a/src/main/java/domain/strategy/GuardMoveStrategy.java +++ b/src/main/java/domain/strategy/GuardMoveStrategy.java @@ -26,10 +26,39 @@ public boolean canMove(final Piece mover, final Position from, final Position to if (target == null) { return true; } + return mover.isAnotherTeam(target); } private boolean isNotCorrectPath(final Position from, final Position to) { + if (hanSoldierCanDiagonalMoveInPalace(from, to) || chuSoldierCanDiagonalMoveInPalace(from, to)) { + return true; + } + return Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) != 1; } + + private boolean chuSoldierCanDiagonalMoveInPalace(Position from, Position to) { + if ((from.getRow() == 7 && from.getCol() == 4) || (from.getRow() == 8 && from.getCol() == 3) + || (from.getRow() == 8 && from.getCol() == 5)) { + if (isDiagonal(from, to)) { + return true; + } + } + return false; + } + + private boolean hanSoldierCanDiagonalMoveInPalace(Position from, Position to) { + if ((from.getRow() == 2 && from.getCol() == 4) || (from.getRow() == 1 && from.getCol() == 3) + || (from.getRow() == 1 && from.getCol() == 5)) { + if (isDiagonal(from, to)) { + return true; + } + } + return false; + } + + private boolean isDiagonal(final Position from, final Position to) { + return Math.abs(from.getRow() - to.getRow()) == 1 && Math.abs(from.getCol() - to.getCol()) == 1; + } } \ No newline at end of file diff --git a/src/test/java/domain/strategy/GuardMoveStrategyTest.java b/src/test/java/domain/strategy/GuardMoveStrategyTest.java index fd741ccf27..822c914767 100644 --- a/src/test/java/domain/strategy/GuardMoveStrategyTest.java +++ b/src/test/java/domain/strategy/GuardMoveStrategyTest.java @@ -1,10 +1,12 @@ package domain.strategy; +import static org.junit.jupiter.api.Assertions.*; + import domain.Piece; import domain.Team; import domain.Type; import domain.vo.Position; -import org.junit.jupiter.api.Assertions; +import java.util.HashMap; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -19,11 +21,11 @@ class GuardMoveStrategyTest { MoveStrategy strategy = new GuardMoveStrategy(); Piece mover = Piece.of(Team.CHU, Type.GUARD); - Position position = Position.of(0, 3); - Position targetPosition = Position.of(1, 3); + Position from = Position.of(0, 3); + Position to = Position.of(1, 3); // when & then - Assertions.assertTrue(strategy.canMove(mover, position, targetPosition, Map.of())); + assertTrue(strategy.canMove(mover, from, to, Map.of())); } @Test @@ -32,11 +34,11 @@ class GuardMoveStrategyTest { // given Piece guardPiece = Piece.of(Team.CHU, Type.GUARD); - Position position = Position.of(0, 3); - Position targetPosition = Position.of(0, 2); + Position from = Position.of(0, 3); + Position to = Position.of(0, 2); // when & then - Assertions.assertFalse(guardPiece.canMovePiece(position, targetPosition, Map.of(targetPosition, guardPiece))); + assertFalse(guardPiece.canMovePiece(from, to, Map.of(to, guardPiece))); } @Test @@ -46,11 +48,11 @@ class GuardMoveStrategyTest { Piece guardPiece = Piece.of(Team.CHU, Type.GUARD); Piece soldierPiece = Piece.of(Team.HAN, Type.SOLDIER); - Position position = Position.of(0, 3); - Position targetPosition = Position.of(1, 3); + Position from = Position.of(0, 3); + Position to = Position.of(1, 3); // when & then - Assertions.assertTrue(guardPiece.canMovePiece(position, targetPosition, Map.of(targetPosition, soldierPiece))); + assertTrue(guardPiece.canMovePiece(from, to, Map.of(to, soldierPiece))); } @Test @@ -59,10 +61,25 @@ class GuardMoveStrategyTest { // given Piece guardPiece = Piece.of(Team.CHU, Type.GUARD); - Position position = Position.of(0, 3); - Position targetPosition = Position.of(1, 2); + Position from = Position.of(0, 3); + Position to = Position.of(1, 2); // when & then - Assertions.assertFalse(guardPiece.canMovePiece(position, targetPosition, Map.of())); + assertFalse(guardPiece.canMovePiece(from, to, Map.of())); + } + + @Test + @DisplayName("사가 궁성 안에서 이동할 수 없는 곳으로 대각선 이동하려고 하면 이동하지 않는다.") + void 사_궁성_안_이동_불가능한_대각선_이동_불가() { + // given + Piece guardPiece = Piece.of(Team.CHU, Type.GUARD); + + Position from = Position.of(1, 3); + Position to = Position.of(2, 4); + Map pieceOnPath = new HashMap<>(); + pieceOnPath.put(to, null); + + // when // then + assertFalse(guardPiece.canMovePiece(from, to, pieceOnPath)); } } From 8a457130dd5d79e7dd1606fcb544a9095287c17a Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 8 Apr 2026 15:24:44 +0900 Subject: [PATCH 68/87] =?UTF-8?q?feat:=20=EC=82=AC=EC=9D=98=20=EA=B6=81?= =?UTF-8?q?=EC=84=B1=20=EB=B0=96=20=EC=9D=B4=EB=8F=99=20=EC=A0=9C=ED=95=9C?= =?UTF-8?q?=20=EA=B7=9C=EC=B9=99=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - .../java/domain/strategy/ChariotMoveStrategy.java | 15 +++++++++++++++ .../java/domain/strategy/GuardMoveStrategy.java | 10 ++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f0d8669efd..df8f07f3d0 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,6 @@ - 목적지에 다른 팀 기물이 존재한다면 해당 기물을 잡을 수 있다. - 이동할 기물이 포이고 이동 경로에 포를 제외한 다른 기물이 있다면 기물을 넘어서 이동할 수 있다. - [ ] 기물의 이동에 궁성(宮城) 영역의 규칙을 포함한다. - - - [ ] 왕이 잡히는 경우 게임에서 진다. - 왕이 잡혔을 때 게임을 종료한다. - [ ] 현재 남아 있는 기물에 대한 점수를 구할수 있어야 한다. diff --git a/src/main/java/domain/strategy/ChariotMoveStrategy.java b/src/main/java/domain/strategy/ChariotMoveStrategy.java index f57309a5bb..f7e22297f1 100644 --- a/src/main/java/domain/strategy/ChariotMoveStrategy.java +++ b/src/main/java/domain/strategy/ChariotMoveStrategy.java @@ -50,6 +50,21 @@ public boolean canMove(final Piece mover, final Position from, final Position to } private boolean isNotCorrectPath(final Position from, final Position to) { + if (isInPalace(from, to)) { + if (isDiagonal(from, to)) { + + } + } + return from.getCol() != to.getCol() && from.getRow() != to.getRow(); } + + private boolean isInPalace(final Position from, final Position to) { +// if () + return false; + } + + private boolean isDiagonal(final Position from, final Position to) { + return Math.abs(from.getRow() - to.getRow()) >= 1 && Math.abs(from.getCol() - to.getCol()) >= 1; + } } \ No newline at end of file diff --git a/src/main/java/domain/strategy/GuardMoveStrategy.java b/src/main/java/domain/strategy/GuardMoveStrategy.java index 73550493eb..31ebcdd391 100644 --- a/src/main/java/domain/strategy/GuardMoveStrategy.java +++ b/src/main/java/domain/strategy/GuardMoveStrategy.java @@ -22,6 +22,10 @@ public boolean canMove(final Piece mover, final Position from, final Position to return false; } + if (!palaceInRange(to)) { + return false; + } + Piece target = piecesOnPath.get(to); if (target == null) { return true; @@ -61,4 +65,10 @@ private boolean hanSoldierCanDiagonalMoveInPalace(Position from, Position to) { private boolean isDiagonal(final Position from, final Position to) { return Math.abs(from.getRow() - to.getRow()) == 1 && Math.abs(from.getCol() - to.getCol()) == 1; } + + private boolean palaceInRange(final Position position) { + return (((0 <= position.getRow() && position.getRow() <= 2) || (7 <= position.getRow() + && position.getRow() <= 9)) + && (3 <= position.getCol() && position.getCol() <= 5)); + } } \ No newline at end of file From dee91128d2ee7583dc29712218f2169e7f6496f6 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 8 Apr 2026 16:41:06 +0900 Subject: [PATCH 69/87] =?UTF-8?q?feat:=20=EC=B0=A8=EC=9D=98=20=EA=B6=81?= =?UTF-8?q?=EC=84=B1=20=EC=95=88=20=EC=9D=B4=EB=8F=99=20=EA=B7=9C=EC=B9=99?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/ChariotMoveStrategy.java | 18 +++++++--- .../strategy/ChariotMoveStrategyTest.java | 36 +++++++++++++++---- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/main/java/domain/strategy/ChariotMoveStrategy.java b/src/main/java/domain/strategy/ChariotMoveStrategy.java index f7e22297f1..2482d09e03 100644 --- a/src/main/java/domain/strategy/ChariotMoveStrategy.java +++ b/src/main/java/domain/strategy/ChariotMoveStrategy.java @@ -50,18 +50,26 @@ public boolean canMove(final Piece mover, final Position from, final Position to } private boolean isNotCorrectPath(final Position from, final Position to) { - if (isInPalace(from, to)) { + if (isInPalaceAndCanDiagonalMove(from)) { if (isDiagonal(from, to)) { - + if (Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) <= 4) { + return false; + } } } return from.getCol() != to.getCol() && from.getRow() != to.getRow(); } - private boolean isInPalace(final Position from, final Position to) { -// if () - return false; + private boolean isInPalaceAndCanDiagonalMove(final Position position) { + int row = position.getRow(); + int column = position.getCol(); + if ((row == 0 && column == 4) || (row == 2 && column == 4) || (row == 1 && column == 3) || (row == 1 && column == 5) + || (row == 7 && column == 4) || (row == 9 && column == 4) || (row == 8 && column == 3) || (row == 8 && column == 5)) { + return false; + } + + return true; } private boolean isDiagonal(final Position from, final Position to) { diff --git a/src/test/java/domain/strategy/ChariotMoveStrategyTest.java b/src/test/java/domain/strategy/ChariotMoveStrategyTest.java index a47cda8456..dbd7707fd6 100644 --- a/src/test/java/domain/strategy/ChariotMoveStrategyTest.java +++ b/src/test/java/domain/strategy/ChariotMoveStrategyTest.java @@ -1,5 +1,7 @@ package domain.strategy; +import static org.junit.jupiter.api.Assertions.*; + import domain.Piece; import domain.Team; import domain.Type; @@ -31,8 +33,8 @@ void setUp() { Position from = Position.of(0, 0); Position to = Position.of(2, 0); - // then - Assertions.assertTrue(chariotPiece.canMovePiece(from, to, Map.of())); + // when // then + assertTrue(chariotPiece.canMovePiece(from, to, Map.of())); } @Test @@ -42,8 +44,8 @@ void setUp() { Position from = Position.of(0, 0); Position to = Position.of(3, 0); - // then - Assertions.assertFalse(chariotPiece.canMovePiece(from, to, Map.of(to, horsePiece))); + // when // then + assertFalse(chariotPiece.canMovePiece(from, to, Map.of(to, horsePiece))); } @Test @@ -53,7 +55,29 @@ void setUp() { Position from = Position.of(0, 0); Position to = Position.of(0, 3); - // then - Assertions.assertTrue(chariotPiece.canMovePiece(from, to, Map.of(to, elephantPiece))); + // when // then + assertTrue(chariotPiece.canMovePiece(from, to, Map.of(to, elephantPiece))); + } + + @Test + @DisplayName("궁성 안에서 가능한 대각선 이동 시 이동한다.") + void 궁성_안_가능한_대각선_이동_가능() { + // given + Position from = Position.of(2, 3); + Position to = Position.of(0, 5); + + // when // then + assertTrue(chariotPiece.canMovePiece(from, to, Map.of())); + } + + @Test + @DisplayName("궁성 안에서 불가능한 대각선 이동 시 이동하지 않는다.") + void 궁성_안_불가능한_대각선_이동은_불가() { + // given + Position from = Position.of(0, 4); + Position to = Position.of(2, 6); + + // when // then + assertFalse(chariotPiece.canMovePiece(from, to, Map.of())); } } From 7471b6658f5c80e73f18cc1bbaf0b10a45304a01 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 8 Apr 2026 17:07:17 +0900 Subject: [PATCH 70/87] =?UTF-8?q?feat:=20=ED=8F=AC=EC=9D=98=20=EA=B6=81?= =?UTF-8?q?=EC=84=B1=20=EC=95=88=EC=97=90=EC=84=9C=20=EC=9D=B4=EB=8F=99=20?= =?UTF-8?q?=EA=B7=9C=EC=B9=99=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/strategy/CannonMoveStrategy.java | 23 +++++++++++++++++++ .../strategy/CannonMoveStrategyTest.java | 17 ++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/main/java/domain/strategy/CannonMoveStrategy.java b/src/main/java/domain/strategy/CannonMoveStrategy.java index 23a09dd64a..2cc8a75719 100644 --- a/src/main/java/domain/strategy/CannonMoveStrategy.java +++ b/src/main/java/domain/strategy/CannonMoveStrategy.java @@ -62,6 +62,29 @@ public boolean canMove(final Piece mover, final Position from, final Position to } private boolean isNotCorrectPath(final Position from, final Position to) { + if (isInPalaceAndCanDiagonalMove(from)) { + if (isDiagonal(from, to)) { + if (Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) <= 4) { + return false; + } + } + } + return from.getRow() != to.getRow() && from.getCol() != to.getCol(); } + + private boolean isInPalaceAndCanDiagonalMove(final Position position) { + int row = position.getRow(); + int column = position.getCol(); + if ((row == 0 && column == 4) || (row == 2 && column == 4) || (row == 1 && column == 3) || (row == 1 && column == 5) + || (row == 7 && column == 4) || (row == 9 && column == 4) || (row == 8 && column == 3) || (row == 8 && column == 5)) { + return false; + } + + return true; + } + + private boolean isDiagonal(final Position from, final Position to) { + return Math.abs(from.getRow() - to.getRow()) >= 1 && Math.abs(from.getCol() - to.getCol()) >= 1; + } } \ No newline at end of file diff --git a/src/test/java/domain/strategy/CannonMoveStrategyTest.java b/src/test/java/domain/strategy/CannonMoveStrategyTest.java index 49a33962b7..af497f3b3b 100644 --- a/src/test/java/domain/strategy/CannonMoveStrategyTest.java +++ b/src/test/java/domain/strategy/CannonMoveStrategyTest.java @@ -121,4 +121,21 @@ class CannonMoveStrategyTest { Assertions.assertFalse(strategy.canMove(mover, from, to, Map.of(Position.of(3, 1), pathCannon))); } + + @Test + @DisplayName("궁성 안에서 포의 이동 가능한 대각선 이동 시 이동한다.") + void 궁성_안_가능한_포의_대각선_이동() { + // given + Position from = Position.of(7, 3); + Position to = Position.of(9, 5); + + MoveStrategy strategy = new CannonMoveStrategy(); + Piece mover = Piece.of(Team.CHU, Type.CANNON); + Piece general = Piece.of(Team.CHU, Type.GENERAL); + + // when + + // then + Assertions.assertTrue(strategy.canMove(mover, from, to, Map.of(Position.of(8, 4), general))); + } } From b5aaa6e6c67caf8c47a39554d53978bc5f2ca153 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 8 Apr 2026 17:08:31 +0900 Subject: [PATCH 71/87] =?UTF-8?q?docs:=20=EA=B6=81=EC=84=B1=20=EC=98=81?= =?UTF-8?q?=EC=97=AD=20=EA=B5=AC=ED=98=84=20=EA=B8=B0=EB=8A=A5=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/test/java/domain/strategy/CannonMoveStrategyTest.java | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index df8f07f3d0..c62ab9baed 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ - 목적지에 같은 팀 기물이 존재한다면 이동하지 못한다. - 목적지에 다른 팀 기물이 존재한다면 해당 기물을 잡을 수 있다. - 이동할 기물이 포이고 이동 경로에 포를 제외한 다른 기물이 있다면 기물을 넘어서 이동할 수 있다. -- [ ] 기물의 이동에 궁성(宮城) 영역의 규칙을 포함한다. +- [x] 기물의 이동에 궁성(宮城) 영역의 규칙을 포함한다. - [ ] 왕이 잡히는 경우 게임에서 진다. - 왕이 잡혔을 때 게임을 종료한다. - [ ] 현재 남아 있는 기물에 대한 점수를 구할수 있어야 한다. diff --git a/src/test/java/domain/strategy/CannonMoveStrategyTest.java b/src/test/java/domain/strategy/CannonMoveStrategyTest.java index af497f3b3b..b05ad9149e 100644 --- a/src/test/java/domain/strategy/CannonMoveStrategyTest.java +++ b/src/test/java/domain/strategy/CannonMoveStrategyTest.java @@ -133,9 +133,7 @@ class CannonMoveStrategyTest { Piece mover = Piece.of(Team.CHU, Type.CANNON); Piece general = Piece.of(Team.CHU, Type.GENERAL); - // when - - // then + // when // then Assertions.assertTrue(strategy.canMove(mover, from, to, Map.of(Position.of(8, 4), general))); } } From a20e0fbf001384cb4d911d72b435488bbe41edca Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 8 Apr 2026 19:01:49 +0900 Subject: [PATCH 72/87] =?UTF-8?q?refacotr:=20JanggiGame=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EB=8F=84=EC=9E=85,=20Controller=EC=97=90=20?= =?UTF-8?q?=ED=8D=BC=EC=A7=84=20=EB=B3=B4=EB=93=9C=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=BA=A1=EC=8A=90=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/JanggiController.java | 20 +++++----- src/main/java/domain/Board.java | 21 ++++++---- src/main/java/domain/JanggiGame.java | 39 +++++++++++++++++++ src/main/java/domain/TurnCount.java | 25 ++++++++++++ src/main/java/view/OutputView.java | 7 ++-- 5 files changed, 92 insertions(+), 20 deletions(-) create mode 100644 src/main/java/domain/JanggiGame.java create mode 100644 src/main/java/domain/TurnCount.java diff --git a/src/main/java/controller/JanggiController.java b/src/main/java/controller/JanggiController.java index 500cc5a386..ba7f0f9097 100644 --- a/src/main/java/controller/JanggiController.java +++ b/src/main/java/controller/JanggiController.java @@ -3,6 +3,7 @@ import domain.Board; import domain.BoardFactory; import domain.Formation; +import domain.JanggiGame; import domain.Team; import domain.vo.Position; import view.InputView; @@ -25,11 +26,11 @@ public void run() { outputView.printBoard(board.getBoard()); - int turnCount = 0; - turnCount = movePosition(board, turnCount); + JanggiGame janggiGame = JanggiGame.of(board); + movePosition(janggiGame); while (true) { - turnCount = movePosition(board, turnCount); + movePosition(janggiGame); } } @@ -77,18 +78,19 @@ private static Board applyArrangement(String arrangement, Board board, Team team return board; } - private int movePosition(Board board, int turnCount) { + private void movePosition(JanggiGame janggiGame) { while (true) { try { - outputView.printCurrentTurn(turnCount); + outputView.printCurrentTurn(janggiGame.currentTurn()); Position position = inputView.readPosition(); Position targetPosition = inputView.readTargetPosition(); - Team currentTeam = Team.from(turnCount); - board.move(position, targetPosition, currentTeam); - outputView.printBoard(board.getBoard()); - return turnCount += 1; + janggiGame.move(position, targetPosition); + outputView.printBoard(janggiGame.getBoardStatus()); + janggiGame.passTheTurn(); + + return; } catch (Exception e) { System.out.println(e.getMessage()); System.out.println(); diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index 1b5ccd7eff..24eabca641 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -38,14 +38,6 @@ public void move(final Position from, final Position to, final Team currentTeam) board.put(to, fromPiece); } - private Map findPiecesAt(final List positions) { - Map result = new HashMap<>(); - for (Position pos : positions) { - findPieceByPosition(pos).ifPresent(piece -> result.put(pos, piece)); - } - return result; - } - public boolean isExistPosition(final Position tempPosition) { return board.containsKey(tempPosition); } @@ -57,4 +49,17 @@ public Optional findPieceByPosition(final Position position) { public Map getBoard() { return Map.copyOf(board); } + + public boolean isGeneralAlive(Team team) { + return board.values().stream() + .anyMatch(piece -> piece.getTeam() == team && piece.getType() == Type.GENERAL); + } + + private Map findPiecesAt(final List positions) { + Map result = new HashMap<>(); + for (Position pos : positions) { + findPieceByPosition(pos).ifPresent(piece -> result.put(pos, piece)); + } + return result; + } } \ No newline at end of file diff --git a/src/main/java/domain/JanggiGame.java b/src/main/java/domain/JanggiGame.java new file mode 100644 index 0000000000..9c8d7186f6 --- /dev/null +++ b/src/main/java/domain/JanggiGame.java @@ -0,0 +1,39 @@ +package domain; + +import domain.vo.Position; +import java.util.Map; + +public class JanggiGame { + + private final Board board; + private TurnCount turnCount; + + private JanggiGame(final Board board) { + this.board = board; + this.turnCount = TurnCount.of(0); + } + + public static JanggiGame of(final Board board) { + return new JanggiGame(board); + } + + public Team currentTurn() { + if (turnCount.getTurnCount() % 2 == 0) { + return Team.HAN; + } + + return Team.CHU; + } + + public void passTheTurn() { + turnCount = TurnCount.of(turnCount.getTurnCount() + 1); + } + + public void move(Position from, Position to) { + board.move(from, to, currentTurn()); + } + + public Map getBoardStatus() { + return board.getBoard(); + } +} diff --git a/src/main/java/domain/TurnCount.java b/src/main/java/domain/TurnCount.java new file mode 100644 index 0000000000..f61b1d7fd7 --- /dev/null +++ b/src/main/java/domain/TurnCount.java @@ -0,0 +1,25 @@ +package domain; + +public class TurnCount { + + private final int turnCount; + + private TurnCount(final int turnCount) { + this.turnCount = turnCount; + } + + public static TurnCount of(final int turnCount) { + validate(turnCount); + return new TurnCount(turnCount); + } + + public int getTurnCount() { + return turnCount; + } + + private static void validate(final int turnCount) { + if (turnCount < 0) { + throw new IllegalArgumentException("[ERROR] 턴은 0 이하가 될 수 없습니다."); + } + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 767436ecea..bb585cac6f 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,6 +1,7 @@ package view; import domain.Piece; +import domain.Team; import domain.vo.Position; import java.util.Map; @@ -49,11 +50,11 @@ public void printBoard(Map board) { System.out.println(); } - public void printCurrentTurn(int turnCount) { - if (turnCount % 2 == 0) { + public void printCurrentTurn(Team team) { + if (team == Team.HAN) { System.out.println("현재는 한나라 차례입니다."); } - if (turnCount % 2 != 0) { + if (team == Team.CHU) { System.out.println("현재는 초나라 차례입니다."); } } From c4286b51f0cbc83dd017570aff4f49429223b663 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 8 Apr 2026 19:25:13 +0900 Subject: [PATCH 73/87] =?UTF-8?q?test:=20JanggiGame=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../java/controller/JanggiController.java | 4 + src/main/java/domain/JanggiGame.java | 8 +- src/main/java/view/OutputView.java | 4 + src/test/java/domain/JanggiGameTest.java | 177 ++++++++++++++++++ 5 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 src/test/java/domain/JanggiGameTest.java diff --git a/README.md b/README.md index c62ab9baed..8f090e9fe9 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ - 목적지에 다른 팀 기물이 존재한다면 해당 기물을 잡을 수 있다. - 이동할 기물이 포이고 이동 경로에 포를 제외한 다른 기물이 있다면 기물을 넘어서 이동할 수 있다. - [x] 기물의 이동에 궁성(宮城) 영역의 규칙을 포함한다. -- [ ] 왕이 잡히는 경우 게임에서 진다. +- [x] 왕이 잡히는 경우 게임에서 진다. - 왕이 잡혔을 때 게임을 종료한다. - [ ] 현재 남아 있는 기물에 대한 점수를 구할수 있어야 한다. - [ ] 애플리케이션을 재시작하더라도 이전에 하던 장기 게임을 다시 시작할 수 있어야 한다. diff --git a/src/main/java/controller/JanggiController.java b/src/main/java/controller/JanggiController.java index ba7f0f9097..105757b5f7 100644 --- a/src/main/java/controller/JanggiController.java +++ b/src/main/java/controller/JanggiController.java @@ -31,6 +31,10 @@ public void run() { while (true) { movePosition(janggiGame); + if (janggiGame.isFinished()) { + outputView.printGameFinishMessage(); + break; + } } } diff --git a/src/main/java/domain/JanggiGame.java b/src/main/java/domain/JanggiGame.java index 9c8d7186f6..b33b84490c 100644 --- a/src/main/java/domain/JanggiGame.java +++ b/src/main/java/domain/JanggiGame.java @@ -5,12 +5,14 @@ public class JanggiGame { + private static final int DEFAULT_TURN_COUNT = 0; + private final Board board; private TurnCount turnCount; private JanggiGame(final Board board) { this.board = board; - this.turnCount = TurnCount.of(0); + this.turnCount = TurnCount.of(DEFAULT_TURN_COUNT); } public static JanggiGame of(final Board board) { @@ -36,4 +38,8 @@ public void move(Position from, Position to) { public Map getBoardStatus() { return board.getBoard(); } + + public boolean isFinished() { + return !board.isGeneralAlive(Team.CHU) || !board.isGeneralAlive(Team.HAN); + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index bb585cac6f..97a0b1b3a4 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -71,4 +71,8 @@ private String matchSoldierName(String type, Piece piece) { } return type; } + + public void printGameFinishMessage() { + System.out.println("왕이 잡혀서 게임을 종료합니다."); + } } diff --git a/src/test/java/domain/JanggiGameTest.java b/src/test/java/domain/JanggiGameTest.java new file mode 100644 index 0000000000..ef880f1c12 --- /dev/null +++ b/src/test/java/domain/JanggiGameTest.java @@ -0,0 +1,177 @@ +package domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import domain.vo.Position; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class JanggiGameTest { + + @Test + @DisplayName("게임 시작 시 한나라가 먼저 시작한다") + void 게임_시작_시_한나라가_먼저_시작한다() { + // given + Board board = BoardFactory.setUp(); + + // when + JanggiGame game = JanggiGame.of(board); + + // then + assertThat(game.currentTurn()).isEqualTo(Team.HAN); + } + + @Test + @DisplayName("턴을 넘기면 초나라 차례가 된다") + void 턴을_넘기면_초나라_차례가_된다() { + // given + Board board = BoardFactory.setUp(); + JanggiGame game = JanggiGame.of(board); + + // when + game.passTheTurn(); + + // then + assertThat(game.currentTurn()).isEqualTo(Team.CHU); + } + + @Test + @DisplayName("턴을 두 번 넘기면 다시 한나라 차례가 된다") + void 턴을_두_번_넘기면_다시_한나라_차례가_된다() { + // given + Board board = BoardFactory.setUp(); + JanggiGame game = JanggiGame.of(board); + + // when + game.passTheTurn(); + game.passTheTurn(); + + // then + assertThat(game.currentTurn()).isEqualTo(Team.HAN); + } + + @Test + @DisplayName("한나라 졸을 앞으로 한 칸 이동할 수 있다") + void 한나라_졸을_앞으로_한_칸_이동할_수_있다() { + // given + Board board = BoardFactory.setUp(); + JanggiGame game = JanggiGame.of(board); + Position from = Position.of(6, 0); + Position to = Position.of(5, 0); + + // when + game.move(from, to); + + // then + Map boardStatus = game.getBoardStatus(); + assertThat(boardStatus.containsKey(to)).isTrue(); + assertThat(boardStatus.containsKey(from)).isFalse(); + assertThat(boardStatus.get(to).getType()).isEqualTo(Type.SOLDIER); + } + + @Test + @DisplayName("상대편 기물을 이동하려 하면 예외가 발생한다") + void 상대편_기물을_이동하려_하면_예외가_발생한다() { + // given + Board board = BoardFactory.setUp(); + JanggiGame game = JanggiGame.of(board); + Position from = Position.of(3, 0); + Position to = Position.of(4, 0); + + // when // then + assertThatThrownBy(() -> game.move(from, to)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("[ERROR] 상대편의 기물은 움직일 수 없습니다"); + } + + @Test + @DisplayName("빈 위치의 기물을 이동하려 하면 예외가 발생한다") + void 빈_위치의_기물을_이동하려_하면_예외가_발생한다() { + // given + Board board = BoardFactory.setUp(); + JanggiGame game = JanggiGame.of(board); + Position from = Position.of(5, 0); + Position to = Position.of(4, 0); + + // when // then + assertThatThrownBy(() -> game.move(from, to)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("[ERROR] 해당 위치에 기물이 존재하지 않습니다"); + } + + @Test + @DisplayName("양쪽 궁이 모두 살아있으면 게임이 끝나지 않는다") + void 양쪽_궁이_모두_살아있으면_게임이_끝나지_않는다() { + // given + Board board = BoardFactory.setUp(); + + // when + JanggiGame game = JanggiGame.of(board); + + // then + assertThat(game.isFinished()).isFalse(); + } + + @Test + @DisplayName("초나라 궁이 잡히면 게임이 종료된다") + void 초나라_궁이_잡히면_게임이_종료된다() { + // given + Map pieces = new HashMap<>(); + pieces.put(Position.of(8, 4), Piece.of(Team.HAN, Type.GENERAL)); + Board board = Board.of(pieces); + + // when + JanggiGame game = JanggiGame.of(board); + + // then + assertThat(game.isFinished()).isTrue(); + } + + @Test + @DisplayName("한나라 궁이 잡히면 게임이 종료된다") + void 한나라_궁이_잡히면_게임이_종료된다() { + // given + Map pieces = new HashMap<>(); + pieces.put(Position.of(1, 4), Piece.of(Team.CHU, Type.GENERAL)); + Board board = Board.of(pieces); + + // when + JanggiGame game = JanggiGame.of(board); + + // then + assertThat(game.isFinished()).isTrue(); + } + + @Test + @DisplayName("초기 보드 상태를 조회할 수 있다") + void 초기_보드_상태를_조회할_수_있다() { + // given + Board board = BoardFactory.setUp(); + + // when + JanggiGame game = JanggiGame.of(board); + + // then + assertThat(game.getBoardStatus()).isNotEmpty(); + } + + @Test + @DisplayName("기물 이동 후 보드 상태가 반영된다") + void 기물_이동_후_보드_상태가_반영된다() { + // given + Board board = BoardFactory.setUp(); + JanggiGame game = JanggiGame.of(board); + Position from = Position.of(6, 0); + Position to = Position.of(5, 0); + + // when + game.move(from, to); + + // then + Map boardStatus = game.getBoardStatus(); + assertThat(boardStatus.get(Position.of(5, 0)).getTeam()).isEqualTo(Team.HAN); + } +} From 5b9740975b512e90f4bf198a8e4f293f736faa4b Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 8 Apr 2026 20:23:35 +0900 Subject: [PATCH 74/87] =?UTF-8?q?feat:=20=EC=A0=90=EC=88=98=20=EA=B3=84?= =?UTF-8?q?=EC=82=B0=20=EA=B7=9C=EC=B9=99=20=EC=B6=94=EA=B0=80=20=EB=B0=8F?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/JanggiController.java | 1 + src/main/java/domain/Board.java | 9 ++++++++ src/main/java/domain/JanggiGame.java | 4 ++++ src/main/java/domain/Type.java | 22 ++++++++++++------- src/main/java/view/OutputView.java | 6 +++++ src/test/java/domain/BoardTest.java | 13 +++++++++++ 6 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/main/java/controller/JanggiController.java b/src/main/java/controller/JanggiController.java index 105757b5f7..434b8b173c 100644 --- a/src/main/java/controller/JanggiController.java +++ b/src/main/java/controller/JanggiController.java @@ -33,6 +33,7 @@ public void run() { movePosition(janggiGame); if (janggiGame.isFinished()) { outputView.printGameFinishMessage(); + outputView.printScore(janggiGame.calculateScore(Team.HAN), janggiGame.calculateScore(Team.CHU)); break; } } diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index 24eabca641..32e0780bd4 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -55,6 +55,15 @@ public boolean isGeneralAlive(Team team) { .anyMatch(piece -> piece.getTeam() == team && piece.getType() == Type.GENERAL); } + public int calculateScore(Team team) { + return board.values() + .stream() + .filter(piece -> piece.getTeam() == team) + .map(piece -> piece.getType().getScore()) + .mapToInt(Integer::intValue) + .sum(); + } + private Map findPiecesAt(final List positions) { Map result = new HashMap<>(); for (Position pos : positions) { diff --git a/src/main/java/domain/JanggiGame.java b/src/main/java/domain/JanggiGame.java index b33b84490c..66c9edacbe 100644 --- a/src/main/java/domain/JanggiGame.java +++ b/src/main/java/domain/JanggiGame.java @@ -42,4 +42,8 @@ public Map getBoardStatus() { public boolean isFinished() { return !board.isGeneralAlive(Team.CHU) || !board.isGeneralAlive(Team.HAN); } + + public int calculateScore(Team team) { + return board.calculateScore(team); + } } diff --git a/src/main/java/domain/Type.java b/src/main/java/domain/Type.java index f1aaecc0bf..4f139b59ea 100644 --- a/src/main/java/domain/Type.java +++ b/src/main/java/domain/Type.java @@ -10,20 +10,22 @@ import domain.strategy.SoldierMoveStrategy; public enum Type { - GENERAL("궁", new GeneralMoveStrategy()), - CHARIOT("차", new ChariotMoveStrategy()), - CANNON("포", new CannonMoveStrategy()), - HORSE("마", new HorseMoveStrategy()), - ELEPHANT("상", new ElephantMoveStrategy()), - GUARD("사", new GuardMoveStrategy()), - SOLDIER("졸", new SoldierMoveStrategy()); + GENERAL("궁", new GeneralMoveStrategy(), 0), + CHARIOT("차", new ChariotMoveStrategy(), 13), + CANNON("포", new CannonMoveStrategy(), 7), + HORSE("마", new HorseMoveStrategy(), 5), + ELEPHANT("상", new ElephantMoveStrategy(), 3), + GUARD("사", new GuardMoveStrategy(), 3), + SOLDIER("졸", new SoldierMoveStrategy(), 2); private final String name; private final MoveStrategy strategy; + private final int score; - Type(String name, MoveStrategy strategy) { + Type(String name, MoveStrategy strategy, int score) { this.name = name; this.strategy = strategy; + this.score = score; } public MoveStrategy getStrategy() { @@ -33,4 +35,8 @@ public MoveStrategy getStrategy() { public String getName() { return name; } + + public int getScore() { + return score; + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 97a0b1b3a4..b410363b42 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -75,4 +75,10 @@ private String matchSoldierName(String type, Piece piece) { public void printGameFinishMessage() { System.out.println("왕이 잡혀서 게임을 종료합니다."); } + + public void printScore(int hanScore, int chuScore) { + System.out.println("== 최종 점수 =="); + System.out.println("한: " + hanScore + "점"); + System.out.println("초: " + chuScore + "점"); + } } diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java index 294333baba..1b7d489ce1 100644 --- a/src/test/java/domain/BoardTest.java +++ b/src/test/java/domain/BoardTest.java @@ -1,6 +1,7 @@ package domain; import domain.vo.Position; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -61,6 +62,18 @@ class BoardTest { assertFalse(board.isExistPosition(from)); } + @Test + @DisplayName("모든 기물이 살아 있다면 현재 점수는 72점이다.") + void 현재_점수_계산() { + // given + Board board = BoardFactory.setUp(); + JanggiGame janggiGame = JanggiGame.of(board); + + // when // then + Assertions.assertThat(janggiGame.calculateScore(Team.HAN)).isEqualTo(72); + Assertions.assertThat(janggiGame.calculateScore(Team.CHU)).isEqualTo(72); + } + private static Stream providePiece() { return Stream.of( Arguments.of(0, 0, Type.CHARIOT), From f2eec99ec9e0e2bc6b731328c02225049a14249e Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Wed, 8 Apr 2026 20:24:48 +0900 Subject: [PATCH 75/87] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EB=82=B4=EC=97=AD=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 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8f090e9fe9..823fa24cfe 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ - [x] 기물의 이동에 궁성(宮城) 영역의 규칙을 포함한다. - [x] 왕이 잡히는 경우 게임에서 진다. - 왕이 잡혔을 때 게임을 종료한다. -- [ ] 현재 남아 있는 기물에 대한 점수를 구할수 있어야 한다. +- [x] 현재 남아 있는 기물에 대한 점수를 구할수 있어야 한다. - [ ] 애플리케이션을 재시작하더라도 이전에 하던 장기 게임을 다시 시작할 수 있어야 한다. - DB를 적용할 때 도메인 객체의 변경을 최소화해야 한다. From f34dfae627bc47badf170abec7ec89aeecf93d51 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Thu, 9 Apr 2026 17:58:58 +0900 Subject: [PATCH 76/87] =?UTF-8?q?feat:=20DB=20=EC=A0=81=EC=9A=A9=20?= =?UTF-8?q?=EB=B0=8F=20=EB=B7=B0=20=EA=B3=84=EC=B8=B5=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + src/main/java/Application.java | 3 +- .../java/controller/JanggiController.java | 53 +++++++- src/main/java/dao/BoardDao.java | 125 ++++++++++++++++++ src/main/java/domain/JanggiGame.java | 11 ++ .../java/presentation/PositionCommand.java | 33 +++++ src/main/java/view/InputView.java | 48 ++----- src/main/java/view/OutputView.java | 4 + src/test/java/dao/BoardDaoTest.java | 105 +++++++++++++++ src/test/java/dao/MongoConnectionTest.java | 28 ++++ 10 files changed, 368 insertions(+), 44 deletions(-) create mode 100644 src/main/java/dao/BoardDao.java create mode 100644 src/main/java/presentation/PositionCommand.java create mode 100644 src/test/java/dao/BoardDaoTest.java create mode 100644 src/test/java/dao/MongoConnectionTest.java diff --git a/build.gradle b/build.gradle index ce846f70cc..dcca1dae54 100644 --- a/build.gradle +++ b/build.gradle @@ -9,6 +9,8 @@ repositories { } dependencies { + implementation 'org.mongodb:mongodb-driver-sync:5.3.1' + testImplementation platform('org.junit:junit-bom:5.11.4') testImplementation platform('org.assertj:assertj-bom:3.27.3') testImplementation('org.junit.jupiter:junit-jupiter') diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 528a3ad0d0..e36a1ca5a5 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,11 +1,12 @@ import controller.JanggiController; +import dao.BoardDao; import view.InputView; import view.OutputView; public class Application { public static void main(String[] args) { - JanggiController janggiController = new JanggiController(new InputView(), new OutputView()); + JanggiController janggiController = new JanggiController(new InputView(), new OutputView(), new BoardDao()); janggiController.run(); } } diff --git a/src/main/java/controller/JanggiController.java b/src/main/java/controller/JanggiController.java index 434b8b173c..3fc849f792 100644 --- a/src/main/java/controller/JanggiController.java +++ b/src/main/java/controller/JanggiController.java @@ -1,36 +1,69 @@ package controller; +import dao.BoardDao; import domain.Board; import domain.BoardFactory; import domain.Formation; import domain.JanggiGame; import domain.Team; import domain.vo.Position; +import presentation.PositionCommand; import view.InputView; import view.OutputView; public class JanggiController { + private static final String RESUME_GAME_NUMBER = "2"; + private final InputView inputView; private final OutputView outputView; + private final BoardDao boardDao; - public JanggiController(InputView inputView, OutputView outputView) { + public JanggiController(InputView inputView, OutputView outputView, BoardDao boardDao) { this.inputView = inputView; this.outputView = outputView; + this.boardDao = boardDao; } public void run() { + String command = inputView.readCommand(); + + if (command.equals(RESUME_GAME_NUMBER)) { + resumeGame(); + return; + } + + startNewGame(); + } + + private void startNewGame() { Board board = BoardFactory.setUp(); board = readHanFormation(board); board = readChuFormation(board); - outputView.printBoard(board.getBoard()); - JanggiGame janggiGame = JanggiGame.of(board); - movePosition(janggiGame); + String gameId = boardDao.save(board, janggiGame.getTurnCount()); + + playGame(gameId, janggiGame); + } + + private void resumeGame() { + String gameId = inputView.readGameId(); + Board board = boardDao.findBoardByGameId(gameId); + int turnCount = boardDao.findTurnCountByGameId(gameId); + JanggiGame janggiGame = JanggiGame.of(board, turnCount); + + playGame(gameId, janggiGame); + } + + private void playGame(String gameId, JanggiGame janggiGame) { + outputView.printCurrentGameId(gameId); + outputView.printBoard(janggiGame.getBoardStatus()); while (true) { movePosition(janggiGame); + boardDao.update(gameId, Board.of(janggiGame.getBoardStatus()), janggiGame.getTurnCount()); + if (janggiGame.isFinished()) { outputView.printGameFinishMessage(); outputView.printScore(janggiGame.calculateScore(Team.HAN), janggiGame.calculateScore(Team.CHU)); @@ -88,8 +121,16 @@ private void movePosition(JanggiGame janggiGame) { try { outputView.printCurrentTurn(janggiGame.currentTurn()); - Position position = inputView.readPosition(); - Position targetPosition = inputView.readTargetPosition(); + String input = inputView.readPosition(); + if (input.equals("항복")) { + outputView.printGameFinishMessage(); + return; + } + + String targetInput = inputView.readTargetPosition(); + + Position position = PositionCommand.from(input).toPosition(); + Position targetPosition = PositionCommand.from(targetInput).toPosition(); janggiGame.move(position, targetPosition); outputView.printBoard(janggiGame.getBoardStatus()); diff --git a/src/main/java/dao/BoardDao.java b/src/main/java/dao/BoardDao.java new file mode 100644 index 0000000000..6dd9b90562 --- /dev/null +++ b/src/main/java/dao/BoardDao.java @@ -0,0 +1,125 @@ +package dao; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.Filters; +import domain.Board; +import domain.Piece; +import domain.Team; +import domain.Type; +import domain.vo.Position; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.bson.Document; +import org.bson.types.ObjectId; + +public class BoardDao { + + private final MongoCollection collection; + + public BoardDao() { + MongoClient client = MongoClients.create("mongodb://admin:password123@localhost:27017"); + MongoDatabase database = client.getDatabase("janggi"); + this.collection = database.getCollection("board"); + } + + public String save(Board board, int turnCount) { + ArrayList pieces = new ArrayList<>(); + + for (Map.Entry entry : board.getBoard().entrySet()) { + Position position = entry.getKey(); + Piece piece = entry.getValue(); + + Document document = new Document() + .append("row", position.getRow()) + .append("col", position.getCol()) + .append("team", piece.getTeamName()) + .append("type", piece.getTypeName()); + pieces.add(document); + } + + Document gameDocument = new Document() + .append("pieces", pieces) + .append("turnCount", turnCount); + + collection.insertOne(gameDocument); + return gameDocument.getObjectId("_id").toString(); + } + + public Board findBoardByGameId(String gameId) { + Document gameDocument = collection.find(Filters.eq("_id", new ObjectId(gameId))).first(); + if (gameDocument == null) { + throw new IllegalArgumentException("[ERROR] 해당 게임을 찾을 수 없습니다: " + gameId); + } + + List pieces = gameDocument.getList("pieces", Document.class); + HashMap boardMap = new HashMap<>(); + + for (Document doc : pieces) { + Position position = Position.of(doc.getInteger("row"), doc.getInteger("col")); + Team team = findTeamByName(doc.getString("team")); + Type type = findTypeByName(doc.getString("type")); + boardMap.put(position, Piece.of(team, type)); + } + + return Board.of(boardMap); + } + + public void update(String gameId, Board board, int turnCount) { + ArrayList pieces = new ArrayList<>(); + for (Map.Entry entry : board.getBoard().entrySet()) { + Position position = entry.getKey(); + Piece piece = entry.getValue(); + + Document document = new Document() + .append("row", position.getRow()) + .append("col", position.getCol()) + .append("team", piece.getTeamName()) + .append("type", piece.getTypeName()); + + pieces.add(document); + } + + Document updateDoc = new Document() + .append("pieces", pieces) + .append("turnCount", turnCount); + + collection.replaceOne( + Filters.eq("_id", new ObjectId(gameId)), + updateDoc + ); + } + + public int findTurnCountByGameId(String gameId) { + Document gameDocument = collection.find(Filters.eq("_id", new ObjectId(gameId))).first(); + if (gameDocument == null) { + throw new IllegalArgumentException("[ERROR] 해당 게임을 찾을 수 없습니다: " + gameId); + } + + return gameDocument.getInteger("turnCount"); + } + + private Team findTeamByName(String name) { + for (Team team : Team.values()) { + if (team.getName().equals(name)) { + return team; + } + } + + throw new IllegalArgumentException("[ERROR] 알 수 없는 팀입니다: " + name); + } + + private Type findTypeByName(String name) { + for (Type type : Type.values()) { + if (type.getName().equals(name)) { + return type; + } + } + + throw new IllegalArgumentException("[ERROR] 알 수 없는 기물입니다: " + name); + } +} diff --git a/src/main/java/domain/JanggiGame.java b/src/main/java/domain/JanggiGame.java index 66c9edacbe..e299b61608 100644 --- a/src/main/java/domain/JanggiGame.java +++ b/src/main/java/domain/JanggiGame.java @@ -19,6 +19,13 @@ public static JanggiGame of(final Board board) { return new JanggiGame(board); } + public static JanggiGame of(final Board board, final int turnCount) { + JanggiGame game = new JanggiGame(board); + game.turnCount = TurnCount.of(turnCount); + + return game; + } + public Team currentTurn() { if (turnCount.getTurnCount() % 2 == 0) { return Team.HAN; @@ -27,6 +34,10 @@ public Team currentTurn() { return Team.CHU; } + public int getTurnCount() { + return turnCount.getTurnCount(); + } + public void passTheTurn() { turnCount = TurnCount.of(turnCount.getTurnCount() + 1); } diff --git a/src/main/java/presentation/PositionCommand.java b/src/main/java/presentation/PositionCommand.java new file mode 100644 index 0000000000..9a2ce70709 --- /dev/null +++ b/src/main/java/presentation/PositionCommand.java @@ -0,0 +1,33 @@ +package presentation; + +import domain.vo.Position; + +public class PositionCommand { + + private static final String POSITION_PATTERN = "^\\d+\\s+\\d+$"; + + private final Position position; + + private PositionCommand(final Position position) { + this.position = position; + } + + public static PositionCommand from(final String input) { + validate(input); + + String[] tokens = input.split(" "); + return new PositionCommand( + Position.of(Integer.parseInt(tokens[0]), Integer.parseInt(tokens[1])) + ); + } + + private static void validate(final String input) { + if (!input.matches(POSITION_PATTERN)) { + throw new IllegalArgumentException("[ERROR] 입력 형식이 잘못되었습니다. '숫자 공백 숫자' 형식이어야 합니다."); + } + } + + public Position toPosition() { + return position; + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index f7aaa1c44a..cf584aa323 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,61 +1,35 @@ package view; import domain.Team; -import domain.vo.Position; import java.util.Scanner; public class InputView { - private static final String POSITION_PATTERN = "^\\d+\\s+\\d+$"; final Scanner scanner = new Scanner(System.in); - public Position readPosition() { + public String readPosition() { System.out.println("움직일 기물의 위치를 입력해주세요. (예: 0 0)"); - - String input = scanner.nextLine(); - try { - validatePositionFormat(input); - - String[] tokens = input.split(" "); - return Position.of(Integer.parseInt(tokens[0]), Integer.parseInt(tokens[1])); - } catch (Exception e) { - System.out.println(e.getMessage()); - System.out.println(); - return readPosition(); - } + return scanner.nextLine(); } - public Position readTargetPosition() { + public String readTargetPosition() { System.out.println("기물을 움직일 위치를 입력해주세요. (예: 0 0)"); - - String input = scanner.nextLine(); - try { - validatePositionFormat(input); - - String[] tokens = input.split(" "); - return Position.of(Integer.parseInt(tokens[0]), Integer.parseInt(tokens[1])); - } catch (Exception e) { - System.out.println(e.getMessage()); - System.out.println(); - return readTargetPosition(); - } + return scanner.nextLine(); } public String readArrangement(final Team team) { System.out.println(team.getName() + "나라의 판차림 방식을 선택해주세요.(상마상마, 마상마상, 마상상마, 상마마상)"); - return scanner.nextLine(); } - private void validatePositionFormat(final String input) { - if (input.equals("항복")) { - System.out.println("플레이어의 항복으로 게임을 종료합니다."); - System.exit(0); - } + public String readCommand() { + System.out.println("1. 새 게임 2. 이어하기"); + return scanner.nextLine(); + } - if (!input.matches(POSITION_PATTERN)) { - throw new IllegalArgumentException("[ERROR] 입력 형식이 잘못되었습니다. '숫자 공백 숫자' 형식이어야 합니다."); - } + public String readGameId() { + System.out.println("이어서 진행할 게임 id를 입력해주세요."); + return scanner.nextLine(); } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index b410363b42..bad22b4413 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -81,4 +81,8 @@ public void printScore(int hanScore, int chuScore) { System.out.println("한: " + hanScore + "점"); System.out.println("초: " + chuScore + "점"); } + + public void printCurrentGameId(String gameId) { + System.out.println("현재 진행중인 게임의 아이디는 " + gameId); + } } diff --git a/src/test/java/dao/BoardDaoTest.java b/src/test/java/dao/BoardDaoTest.java new file mode 100644 index 0000000000..233e5853e7 --- /dev/null +++ b/src/test/java/dao/BoardDaoTest.java @@ -0,0 +1,105 @@ +package dao; + +import static org.assertj.core.api.Assertions.assertThat; + +import domain.Board; +import domain.BoardFactory; +import domain.Piece; +import domain.Team; +import domain.Type; +import domain.vo.Position; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class BoardDaoTest { + + private BoardDao boardDao; + + @BeforeEach + void setUp() { + boardDao = new BoardDao(); + } + + @Test + @DisplayName("보드를 저장하고 gameId를 반환한다") + void 보드를_저장하고_gameId를_반환한다() { + // given + Board board = BoardFactory.setUp(); + + // when + String gameId = boardDao.save(board, 0); + + // then + assertThat(gameId).isNotNull(); + } + + @Test + @DisplayName("저장한 보드를 gameId로 조회할 수 있다") + void 저장한_보드를_gameId로_조회할_수_있다() { + // given + Board board = BoardFactory.setUp(); + String gameId = boardDao.save(board, 0); + + // when + Board foundBoard = boardDao.findBoardByGameId(gameId); + + // then + assertThat(foundBoard.getBoard()).hasSize(board.getBoard().size()); + } + + @Test + @DisplayName("저장한 보드의 기물 정보가 일치한다") + void 저장한_보드의_기물_정보가_일치한다() { + // given + Map boardMap = new HashMap<>(); + boardMap.put(Position.of(0, 0), Piece.of(Team.CHU, Type.CHARIOT)); + boardMap.put(Position.of(9, 8), Piece.of(Team.HAN, Type.GENERAL)); + Board board = Board.of(boardMap); + String gameId = boardDao.save(board, 0); + + // when + Board foundBoard = boardDao.findBoardByGameId(gameId); + + // then + Piece piece = foundBoard.findPieceByPosition(Position.of(0, 0)).get(); + assertThat(piece.getTeamName()).isEqualTo("초"); + assertThat(piece.getTypeName()).isEqualTo("차"); + } + + @Test + @DisplayName("턴 카운트를 저장하고 조회할 수 있다") + void 턴_카운트를_저장하고_조회할_수_있다() { + // given + Board board = BoardFactory.setUp(); + String gameId = boardDao.save(board, 3); + + // when + int turnCount = boardDao.findTurnCountByGameId(gameId); + + // then + assertThat(turnCount).isEqualTo(3); + } + + @Test + @DisplayName("보드를 업데이트하면 변경된 내용이 반영된다") + void 보드를_업데이트하면_변경된_내용이_반영된다() { + // given + Board board = BoardFactory.setUp(); + String gameId = boardDao.save(board, 0); + Map updatedMap = new HashMap<>(); + updatedMap.put(Position.of(5, 5), Piece.of(Team.HAN, Type.SOLDIER)); + Board updatedBoard = Board.of(updatedMap); + + // when + boardDao.update(gameId, updatedBoard, 1); + + // then + Board foundBoard = boardDao.findBoardByGameId(gameId); + assertThat(foundBoard.getBoard()).hasSize(1); + int turnCount = boardDao.findTurnCountByGameId(gameId); + assertThat(turnCount).isEqualTo(1); + } +} diff --git a/src/test/java/dao/MongoConnectionTest.java b/src/test/java/dao/MongoConnectionTest.java new file mode 100644 index 0000000000..fb4769c31e --- /dev/null +++ b/src/test/java/dao/MongoConnectionTest.java @@ -0,0 +1,28 @@ +package dao; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoDatabase; +import org.bson.Document; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class MongoConnectionTest { + + private static final String CONNECTION_STRING = "mongodb://admin:password123@localhost:27017"; + private static final String DATABASE_NAME = "janggi"; + + @Test + @DisplayName("MongoDB 서버에 연결할 수 있다") + void MongoDB_서버에_연결할_수_있다() { + try (MongoClient client = MongoClients.create(CONNECTION_STRING)) { + MongoDatabase database = client.getDatabase(DATABASE_NAME); + + Document result = database.runCommand(new Document("ping", 1)); + + assertThat(result.getDouble("ok")).isEqualTo(1.0); + } + } +} From e24988c548b6f00773e4eff68d9f7d549f401c71 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Sat, 11 Apr 2026 18:03:44 +0900 Subject: [PATCH 77/87] =?UTF-8?q?feat:=20=EA=B6=81=EC=9D=B4=200,4=20?= =?UTF-8?q?=EB=98=90=EB=8A=94=209,4=20=EC=9C=84=EC=B9=98=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=EB=8C=80=EA=B0=81=EC=84=A0=20=EC=9D=B4=EB=8F=99=20=EA=B7=9C?= =?UTF-8?q?=EC=B9=99=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/Application.java | 2 +- .../java/controller/JanggiController.java | 2 +- src/main/java/dao/{ => mongodb}/BoardDao.java | 2 +- .../domain/strategy/GeneralMoveStrategy.java | 10 ++++----- src/test/java/dao/BoardDaoTest.java | 1 + .../strategy/GeneralMoveStrategyTest.java | 22 +++++++++++++++++++ 7 files changed, 32 insertions(+), 9 deletions(-) rename src/main/java/dao/{ => mongodb}/BoardDao.java (99%) diff --git a/README.md b/README.md index 823fa24cfe..668d64f5e0 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ - [x] 왕이 잡히는 경우 게임에서 진다. - 왕이 잡혔을 때 게임을 종료한다. - [x] 현재 남아 있는 기물에 대한 점수를 구할수 있어야 한다. -- [ ] 애플리케이션을 재시작하더라도 이전에 하던 장기 게임을 다시 시작할 수 있어야 한다. +- [x] 애플리케이션을 재시작하더라도 이전에 하던 장기 게임을 다시 시작할 수 있어야 한다. - DB를 적용할 때 도메인 객체의 변경을 최소화해야 한다. ### 예외 기능 diff --git a/src/main/java/Application.java b/src/main/java/Application.java index e36a1ca5a5..7c142c2bec 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,5 +1,5 @@ import controller.JanggiController; -import dao.BoardDao; +import dao.mongodb.BoardDao; import view.InputView; import view.OutputView; diff --git a/src/main/java/controller/JanggiController.java b/src/main/java/controller/JanggiController.java index 3fc849f792..5dc76fea30 100644 --- a/src/main/java/controller/JanggiController.java +++ b/src/main/java/controller/JanggiController.java @@ -1,6 +1,6 @@ package controller; -import dao.BoardDao; +import dao.mongodb.BoardDao; import domain.Board; import domain.BoardFactory; import domain.Formation; diff --git a/src/main/java/dao/BoardDao.java b/src/main/java/dao/mongodb/BoardDao.java similarity index 99% rename from src/main/java/dao/BoardDao.java rename to src/main/java/dao/mongodb/BoardDao.java index 6dd9b90562..21eec581ae 100644 --- a/src/main/java/dao/BoardDao.java +++ b/src/main/java/dao/mongodb/BoardDao.java @@ -1,4 +1,4 @@ -package dao; +package dao.mongodb; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; diff --git a/src/main/java/domain/strategy/GeneralMoveStrategy.java b/src/main/java/domain/strategy/GeneralMoveStrategy.java index 34769cc7a1..15c7d5c9e8 100644 --- a/src/main/java/domain/strategy/GeneralMoveStrategy.java +++ b/src/main/java/domain/strategy/GeneralMoveStrategy.java @@ -43,7 +43,7 @@ private boolean isNotCorrectPath(final Position from, final Position to) { return true; } - if (hanSoldierCanDiagonalMoveInPalace(from, to) || chuSoldierCanDiagonalMoveInPalace(from, to)) { + if (hanGeneralCanDiagonalMoveInPalace(from, to) || chuGeneralCanDiagonalMoveInPalace(from, to)) { return true; } @@ -56,9 +56,9 @@ private boolean palaceInRange(final Position position) { && (3 <= position.getCol() && position.getCol() <= 5)); } - private boolean chuSoldierCanDiagonalMoveInPalace(Position from, Position to) { + private boolean chuGeneralCanDiagonalMoveInPalace(Position from, Position to) { if ((from.getRow() == 7 && from.getCol() == 4) || (from.getRow() == 8 && from.getCol() == 3) - || (from.getRow() == 8 && from.getCol() == 5)) { + || (from.getRow() == 8 && from.getCol() == 5 || (from.getRow() == 0 && from.getCol() == 4))) { if (isDiagonal(from, to)) { return true; } @@ -66,9 +66,9 @@ private boolean chuSoldierCanDiagonalMoveInPalace(Position from, Position to) { return false; } - private boolean hanSoldierCanDiagonalMoveInPalace(Position from, Position to) { + private boolean hanGeneralCanDiagonalMoveInPalace(Position from, Position to) { if ((from.getRow() == 2 && from.getCol() == 4) || (from.getRow() == 1 && from.getCol() == 3) - || (from.getRow() == 1 && from.getCol() == 5)) { + || (from.getRow() == 1 && from.getCol() == 5) || (from.getRow() == 9 && from.getCol() == 4)) { if (isDiagonal(from, to)) { return true; } diff --git a/src/test/java/dao/BoardDaoTest.java b/src/test/java/dao/BoardDaoTest.java index 233e5853e7..ca0d987a3e 100644 --- a/src/test/java/dao/BoardDaoTest.java +++ b/src/test/java/dao/BoardDaoTest.java @@ -2,6 +2,7 @@ import static org.assertj.core.api.Assertions.assertThat; +import dao.mongodb.BoardDao; import domain.Board; import domain.BoardFactory; import domain.Piece; diff --git a/src/test/java/domain/strategy/GeneralMoveStrategyTest.java b/src/test/java/domain/strategy/GeneralMoveStrategyTest.java index 81074f2dd0..10f37ae458 100644 --- a/src/test/java/domain/strategy/GeneralMoveStrategyTest.java +++ b/src/test/java/domain/strategy/GeneralMoveStrategyTest.java @@ -10,6 +10,8 @@ import org.junit.jupiter.api.Test; import java.util.Map; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; class GeneralMoveStrategyTest { @@ -86,4 +88,24 @@ void setUp() { // when // then assertFalse(piece.canMovePiece(from, to, pieceOfPath)); } + + @ParameterizedTest + @DisplayName("궁의 0,4 또는 9,4 위치에서 대각선 이동 시 이동하지 않는다.") + @CsvSource({ + "0, 4, 1, 3", + "0, 4, 1, 5", + "9, 4, 8, 3", + "9, 4, 8, 5" + }) + void 궁_대각선_이동이_불가능한_위치면_이동_불가2(int fromRow, int fromCol, int toRow, int toCol) { + // given + Position from = Position.of(fromRow, fromCol); + Position to = Position.of(toRow, toCol); + HashMap pieceOfPath = new HashMap<>(); + + pieceOfPath.put(to, null); + + // when // then + assertFalse(mover.canMovePiece(from, to, pieceOfPath)); + } } From 7c2b8e04f8bc1a155bd4324bb3ca430318ce7d38 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Sun, 12 Apr 2026 17:01:16 +0900 Subject: [PATCH 78/87] =?UTF-8?q?feat:=20=EA=B6=81=EC=84=B1=20=EB=B0=96?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=B0=A8=EC=9D=98=20=EB=8C=80=EA=B0=81?= =?UTF-8?q?=EC=84=A0=20=EC=9D=B4=EB=8F=99=20=EC=A0=9C=ED=95=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/JanggiController.java | 3 ++- .../java/domain/strategy/ChariotMoveStrategy.java | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/main/java/controller/JanggiController.java b/src/main/java/controller/JanggiController.java index 5dc76fea30..1944c5dc8f 100644 --- a/src/main/java/controller/JanggiController.java +++ b/src/main/java/controller/JanggiController.java @@ -14,6 +14,7 @@ public class JanggiController { private static final String RESUME_GAME_NUMBER = "2"; + private static final String SURRENDER = "항복"; private final InputView inputView; private final OutputView outputView; @@ -122,7 +123,7 @@ private void movePosition(JanggiGame janggiGame) { outputView.printCurrentTurn(janggiGame.currentTurn()); String input = inputView.readPosition(); - if (input.equals("항복")) { + if (input.equals(SURRENDER)) { outputView.printGameFinishMessage(); return; } diff --git a/src/main/java/domain/strategy/ChariotMoveStrategy.java b/src/main/java/domain/strategy/ChariotMoveStrategy.java index 2482d09e03..066c714e41 100644 --- a/src/main/java/domain/strategy/ChariotMoveStrategy.java +++ b/src/main/java/domain/strategy/ChariotMoveStrategy.java @@ -50,6 +50,12 @@ public boolean canMove(final Piece mover, final Position from, final Position to } private boolean isNotCorrectPath(final Position from, final Position to) { + if (!palaceInRange(from)) { + if (isDiagonal(from, to)) { + return true; + } + } + if (isInPalaceAndCanDiagonalMove(from)) { if (isDiagonal(from, to)) { if (Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) <= 4) { @@ -64,8 +70,9 @@ private boolean isNotCorrectPath(final Position from, final Position to) { private boolean isInPalaceAndCanDiagonalMove(final Position position) { int row = position.getRow(); int column = position.getCol(); + if ((row == 0 && column == 4) || (row == 2 && column == 4) || (row == 1 && column == 3) || (row == 1 && column == 5) - || (row == 7 && column == 4) || (row == 9 && column == 4) || (row == 8 && column == 3) || (row == 8 && column == 5)) { + || (row == 7 && column == 4) || (row == 9 && column == 4) || (row == 8 && column == 3) || (row == 8 && column == 5)) { return false; } @@ -75,4 +82,10 @@ private boolean isInPalaceAndCanDiagonalMove(final Position position) { private boolean isDiagonal(final Position from, final Position to) { return Math.abs(from.getRow() - to.getRow()) >= 1 && Math.abs(from.getCol() - to.getCol()) >= 1; } + + private boolean palaceInRange(final Position position) { + return (((0 <= position.getRow() && position.getRow() <= 2) || (7 <= position.getRow() + && position.getRow() <= 9)) + && (3 <= position.getCol() && position.getCol() <= 5)); + } } \ No newline at end of file From 06a67be01b38be39f85e1876325f0b08125d2519 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Mon, 13 Apr 2026 10:32:19 +0900 Subject: [PATCH 79/87] =?UTF-8?q?feat:=20=EC=9E=A5=EA=B8=B0=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=EC=97=90=20=ED=95=AD=EB=B3=B5=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=ED=96=89=EC=9C=84=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/JanggiController.java | 8 +++++++- src/main/java/domain/JanggiGame.java | 9 +++++++++ src/main/java/view/OutputView.java | 4 ++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/main/java/controller/JanggiController.java b/src/main/java/controller/JanggiController.java index 1944c5dc8f..781b7bf339 100644 --- a/src/main/java/controller/JanggiController.java +++ b/src/main/java/controller/JanggiController.java @@ -70,6 +70,12 @@ private void playGame(String gameId, JanggiGame janggiGame) { outputView.printScore(janggiGame.calculateScore(Team.HAN), janggiGame.calculateScore(Team.CHU)); break; } + + if (janggiGame.isSurrendered()) { + outputView.printGameSurrenderMessage(); + outputView.printScore(janggiGame.calculateScore(Team.HAN), janggiGame.calculateScore(Team.CHU)); + break; + } } } @@ -124,7 +130,7 @@ private void movePosition(JanggiGame janggiGame) { String input = inputView.readPosition(); if (input.equals(SURRENDER)) { - outputView.printGameFinishMessage(); + janggiGame.surrender(); return; } diff --git a/src/main/java/domain/JanggiGame.java b/src/main/java/domain/JanggiGame.java index e299b61608..3231bdec2f 100644 --- a/src/main/java/domain/JanggiGame.java +++ b/src/main/java/domain/JanggiGame.java @@ -9,6 +9,7 @@ public class JanggiGame { private final Board board; private TurnCount turnCount; + private boolean isSurrender; private JanggiGame(final Board board) { this.board = board; @@ -54,6 +55,14 @@ public boolean isFinished() { return !board.isGeneralAlive(Team.CHU) || !board.isGeneralAlive(Team.HAN); } + public boolean isSurrendered() { + return isSurrender; + } + + public void surrender() { + isSurrender = true; + } + public int calculateScore(Team team) { return board.calculateScore(team); } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index bad22b4413..ef46e660d5 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -85,4 +85,8 @@ public void printScore(int hanScore, int chuScore) { public void printCurrentGameId(String gameId) { System.out.println("현재 진행중인 게임의 아이디는 " + gameId); } + + public void printGameSurrenderMessage() { + System.out.println("유저의 항복으로 인해 게임을 종료합니다."); + } } From 6d24523f6edc8302740fd7c71b0c74ef9a7080c8 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Mon, 13 Apr 2026 11:07:01 +0900 Subject: [PATCH 80/87] =?UTF-8?q?refactor:=20Document=20=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=20=EB=A7=8C=EB=93=9C=EB=8A=94=20=EA=B3=B5=ED=86=B5=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EB=A9=94=EC=86=8C=EB=93=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/dao/mongodb/BoardDao.java | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/dao/mongodb/BoardDao.java b/src/main/java/dao/mongodb/BoardDao.java index 21eec581ae..f9094d9e30 100644 --- a/src/main/java/dao/mongodb/BoardDao.java +++ b/src/main/java/dao/mongodb/BoardDao.java @@ -34,11 +34,7 @@ public String save(Board board, int turnCount) { Position position = entry.getKey(); Piece piece = entry.getValue(); - Document document = new Document() - .append("row", position.getRow()) - .append("col", position.getCol()) - .append("team", piece.getTeamName()) - .append("type", piece.getTypeName()); + Document document = toDocument(position, piece); pieces.add(document); } @@ -75,11 +71,7 @@ public void update(String gameId, Board board, int turnCount) { Position position = entry.getKey(); Piece piece = entry.getValue(); - Document document = new Document() - .append("row", position.getRow()) - .append("col", position.getCol()) - .append("team", piece.getTeamName()) - .append("type", piece.getTypeName()); + Document document = toDocument(position, piece); pieces.add(document); } @@ -103,6 +95,14 @@ public int findTurnCountByGameId(String gameId) { return gameDocument.getInteger("turnCount"); } + private Document toDocument(Position position, Piece piece) { + return new Document() + .append("row", position.getRow()) + .append("col", position.getCol()) + .append("team", piece.getTeamName()) + .append("type", piece.getTypeName()); + } + private Team findTeamByName(String name) { for (Team team : Team.values()) { if (team.getName().equals(name)) { From 2d00432a6ebcf72860381e079119708eedc75845 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Mon, 13 Apr 2026 13:33:43 +0900 Subject: [PATCH 81/87] =?UTF-8?q?refacotr:=20=EC=9E=A5=EA=B8=B0=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20=EC=8B=9C?= =?UTF-8?q?=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20=EC=B4=88=EA=B8=B0?= =?UTF-8?q?=ED=99=94=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/JanggiController.java | 2 +- src/main/java/dao/mongodb/BoardDao.java | 4 ++-- src/main/java/domain/JanggiGame.java | 9 +++++---- src/test/java/dao/BoardDaoTest.java | 3 +-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/controller/JanggiController.java b/src/main/java/controller/JanggiController.java index 781b7bf339..2bf15ecc1c 100644 --- a/src/main/java/controller/JanggiController.java +++ b/src/main/java/controller/JanggiController.java @@ -63,7 +63,7 @@ private void playGame(String gameId, JanggiGame janggiGame) { while (true) { movePosition(janggiGame); - boardDao.update(gameId, Board.of(janggiGame.getBoardStatus()), janggiGame.getTurnCount()); + boardDao.update(gameId, janggiGame.getBoardStatus(), janggiGame.getTurnCount()); if (janggiGame.isFinished()) { outputView.printGameFinishMessage(); diff --git a/src/main/java/dao/mongodb/BoardDao.java b/src/main/java/dao/mongodb/BoardDao.java index f9094d9e30..8e49c952e1 100644 --- a/src/main/java/dao/mongodb/BoardDao.java +++ b/src/main/java/dao/mongodb/BoardDao.java @@ -65,9 +65,9 @@ public Board findBoardByGameId(String gameId) { return Board.of(boardMap); } - public void update(String gameId, Board board, int turnCount) { + public void update(String gameId, Map boardStatus, int turnCount) { ArrayList pieces = new ArrayList<>(); - for (Map.Entry entry : board.getBoard().entrySet()) { + for (Map.Entry entry : boardStatus.entrySet()) { Position position = entry.getKey(); Piece piece = entry.getValue(); diff --git a/src/main/java/domain/JanggiGame.java b/src/main/java/domain/JanggiGame.java index 3231bdec2f..a0cd1c551b 100644 --- a/src/main/java/domain/JanggiGame.java +++ b/src/main/java/domain/JanggiGame.java @@ -11,17 +11,18 @@ public class JanggiGame { private TurnCount turnCount; private boolean isSurrender; - private JanggiGame(final Board board) { + private JanggiGame(final Board board, final TurnCount turnCount, boolean isSurrender) { this.board = board; - this.turnCount = TurnCount.of(DEFAULT_TURN_COUNT); + this.turnCount = turnCount; + this.isSurrender = isSurrender; } public static JanggiGame of(final Board board) { - return new JanggiGame(board); + return new JanggiGame(board, TurnCount.of(DEFAULT_TURN_COUNT), false); } public static JanggiGame of(final Board board, final int turnCount) { - JanggiGame game = new JanggiGame(board); + JanggiGame game = new JanggiGame(board, TurnCount.of(turnCount), false); game.turnCount = TurnCount.of(turnCount); return game; diff --git a/src/test/java/dao/BoardDaoTest.java b/src/test/java/dao/BoardDaoTest.java index ca0d987a3e..9d20776c92 100644 --- a/src/test/java/dao/BoardDaoTest.java +++ b/src/test/java/dao/BoardDaoTest.java @@ -92,10 +92,9 @@ void setUp() { String gameId = boardDao.save(board, 0); Map updatedMap = new HashMap<>(); updatedMap.put(Position.of(5, 5), Piece.of(Team.HAN, Type.SOLDIER)); - Board updatedBoard = Board.of(updatedMap); // when - boardDao.update(gameId, updatedBoard, 1); + boardDao.update(gameId, updatedMap, 1); // then Board foundBoard = boardDao.findBoardByGameId(gameId); From 0b983813cafcfc26b404ddcb6912f725f0147f72 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Mon, 13 Apr 2026 14:31:53 +0900 Subject: [PATCH 82/87] =?UTF-8?q?refactor:=20=ED=98=84=EC=9E=AC=20?= =?UTF-8?q?=ED=84=B4=EC=9D=84=20=EB=A6=AC=ED=84=B4=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=A9=94=EC=86=8C=EB=93=9C=EC=9D=98=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/JanggiGame.java | 6 +----- src/main/java/domain/Team.java | 1 + 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/domain/JanggiGame.java b/src/main/java/domain/JanggiGame.java index a0cd1c551b..1d81ffb16d 100644 --- a/src/main/java/domain/JanggiGame.java +++ b/src/main/java/domain/JanggiGame.java @@ -29,11 +29,7 @@ public static JanggiGame of(final Board board, final int turnCount) { } public Team currentTurn() { - if (turnCount.getTurnCount() % 2 == 0) { - return Team.HAN; - } - - return Team.CHU; + return Team.from(turnCount.getTurnCount()); } public int getTurnCount() { diff --git a/src/main/java/domain/Team.java b/src/main/java/domain/Team.java index 6747774ca1..049b4e7882 100644 --- a/src/main/java/domain/Team.java +++ b/src/main/java/domain/Team.java @@ -18,6 +18,7 @@ public static Team from(final int turnCount) { if (turnCount % 2 == 0) { return HAN; } + return CHU; } } From ae1956c275467894b865285ad222e0f4d71d650a Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Mon, 13 Apr 2026 16:13:10 +0900 Subject: [PATCH 83/87] =?UTF-8?q?refactor:=20BoardDao=EC=9D=98=20db=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0=EC=B1=85=EC=9E=84=20MongoConnection=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 9 ++++-- src/main/java/dao/mongodb/BoardDao.java | 11 ++----- .../java/dao/mongodb/MongoConnection.java | 30 +++++++++++++++++++ src/test/java/dao/BoardDaoTest.java | 3 +- 4 files changed, 41 insertions(+), 12 deletions(-) create mode 100644 src/main/java/dao/mongodb/MongoConnection.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index 7c142c2bec..8660a5c33c 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,12 +1,15 @@ import controller.JanggiController; import dao.mongodb.BoardDao; +import dao.mongodb.MongoConnection; import view.InputView; import view.OutputView; public class Application { public static void main(String[] args) { - JanggiController janggiController = new JanggiController(new InputView(), new OutputView(), new BoardDao()); - janggiController.run(); + try (MongoConnection connection = new MongoConnection()) { + JanggiController janggiController = new JanggiController(new InputView(), new OutputView(), new BoardDao(connection)); + janggiController.run(); + } } -} +} \ No newline at end of file diff --git a/src/main/java/dao/mongodb/BoardDao.java b/src/main/java/dao/mongodb/BoardDao.java index 8e49c952e1..401f5f76ee 100644 --- a/src/main/java/dao/mongodb/BoardDao.java +++ b/src/main/java/dao/mongodb/BoardDao.java @@ -1,9 +1,6 @@ package dao.mongodb; -import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoClients; import com.mongodb.client.MongoCollection; -import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.Filters; import domain.Board; import domain.Piece; @@ -21,10 +18,8 @@ public class BoardDao { private final MongoCollection collection; - public BoardDao() { - MongoClient client = MongoClients.create("mongodb://admin:password123@localhost:27017"); - MongoDatabase database = client.getDatabase("janggi"); - this.collection = database.getCollection("board"); + public BoardDao(MongoConnection connection) { + this.collection = connection.getCollection("board"); } public String save(Board board, int turnCount) { @@ -122,4 +117,4 @@ private Type findTypeByName(String name) { throw new IllegalArgumentException("[ERROR] 알 수 없는 기물입니다: " + name); } -} +} \ No newline at end of file diff --git a/src/main/java/dao/mongodb/MongoConnection.java b/src/main/java/dao/mongodb/MongoConnection.java new file mode 100644 index 0000000000..0220c59b1e --- /dev/null +++ b/src/main/java/dao/mongodb/MongoConnection.java @@ -0,0 +1,30 @@ +package dao.mongodb; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import org.bson.Document; + +public class MongoConnection implements AutoCloseable { + + private static final String CONNECTION_STRING = "mongodb://admin:password123@localhost:27017"; + private static final String DATABASE_NAME = "janggi"; + + private final MongoClient client; + private final MongoDatabase database; + + public MongoConnection() { + this.client = MongoClients.create(CONNECTION_STRING); + this.database = client.getDatabase(DATABASE_NAME); + } + + public MongoCollection getCollection(String name) { + return database.getCollection(name); + } + + @Override + public void close() { + client.close(); + } +} \ No newline at end of file diff --git a/src/test/java/dao/BoardDaoTest.java b/src/test/java/dao/BoardDaoTest.java index 9d20776c92..279f930355 100644 --- a/src/test/java/dao/BoardDaoTest.java +++ b/src/test/java/dao/BoardDaoTest.java @@ -3,6 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import dao.mongodb.BoardDao; +import dao.mongodb.MongoConnection; import domain.Board; import domain.BoardFactory; import domain.Piece; @@ -21,7 +22,7 @@ class BoardDaoTest { @BeforeEach void setUp() { - boardDao = new BoardDao(); + boardDao = new BoardDao(new MongoConnection()); } @Test From f0cecfd464c6ebf002593afbd8180b41b399d44e Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Mon, 13 Apr 2026 17:43:31 +0900 Subject: [PATCH 84/87] =?UTF-8?q?refactor:=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=EC=97=90=20=EC=9E=88=EB=8D=98=20=EC=83=81=EC=B0=A8?= =?UTF-8?q?=EB=A6=BC=20=EB=B6=84=EA=B8=B0=20=EC=BD=94=EB=93=9C=20formation?= =?UTF-8?q?=20enum=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A1=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/JanggiController.java | 21 ++----------------- src/main/java/domain/Formation.java | 19 +++++++++++++++-- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/main/java/controller/JanggiController.java b/src/main/java/controller/JanggiController.java index 2bf15ecc1c..ffa500afcd 100644 --- a/src/main/java/controller/JanggiController.java +++ b/src/main/java/controller/JanggiController.java @@ -83,7 +83,7 @@ private Board readChuFormation(Board board) { while (true) { try { String chuArrangement = inputView.readArrangement(Team.CHU); - board = applyArrangement(chuArrangement, board, Team.CHU); + board = Formation.from(chuArrangement, board, Team.CHU); return board; } catch (Exception e) { System.out.println(e.getMessage()); @@ -96,7 +96,7 @@ private Board readHanFormation(Board board) { while (true) { try { String hanArrangement = inputView.readArrangement(Team.HAN); - board = applyArrangement(hanArrangement, board, Team.HAN); + board = Formation.from(hanArrangement, board, Team.HAN); return board; } catch (Exception e) { @@ -106,23 +106,6 @@ private Board readHanFormation(Board board) { } } - private static Board applyArrangement(String arrangement, Board board, Team team) { - if (Formation.from(arrangement) == Formation.SANG_MA_SANG_MA) { - return BoardFactory.setUpLeftElephantFormation(board.getBoard(), team); - } - if (Formation.from(arrangement) == Formation.MA_SANG_MA_SANG) { - return BoardFactory.setUpRightElephantFormation(board.getBoard(), team); - } - if (Formation.from(arrangement) == Formation.MA_SANG_SANG_MA) { - return BoardFactory.setUpInnerElephantFormation(board.getBoard(), team); - } - if (Formation.from(arrangement) == Formation.SANG_MA_MA_SANG) { - return BoardFactory.setUpOuterElephantFormation(board.getBoard(), team); - } - - return board; - } - private void movePosition(JanggiGame janggiGame) { while (true) { try { diff --git a/src/main/java/domain/Formation.java b/src/main/java/domain/Formation.java index 9d516bcd45..768d9953be 100644 --- a/src/main/java/domain/Formation.java +++ b/src/main/java/domain/Formation.java @@ -15,10 +15,25 @@ public enum Formation { this.koreanName = koreanName; } - public static Formation from(String input) { - return Arrays.stream(values()) + public static Board from(String input, Board board, Team team) { + Formation matchedFormation = Arrays.stream(values()) .filter(formation -> formation.koreanName.equals(input)) .findFirst() .orElseThrow(() -> new IllegalArgumentException("[ERROR] 잘못된 진형 입력입니다.")); + + if (matchedFormation == Formation.SANG_MA_SANG_MA) { + return BoardFactory.setUpLeftElephantFormation(board.getBoard(), team); + } + if (matchedFormation == Formation.MA_SANG_MA_SANG) { + return BoardFactory.setUpRightElephantFormation(board.getBoard(), team); + } + if (matchedFormation == Formation.MA_SANG_SANG_MA) { + return BoardFactory.setUpInnerElephantFormation(board.getBoard(), team); + } + if (matchedFormation == Formation.SANG_MA_MA_SANG) { + return BoardFactory.setUpOuterElephantFormation(board.getBoard(), team); + } + + return board; } } From 6b73bf049e38d0517556daf8789a8ea851f0102d Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Mon, 13 Apr 2026 19:56:46 +0900 Subject: [PATCH 85/87] =?UTF-8?q?feat:=20=EC=9D=B4=EB=AF=B8=20=EC=A2=85?= =?UTF-8?q?=EB=A3=8C=EB=90=9C=20=EA=B2=8C=EC=9E=84=EC=9D=84=20=EB=B6=88?= =?UTF-8?q?=EB=9F=AC=EC=99=94=EC=9D=84=20=EB=95=8C=20=EC=A2=85=EB=A3=8C?= =?UTF-8?q?=EB=90=90=EC=9D=8C=EC=9D=84=20=EC=9C=A0=EC=A0=80=EC=97=90?= =?UTF-8?q?=EA=B2=8C=20=EC=95=8C=EB=A6=AC=EA=B3=A0=20=EC=9E=AC=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=EB=B0=9B=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/JanggiController.java | 28 +++-- src/main/java/dao/mongodb/BoardDao.java | 119 ++++++++---------- src/main/java/domain/Team.java | 9 ++ src/main/java/domain/Type.java | 9 ++ src/main/java/dto/PieceDto.java | 34 +++++ src/test/java/dao/BoardDaoTest.java | 68 +++++----- 6 files changed, 163 insertions(+), 104 deletions(-) create mode 100644 src/main/java/dto/PieceDto.java diff --git a/src/main/java/controller/JanggiController.java b/src/main/java/controller/JanggiController.java index ffa500afcd..98c97ddb53 100644 --- a/src/main/java/controller/JanggiController.java +++ b/src/main/java/controller/JanggiController.java @@ -7,6 +7,8 @@ import domain.JanggiGame; import domain.Team; import domain.vo.Position; +import dto.PieceDto; +import java.util.List; import presentation.PositionCommand; import view.InputView; import view.OutputView; @@ -43,18 +45,28 @@ private void startNewGame() { board = readChuFormation(board); JanggiGame janggiGame = JanggiGame.of(board); - String gameId = boardDao.save(board, janggiGame.getTurnCount()); + String gameId = boardDao.save(PieceDto.fromBoard(board.getBoard()), janggiGame.getTurnCount()); playGame(gameId, janggiGame); } private void resumeGame() { - String gameId = inputView.readGameId(); - Board board = boardDao.findBoardByGameId(gameId); - int turnCount = boardDao.findTurnCountByGameId(gameId); - JanggiGame janggiGame = JanggiGame.of(board, turnCount); + while (true) { + try { + String gameId = inputView.readGameId(); + List pieceDtos = boardDao.findPiecesByGameId(gameId); - playGame(gameId, janggiGame); + int turnCount = boardDao.findTurnCountByGameId(gameId); + Board board = PieceDto.toBoard(pieceDtos); + JanggiGame janggiGame = JanggiGame.of(board, turnCount); + + playGame(gameId, janggiGame); + return; + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + System.out.println(); + } + } } private void playGame(String gameId, JanggiGame janggiGame) { @@ -63,15 +75,17 @@ private void playGame(String gameId, JanggiGame janggiGame) { while (true) { movePosition(janggiGame); - boardDao.update(gameId, janggiGame.getBoardStatus(), janggiGame.getTurnCount()); + boardDao.update(gameId, PieceDto.fromBoard(janggiGame.getBoardStatus()), janggiGame.getTurnCount()); if (janggiGame.isFinished()) { + boardDao.finish(gameId); outputView.printGameFinishMessage(); outputView.printScore(janggiGame.calculateScore(Team.HAN), janggiGame.calculateScore(Team.CHU)); break; } if (janggiGame.isSurrendered()) { + boardDao.finish(gameId); outputView.printGameSurrenderMessage(); outputView.printScore(janggiGame.calculateScore(Team.HAN), janggiGame.calculateScore(Team.CHU)); break; diff --git a/src/main/java/dao/mongodb/BoardDao.java b/src/main/java/dao/mongodb/BoardDao.java index 401f5f76ee..ee0e611b01 100644 --- a/src/main/java/dao/mongodb/BoardDao.java +++ b/src/main/java/dao/mongodb/BoardDao.java @@ -2,15 +2,9 @@ import com.mongodb.client.MongoCollection; import com.mongodb.client.model.Filters; -import domain.Board; -import domain.Piece; -import domain.Team; -import domain.Type; -import domain.vo.Position; +import dto.PieceDto; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.bson.Document; import org.bson.types.ObjectId; @@ -22,99 +16,96 @@ public BoardDao(MongoConnection connection) { this.collection = connection.getCollection("board"); } - public String save(Board board, int turnCount) { - ArrayList pieces = new ArrayList<>(); + public String save(List pieces, int turnCount) { + ArrayList pieceDocuments = new ArrayList<>(); - for (Map.Entry entry : board.getBoard().entrySet()) { - Position position = entry.getKey(); - Piece piece = entry.getValue(); - - Document document = toDocument(position, piece); - pieces.add(document); + for (PieceDto pieceDto : pieces) { + pieceDocuments.add(toDocument(pieceDto)); } - Document gameDocument = new Document() - .append("pieces", pieces) - .append("turnCount", turnCount); + Document gameDocument = getDocument(turnCount, pieceDocuments); collection.insertOne(gameDocument); return gameDocument.getObjectId("_id").toString(); } - public Board findBoardByGameId(String gameId) { - Document gameDocument = collection.find(Filters.eq("_id", new ObjectId(gameId))).first(); - if (gameDocument == null) { - throw new IllegalArgumentException("[ERROR] 해당 게임을 찾을 수 없습니다: " + gameId); + public List findPiecesByGameId(String gameId) { + Document gameDocument = findGameDocument(gameId); + + if (gameDocument.getBoolean("isFinished")) { + throw new IllegalArgumentException("[ERROR] 이미 종료된 게임입니다: " + gameId); } List pieces = gameDocument.getList("pieces", Document.class); - HashMap boardMap = new HashMap<>(); + List pieceDtos = new ArrayList<>(); for (Document doc : pieces) { - Position position = Position.of(doc.getInteger("row"), doc.getInteger("col")); - Team team = findTeamByName(doc.getString("team")); - Type type = findTypeByName(doc.getString("type")); - boardMap.put(position, Piece.of(team, type)); + pieceDtos.add(toPieceDto(doc)); } - return Board.of(boardMap); + return pieceDtos; } - public void update(String gameId, Map boardStatus, int turnCount) { - ArrayList pieces = new ArrayList<>(); - for (Map.Entry entry : boardStatus.entrySet()) { - Position position = entry.getKey(); - Piece piece = entry.getValue(); + public int findTurnCountByGameId(String gameId) { + Document gameDocument = findGameDocument(gameId); + return gameDocument.getInteger("turnCount"); + } - Document document = toDocument(position, piece); + public void update(String gameId, List pieces, int turnCount) { + ArrayList pieceDocuments = new ArrayList<>(); - pieces.add(document); + for (PieceDto pieceDto : pieces) { + pieceDocuments.add(toDocument(pieceDto)); } - Document updateDoc = new Document() - .append("pieces", pieces) - .append("turnCount", turnCount); + Document updateFields = new Document("$set", new Document() + .append("pieces", pieceDocuments) + .append("turnCount", turnCount)); - collection.replaceOne( + collection.updateOne( Filters.eq("_id", new ObjectId(gameId)), - updateDoc + updateFields ); } - public int findTurnCountByGameId(String gameId) { + public void finish(String gameId) { + Document updateFields = new Document("$set", new Document("isFinished", true)); + + collection.updateOne( + Filters.eq("_id", new ObjectId(gameId)), + updateFields + ); + } + + private Document findGameDocument(String gameId) { Document gameDocument = collection.find(Filters.eq("_id", new ObjectId(gameId))).first(); if (gameDocument == null) { throw new IllegalArgumentException("[ERROR] 해당 게임을 찾을 수 없습니다: " + gameId); } - - return gameDocument.getInteger("turnCount"); + return gameDocument; } - private Document toDocument(Position position, Piece piece) { + private Document getDocument(int turnCount, ArrayList pieceDocuments) { return new Document() - .append("row", position.getRow()) - .append("col", position.getCol()) - .append("team", piece.getTeamName()) - .append("type", piece.getTypeName()); + .append("pieces", pieceDocuments) + .append("turnCount", turnCount) + .append("isFinished", false); } - private Team findTeamByName(String name) { - for (Team team : Team.values()) { - if (team.getName().equals(name)) { - return team; - } - } - - throw new IllegalArgumentException("[ERROR] 알 수 없는 팀입니다: " + name); + private Document toDocument(PieceDto pieceDto) { + return new Document() + .append("row", pieceDto.row()) + .append("col", pieceDto.col()) + .append("team", pieceDto.team()) + .append("type", pieceDto.type()); } - private Type findTypeByName(String name) { - for (Type type : Type.values()) { - if (type.getName().equals(name)) { - return type; - } - } - - throw new IllegalArgumentException("[ERROR] 알 수 없는 기물입니다: " + name); + private PieceDto toPieceDto(Document doc) { + return new PieceDto( + doc.getInteger("row"), + doc.getInteger("col"), + doc.getString("team"), + doc.getString("type") + ); } } \ No newline at end of file diff --git a/src/main/java/domain/Team.java b/src/main/java/domain/Team.java index 049b4e7882..d365447c58 100644 --- a/src/main/java/domain/Team.java +++ b/src/main/java/domain/Team.java @@ -14,6 +14,15 @@ public String getName() { return name; } + public static Team fromName(final String name) { + for (Team team : values()) { + if (team.name.equals(name)) { + return team; + } + } + throw new IllegalArgumentException("[ERROR] 알 수 없는 팀입니다: " + name); + } + public static Team from(final int turnCount) { if (turnCount % 2 == 0) { return HAN; diff --git a/src/main/java/domain/Type.java b/src/main/java/domain/Type.java index 4f139b59ea..43d20ac5c3 100644 --- a/src/main/java/domain/Type.java +++ b/src/main/java/domain/Type.java @@ -28,6 +28,15 @@ public enum Type { this.score = score; } + public static Type fromName(final String name) { + for (Type type : values()) { + if (type.name.equals(name)) { + return type; + } + } + throw new IllegalArgumentException("[ERROR] 알 수 없는 기물입니다: " + name); + } + public MoveStrategy getStrategy() { return strategy; } diff --git a/src/main/java/dto/PieceDto.java b/src/main/java/dto/PieceDto.java new file mode 100644 index 0000000000..f5182772a2 --- /dev/null +++ b/src/main/java/dto/PieceDto.java @@ -0,0 +1,34 @@ +package dto; + +import domain.Board; +import domain.Piece; +import domain.Team; +import domain.Type; +import domain.vo.Position; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public record PieceDto(int row, int col, String team, String type) { + + public static List fromBoard(Map boardStatus) { + List pieceDtos = new ArrayList<>(); + for (Map.Entry entry : boardStatus.entrySet()) { + Position position = entry.getKey(); + Piece piece = entry.getValue(); + pieceDtos.add(new PieceDto(position.getRow(), position.getCol(), piece.getTeamName(), piece.getTypeName())); + } + return pieceDtos; + } + + public static Board toBoard(List pieceDtos) { + Map boardMap = new HashMap<>(); + for (PieceDto dto : pieceDtos) { + Position position = Position.of(dto.row(), dto.col()); + Piece piece = Piece.of(Team.fromName(dto.team()), Type.fromName(dto.type())); + boardMap.put(position, piece); + } + return Board.of(boardMap); + } +} \ No newline at end of file diff --git a/src/test/java/dao/BoardDaoTest.java b/src/test/java/dao/BoardDaoTest.java index 279f930355..ca8d85e42a 100644 --- a/src/test/java/dao/BoardDaoTest.java +++ b/src/test/java/dao/BoardDaoTest.java @@ -4,14 +4,8 @@ import dao.mongodb.BoardDao; import dao.mongodb.MongoConnection; -import domain.Board; -import domain.BoardFactory; -import domain.Piece; -import domain.Team; -import domain.Type; -import domain.vo.Position; -import java.util.HashMap; -import java.util.Map; +import dto.PieceDto; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -29,10 +23,13 @@ void setUp() { @DisplayName("보드를 저장하고 gameId를 반환한다") void 보드를_저장하고_gameId를_반환한다() { // given - Board board = BoardFactory.setUp(); + List pieces = List.of( + new PieceDto(0, 0, "초", "차"), + new PieceDto(9, 8, "한", "궁") + ); // when - String gameId = boardDao.save(board, 0); + String gameId = boardDao.save(pieces, 0); // then assertThat(gameId).isNotNull(); @@ -42,41 +39,46 @@ void setUp() { @DisplayName("저장한 보드를 gameId로 조회할 수 있다") void 저장한_보드를_gameId로_조회할_수_있다() { // given - Board board = BoardFactory.setUp(); - String gameId = boardDao.save(board, 0); + List pieces = List.of( + new PieceDto(0, 0, "초", "차"), + new PieceDto(9, 8, "한", "궁") + ); + String gameId = boardDao.save(pieces, 0); // when - Board foundBoard = boardDao.findBoardByGameId(gameId); + List foundPieces = boardDao.findPiecesByGameId(gameId); // then - assertThat(foundBoard.getBoard()).hasSize(board.getBoard().size()); + assertThat(foundPieces).hasSize(2); } @Test @DisplayName("저장한 보드의 기물 정보가 일치한다") void 저장한_보드의_기물_정보가_일치한다() { // given - Map boardMap = new HashMap<>(); - boardMap.put(Position.of(0, 0), Piece.of(Team.CHU, Type.CHARIOT)); - boardMap.put(Position.of(9, 8), Piece.of(Team.HAN, Type.GENERAL)); - Board board = Board.of(boardMap); - String gameId = boardDao.save(board, 0); + List pieces = List.of( + new PieceDto(0, 0, "초", "차"), + new PieceDto(9, 8, "한", "궁") + ); + String gameId = boardDao.save(pieces, 0); // when - Board foundBoard = boardDao.findBoardByGameId(gameId); + List foundPieces = boardDao.findPiecesByGameId(gameId); // then - Piece piece = foundBoard.findPieceByPosition(Position.of(0, 0)).get(); - assertThat(piece.getTeamName()).isEqualTo("초"); - assertThat(piece.getTypeName()).isEqualTo("차"); + PieceDto chariot = foundPieces.stream() + .filter(p -> p.row() == 0 && p.col() == 0) + .findFirst().get(); + assertThat(chariot.team()).isEqualTo("초"); + assertThat(chariot.type()).isEqualTo("차"); } @Test @DisplayName("턴 카운트를 저장하고 조회할 수 있다") void 턴_카운트를_저장하고_조회할_수_있다() { // given - Board board = BoardFactory.setUp(); - String gameId = boardDao.save(board, 3); + List pieces = List.of(new PieceDto(0, 0, "초", "차")); + String gameId = boardDao.save(pieces, 3); // when int turnCount = boardDao.findTurnCountByGameId(gameId); @@ -89,18 +91,18 @@ void setUp() { @DisplayName("보드를 업데이트하면 변경된 내용이 반영된다") void 보드를_업데이트하면_변경된_내용이_반영된다() { // given - Board board = BoardFactory.setUp(); - String gameId = boardDao.save(board, 0); - Map updatedMap = new HashMap<>(); - updatedMap.put(Position.of(5, 5), Piece.of(Team.HAN, Type.SOLDIER)); + List pieces = List.of(new PieceDto(0, 0, "초", "차")); + String gameId = boardDao.save(pieces, 0); + + List updatedPieces = List.of(new PieceDto(5, 5, "한", "졸")); // when - boardDao.update(gameId, updatedMap, 1); + boardDao.update(gameId, updatedPieces, 1); // then - Board foundBoard = boardDao.findBoardByGameId(gameId); - assertThat(foundBoard.getBoard()).hasSize(1); + List foundPieces = boardDao.findPiecesByGameId(gameId); + assertThat(foundPieces).hasSize(1); int turnCount = boardDao.findTurnCountByGameId(gameId); assertThat(turnCount).isEqualTo(1); } -} +} \ No newline at end of file From 22ad3463d859974967be0716e7521acf59043999 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Mon, 13 Apr 2026 20:58:27 +0900 Subject: [PATCH 86/87] =?UTF-8?q?refactor:=20=EA=B6=81=EC=84=B1=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=EC=A0=84=EB=9E=B5=20=ED=8C=A8=ED=84=B4=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Piece.java | 15 +++- .../domain/strategy/CannonMoveStrategy.java | 24 +----- .../domain/strategy/ChariotMoveStrategy.java | 37 +------- .../domain/strategy/GeneralMoveStrategy.java | 42 ++-------- .../domain/strategy/GuardMoveStrategy.java | 41 +-------- src/main/java/domain/strategy/Palace.java | 62 ++++++++++++++ .../domain/strategy/PalaceMoveStrategy.java | 45 ++++++++++ .../domain/strategy/SoldierMoveStrategy.java | 84 +------------------ .../strategy/CannonMoveStrategyTest.java | 3 +- 9 files changed, 138 insertions(+), 215 deletions(-) create mode 100644 src/main/java/domain/strategy/Palace.java create mode 100644 src/main/java/domain/strategy/PalaceMoveStrategy.java diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java index f8c349f60f..b663f31c0e 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/Piece.java @@ -1,6 +1,8 @@ package domain; import domain.strategy.MoveStrategy; +import domain.strategy.Palace; +import domain.strategy.PalaceMoveStrategy; import domain.vo.Position; import java.util.List; @@ -25,12 +27,12 @@ public boolean isAnotherTeam(final Piece anotherPiece) { } public List getPathPositions(final Position from, final Position to) { - MoveStrategy strategy = type.getStrategy(); + MoveStrategy strategy = resolveStrategy(from, to); return strategy.getPath(from, to); } public boolean canMovePiece(final Position from, final Position to, final Map piecesOnPath) { - MoveStrategy strategy = type.getStrategy(); + MoveStrategy strategy = resolveStrategy(from, to); return strategy.canMove(this, from, to, piecesOnPath); } @@ -49,4 +51,13 @@ public Team getTeam() { public String getTeamName() { return team.getName(); } + + private MoveStrategy resolveStrategy(final Position from, final Position to) { + MoveStrategy base = type.getStrategy(); + if (Palace.isInPalace(from) || Palace.isInPalace(to)) { + return new PalaceMoveStrategy(base); + } + + return base; + } } diff --git a/src/main/java/domain/strategy/CannonMoveStrategy.java b/src/main/java/domain/strategy/CannonMoveStrategy.java index 2cc8a75719..485b49c0cb 100644 --- a/src/main/java/domain/strategy/CannonMoveStrategy.java +++ b/src/main/java/domain/strategy/CannonMoveStrategy.java @@ -62,29 +62,9 @@ public boolean canMove(final Piece mover, final Position from, final Position to } private boolean isNotCorrectPath(final Position from, final Position to) { - if (isInPalaceAndCanDiagonalMove(from)) { - if (isDiagonal(from, to)) { - if (Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) <= 4) { - return false; - } - } - } - - return from.getRow() != to.getRow() && from.getCol() != to.getCol(); - } - - private boolean isInPalaceAndCanDiagonalMove(final Position position) { - int row = position.getRow(); - int column = position.getCol(); - if ((row == 0 && column == 4) || (row == 2 && column == 4) || (row == 1 && column == 3) || (row == 1 && column == 5) - || (row == 7 && column == 4) || (row == 9 && column == 4) || (row == 8 && column == 3) || (row == 8 && column == 5)) { + if (Palace.canDiagonalInPalace(from, to)) { return false; } - - return true; - } - - private boolean isDiagonal(final Position from, final Position to) { - return Math.abs(from.getRow() - to.getRow()) >= 1 && Math.abs(from.getCol() - to.getCol()) >= 1; + return from.getCol() != to.getCol() && from.getRow() != to.getRow(); } } \ No newline at end of file diff --git a/src/main/java/domain/strategy/ChariotMoveStrategy.java b/src/main/java/domain/strategy/ChariotMoveStrategy.java index 066c714e41..05fb1f9704 100644 --- a/src/main/java/domain/strategy/ChariotMoveStrategy.java +++ b/src/main/java/domain/strategy/ChariotMoveStrategy.java @@ -50,42 +50,9 @@ public boolean canMove(final Piece mover, final Position from, final Position to } private boolean isNotCorrectPath(final Position from, final Position to) { - if (!palaceInRange(from)) { - if (isDiagonal(from, to)) { - return true; - } - } - - if (isInPalaceAndCanDiagonalMove(from)) { - if (isDiagonal(from, to)) { - if (Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) <= 4) { - return false; - } - } - } - - return from.getCol() != to.getCol() && from.getRow() != to.getRow(); - } - - private boolean isInPalaceAndCanDiagonalMove(final Position position) { - int row = position.getRow(); - int column = position.getCol(); - - if ((row == 0 && column == 4) || (row == 2 && column == 4) || (row == 1 && column == 3) || (row == 1 && column == 5) - || (row == 7 && column == 4) || (row == 9 && column == 4) || (row == 8 && column == 3) || (row == 8 && column == 5)) { + if (Palace.canDiagonalInPalace(from, to)) { return false; } - - return true; - } - - private boolean isDiagonal(final Position from, final Position to) { - return Math.abs(from.getRow() - to.getRow()) >= 1 && Math.abs(from.getCol() - to.getCol()) >= 1; - } - - private boolean palaceInRange(final Position position) { - return (((0 <= position.getRow() && position.getRow() <= 2) || (7 <= position.getRow() - && position.getRow() <= 9)) - && (3 <= position.getCol() && position.getCol() <= 5)); + return from.getCol() != to.getCol() && from.getRow() != to.getRow(); } } \ No newline at end of file diff --git a/src/main/java/domain/strategy/GeneralMoveStrategy.java b/src/main/java/domain/strategy/GeneralMoveStrategy.java index 15c7d5c9e8..77b6be9b3b 100644 --- a/src/main/java/domain/strategy/GeneralMoveStrategy.java +++ b/src/main/java/domain/strategy/GeneralMoveStrategy.java @@ -34,20 +34,12 @@ private boolean isNotCorrectPath(final Position from, final Position to) { if (!palaceInRange(to)) { return true; } - - if (from.getRow() == to.getRow() && Math.abs(from.getCol() - to.getCol()) != 1) { - return true; - } - - if (from.getCol() == to.getCol() && Math.abs(from.getRow() - to.getRow()) != 1) { - return true; - } - - if (hanGeneralCanDiagonalMoveInPalace(from, to) || chuGeneralCanDiagonalMoveInPalace(from, to)) { - return true; + if (Palace.canDiagonalInPalace(from, to) + && Math.abs(from.getRow() - to.getRow()) == 1 + && Math.abs(from.getCol() - to.getCol()) == 1) { + return false; } - - return false; + return Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) != 1; } private boolean palaceInRange(final Position position) { @@ -55,28 +47,4 @@ private boolean palaceInRange(final Position position) { && position.getRow() <= 9)) && (3 <= position.getCol() && position.getCol() <= 5)); } - - private boolean chuGeneralCanDiagonalMoveInPalace(Position from, Position to) { - if ((from.getRow() == 7 && from.getCol() == 4) || (from.getRow() == 8 && from.getCol() == 3) - || (from.getRow() == 8 && from.getCol() == 5 || (from.getRow() == 0 && from.getCol() == 4))) { - if (isDiagonal(from, to)) { - return true; - } - } - return false; - } - - private boolean hanGeneralCanDiagonalMoveInPalace(Position from, Position to) { - if ((from.getRow() == 2 && from.getCol() == 4) || (from.getRow() == 1 && from.getCol() == 3) - || (from.getRow() == 1 && from.getCol() == 5) || (from.getRow() == 9 && from.getCol() == 4)) { - if (isDiagonal(from, to)) { - return true; - } - } - return false; - } - - private boolean isDiagonal(final Position from, final Position to) { - return Math.abs(from.getRow() - to.getRow()) == 1 && Math.abs(from.getCol() - to.getCol()) == 1; - } } \ No newline at end of file diff --git a/src/main/java/domain/strategy/GuardMoveStrategy.java b/src/main/java/domain/strategy/GuardMoveStrategy.java index 31ebcdd391..5984a2b332 100644 --- a/src/main/java/domain/strategy/GuardMoveStrategy.java +++ b/src/main/java/domain/strategy/GuardMoveStrategy.java @@ -22,10 +22,6 @@ public boolean canMove(final Piece mover, final Position from, final Position to return false; } - if (!palaceInRange(to)) { - return false; - } - Piece target = piecesOnPath.get(to); if (target == null) { return true; @@ -35,40 +31,11 @@ public boolean canMove(final Piece mover, final Position from, final Position to } private boolean isNotCorrectPath(final Position from, final Position to) { - if (hanSoldierCanDiagonalMoveInPalace(from, to) || chuSoldierCanDiagonalMoveInPalace(from, to)) { - return true; + if (Palace.canDiagonalInPalace(from, to) + && Math.abs(from.getRow() - to.getRow()) == 1 + && Math.abs(from.getCol() - to.getCol()) == 1) { + return false; } - return Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) != 1; } - - private boolean chuSoldierCanDiagonalMoveInPalace(Position from, Position to) { - if ((from.getRow() == 7 && from.getCol() == 4) || (from.getRow() == 8 && from.getCol() == 3) - || (from.getRow() == 8 && from.getCol() == 5)) { - if (isDiagonal(from, to)) { - return true; - } - } - return false; - } - - private boolean hanSoldierCanDiagonalMoveInPalace(Position from, Position to) { - if ((from.getRow() == 2 && from.getCol() == 4) || (from.getRow() == 1 && from.getCol() == 3) - || (from.getRow() == 1 && from.getCol() == 5)) { - if (isDiagonal(from, to)) { - return true; - } - } - return false; - } - - private boolean isDiagonal(final Position from, final Position to) { - return Math.abs(from.getRow() - to.getRow()) == 1 && Math.abs(from.getCol() - to.getCol()) == 1; - } - - private boolean palaceInRange(final Position position) { - return (((0 <= position.getRow() && position.getRow() <= 2) || (7 <= position.getRow() - && position.getRow() <= 9)) - && (3 <= position.getCol() && position.getCol() <= 5)); - } } \ No newline at end of file diff --git a/src/main/java/domain/strategy/Palace.java b/src/main/java/domain/strategy/Palace.java new file mode 100644 index 0000000000..a4b7ebb80b --- /dev/null +++ b/src/main/java/domain/strategy/Palace.java @@ -0,0 +1,62 @@ +package domain.strategy; + +import domain.vo.Position; + +public class Palace { + + private static final int[][] DIAGONAL_CENTERS = {{1, 4}, {8, 4}}; + private static final int[][][] DIAGONAL_CORNERS = { + {{0, 3}, {0, 5}, {2, 3}, {2, 5}}, + {{7, 3}, {7, 5}, {9, 3}, {9, 5}} + }; + + public static boolean isInPalace(Position pos) { + int r = pos.getRow(), c = pos.getCol(); + return (3 <= c && c <= 5) && + ((0 <= r && r <= 2) || (7 <= r && r <= 9)); + } + + public static boolean canDiagonalInPalace(Position from, Position to) { + if (!isInPalace(from) || !isInPalace(to)) { + return false; + } + int rowDiff = Math.abs(from.getRow() - to.getRow()); + int colDiff = Math.abs(from.getCol() - to.getCol()); + if (rowDiff < 1 || colDiff < 1) { + return false; + } + + if (isCenter(from)) { + return true; + } + + if (isCorner(from) && isCenter(to)) { + return true; + } + + if (isCorner(from) && isCorner(to) && isSamePalace(from, to)) { + return true; + } + return false; + } + + private static boolean isSamePalace(Position a, Position b) { + return (a.getRow() <= 2 && b.getRow() <= 2) || (a.getRow() >= 7 && b.getRow() >= 7); + } + + private static boolean isCenter(Position pos) { + for (int[] c : DIAGONAL_CENTERS) { + if (pos.getRow() == c[0] && pos.getCol() == c[1]) return true; + } + return false; + } + + private static boolean isCorner(Position pos) { + for (int[][] group : DIAGONAL_CORNERS) { + for (int[] c : group) { + if (pos.getRow() == c[0] && pos.getCol() == c[1]) return true; + } + } + return false; + } +} diff --git a/src/main/java/domain/strategy/PalaceMoveStrategy.java b/src/main/java/domain/strategy/PalaceMoveStrategy.java new file mode 100644 index 0000000000..03ffd82180 --- /dev/null +++ b/src/main/java/domain/strategy/PalaceMoveStrategy.java @@ -0,0 +1,45 @@ +package domain.strategy; + +import domain.Piece; +import domain.vo.Position; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class PalaceMoveStrategy implements MoveStrategy { + + private final MoveStrategy base; + + public PalaceMoveStrategy(MoveStrategy base) { + this.base = base; + } + + @Override + public List getPath(Position from, Position to) { + if (Palace.canDiagonalInPalace(from, to)) { + return buildDiagonalPath(from, to); + } + return base.getPath(from, to); + } + + @Override + public boolean canMove(Piece mover, Position from, Position to, + Map piecesOnPath) { + return base.canMove(mover, from, to, piecesOnPath); + } + + private List buildDiagonalPath(Position from, Position to) { + List path = new ArrayList<>(); + int dr = Integer.compare(to.getRow(), from.getRow()); + int dc = Integer.compare(to.getCol(), from.getCol()); + int r = from.getRow() + dr; + int c = from.getCol() + dc; + while (r != to.getRow() || c != to.getCol()) { + path.add(Position.of(r, c)); + r += dr; + c += dc; + } + path.add(to); + return path; + } +} diff --git a/src/main/java/domain/strategy/SoldierMoveStrategy.java b/src/main/java/domain/strategy/SoldierMoveStrategy.java index 912a677e63..a857f306af 100644 --- a/src/main/java/domain/strategy/SoldierMoveStrategy.java +++ b/src/main/java/domain/strategy/SoldierMoveStrategy.java @@ -17,67 +17,21 @@ public List getPath(final Position from, final Position to) { return List.of(to); } - @Override public boolean canMove(final Piece mover, final Position from, final Position to, final Map piecesOnPath) { if (isNotCorrectPath(from, to)) { return false; } - - if ((!isInPalace(from) || !isInPalace(to))) { - if (isDiagonal(from, to)) { - return false; - } - } - - if (isInPalace(from) && isInPalace(to)) { - if (isDiagonal(from, to)) { - return canDiagonalInPalace(from, to); - } - } - - if (isInPalace(from) && !isInPalace(to)) { - if (isDiagonal(from, to)) { - return false; - } - } - if (isWithdraw(from, to, mover)) { return false; } - Piece target = piecesOnPath.get(to); if (target == null) { return true; } - - if (hanSoldierCanDiagonalMoveInPalace(from, to) || chuSoldierCanDiagonalMoveInPalace(from, to)) { - return false; - } - return mover.isAnotherTeam(target); } - private boolean chuSoldierCanDiagonalMoveInPalace(Position from, Position to) { - if ((from.getRow() == 7 && from.getCol() == 4) || (from.getRow() == 8 && from.getCol() == 3) - || (from.getRow() == 8 && from.getCol() == 5)) { - if (isDiagonal(from, to)) { - return true; - } - } - return false; - } - - private boolean hanSoldierCanDiagonalMoveInPalace(Position from, Position to) { - if ((from.getRow() == 2 && from.getCol() == 4) || (from.getRow() == 1 && from.getCol() == 3) - || (from.getRow() == 1 && from.getCol() == 5)) { - if (isDiagonal(from, to)) { - return true; - } - } - return false; - } - private boolean isWithdraw(final Position from, final Position to, final Piece mover) { Team team = mover.getTeam(); if (team == Team.CHU && from.getRow() - to.getRow() == 1) { @@ -92,41 +46,11 @@ private boolean isWithdraw(final Position from, final Position to, final Piece m } private boolean isNotCorrectPath(final Position from, final Position to) { - if (Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) > 2) { - return true; - } - - if ((from.getRow() == to.getRow()) && Math.abs(from.getCol() - to.getCol()) != 1) { - return true; - } - - if ((from.getCol() == to.getCol()) && Math.abs(from.getRow() - to.getRow()) != 1) { - return true; - } - - return false; - } - - private boolean isInPalace(final Position position) { - int row = position.getRow(); - int column = position.getCol(); - - return (column >= 3 && column <= 5) && ((row >= 0 && row <= 2) || (row >= 7 && row <= 9)); - } - - private boolean canDiagonalInPalace(final Position from, final Position to) { - if (!isDiagonal(from, to) || !isInPalace(from) || !isInPalace(to)) { + if (Palace.canDiagonalInPalace(from, to) + && Math.abs(from.getRow() - to.getRow()) == 1 + && Math.abs(from.getCol() - to.getCol()) == 1) { return false; } - - return isCenterOfPalace(from) || isCenterOfPalace(to); - } - - private boolean isDiagonal(final Position from, final Position to) { - return Math.abs(from.getRow() - to.getRow()) == 1 && Math.abs(from.getCol() - to.getCol()) == 1; - } - - private boolean isCenterOfPalace(final Position position) { - return position.getCol() == 4 && (position.getRow() == 1 || position.getRow() == 8); + return Math.abs(from.getRow() - to.getRow()) + Math.abs(from.getCol() - to.getCol()) != 1; } } \ No newline at end of file diff --git a/src/test/java/domain/strategy/CannonMoveStrategyTest.java b/src/test/java/domain/strategy/CannonMoveStrategyTest.java index b05ad9149e..51863ddaaa 100644 --- a/src/test/java/domain/strategy/CannonMoveStrategyTest.java +++ b/src/test/java/domain/strategy/CannonMoveStrategyTest.java @@ -129,11 +129,10 @@ class CannonMoveStrategyTest { Position from = Position.of(7, 3); Position to = Position.of(9, 5); - MoveStrategy strategy = new CannonMoveStrategy(); Piece mover = Piece.of(Team.CHU, Type.CANNON); Piece general = Piece.of(Team.CHU, Type.GENERAL); // when // then - Assertions.assertTrue(strategy.canMove(mover, from, to, Map.of(Position.of(8, 4), general))); + Assertions.assertTrue(mover.canMovePiece(from, to, Map.of(Position.of(8, 4), general))); } } From ed1155c950281f84603762193e690faa92c35771 Mon Sep 17 00:00:00 2001 From: LeeJaeHyeok97 Date: Mon, 13 Apr 2026 21:54:36 +0900 Subject: [PATCH 87/87] =?UTF-8?q?feat:=20=ED=95=9C=EB=82=98=EB=9D=BC?= =?UTF-8?q?=EC=9D=98=20=EC=83=81=EC=B0=A8=EB=A6=BC=20=EB=B0=B0=EC=B9=98=20?= =?UTF-8?q?=EB=B0=A9=EC=8B=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/BoardFactory.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/domain/BoardFactory.java b/src/main/java/domain/BoardFactory.java index 7cf0f64c2a..ef99bd9873 100644 --- a/src/main/java/domain/BoardFactory.java +++ b/src/main/java/domain/BoardFactory.java @@ -29,10 +29,10 @@ public static Board setUpLeftElephantFormation(Map initialBoard board.put(Position.of(0, 7), Piece.of(Team.CHU, Type.HORSE)); } if (team == Team.HAN) { - board.put(Position.of(9, 2), Piece.of(Team.HAN, Type.ELEPHANT)); - board.put(Position.of(9, 7), Piece.of(Team.HAN, Type.ELEPHANT)); - board.put(Position.of(9, 1), Piece.of(Team.HAN, Type.HORSE)); - board.put(Position.of(9, 6), Piece.of(Team.HAN, Type.HORSE)); + board.put(Position.of(9, 1), Piece.of(Team.HAN, Type.ELEPHANT)); + board.put(Position.of(9, 6), Piece.of(Team.HAN, Type.ELEPHANT)); + board.put(Position.of(9, 2), Piece.of(Team.HAN, Type.HORSE)); + board.put(Position.of(9, 7), Piece.of(Team.HAN, Type.HORSE)); } return Board.of(board); @@ -48,10 +48,10 @@ public static Board setUpRightElephantFormation(Map initialBoar board.put(Position.of(0, 6), Piece.of(Team.CHU, Type.HORSE)); } if (team == Team.HAN) { - board.put(Position.of(9, 1), Piece.of(Team.HAN, Type.ELEPHANT)); - board.put(Position.of(9, 6), Piece.of(Team.HAN, Type.ELEPHANT)); - board.put(Position.of(9, 2), Piece.of(Team.HAN, Type.HORSE)); - board.put(Position.of(9, 7), Piece.of(Team.HAN, Type.HORSE)); + board.put(Position.of(9, 2), Piece.of(Team.HAN, Type.ELEPHANT)); + board.put(Position.of(9, 7), Piece.of(Team.HAN, Type.ELEPHANT)); + board.put(Position.of(9, 1), Piece.of(Team.HAN, Type.HORSE)); + board.put(Position.of(9, 6), Piece.of(Team.HAN, Type.HORSE)); } return Board.of(board);