Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
ff69636
feat: Palace ๋„๋ฉ”์ธ ๊ฐ์ฒด ์ถ”๊ฐ€ (๊ถ์„ฑ ๋ฒ”์œ„ ๋ฐ ๋Œ€๊ฐ์„  ๊ทœ์น™)
e9ua1 Apr 7, 2026
c6e261c
feat: General/Guard ๊ถ์„ฑ ์ด๋™ ๊ทœ์น™ ์ ์šฉ
e9ua1 Apr 7, 2026
7db48d4
feat: Chariot/Cannon ๊ถ์„ฑ ๋Œ€๊ฐ์„  ์ด๋™ ์ ์šฉ
e9ua1 Apr 7, 2026
ce3a036
feat: Soldier ๊ถ์„ฑ ๋‚ด ์ „์ง„ ๋Œ€๊ฐ์„  ์ด๋™ ์ ์šฉ
e9ua1 Apr 7, 2026
7e8ae2c
refactor: Palace ๋„ค์ด๋ฐ ๊ฐœ์„  ๋ฐ General/Guard ์ค‘๋ณต ๋กœ์ง ์ œ๊ฑฐ
e9ua1 Apr 7, 2026
1acb581
feat: Score ๊ฐ’ ๊ฐ์ฒด ์ถ”๊ฐ€
e9ua1 Apr 7, 2026
eb26f67
feat: Board ์ ์ˆ˜ ๊ณ„์‚ฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
e9ua1 Apr 7, 2026
f833fa8
feat: ๊ฒŒ์ž„ ์ข…๋ฃŒ ์‹œ ์ ์ˆ˜ ์ถœ๋ ฅ ๋ฐ ์ŠนํŒจ ํŒ์ • ๊ธฐ๋Šฅ ์ถ”๊ฐ€
e9ua1 Apr 7, 2026
b64d64d
docs: ๊ถ์„ฑ ๊ทœ์น™ ๋ฐ ์ ์ˆ˜ ๊ณ„์‚ฐ ๊ธฐ๋Šฅ ๋ชฉ๋ก ์ถ”๊ฐ€
e9ua1 Apr 7, 2026
51c39fe
feat: DB ์—ฐ๊ฒฐ ์„ค์ • ์ถ”๊ฐ€
e9ua1 Apr 8, 2026
0825773
feat: GameRepository ์ธํ„ฐํŽ˜์ด์Šค ์ถ”๊ฐ€
e9ua1 Apr 8, 2026
7d3a996
feat: PieceFactory ์ถ”๊ฐ€ (DB โ†” ๋„๋ฉ”์ธ ๋ณ€ํ™˜)
e9ua1 Apr 8, 2026
cb98270
feat: GameRepositoryImpl ์ถ”๊ฐ€ (JDBC ๊ตฌํ˜„์ฒด)
e9ua1 Apr 8, 2026
2ae2c2b
feat: FakeGameRepository ์ถ”๊ฐ€ ๋ฐ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ
e9ua1 Apr 8, 2026
eead766
feat: JanggiGame์— Repository ์ฃผ์ž… ๋ฐ ๊ฒŒ์ž„ ์ด์–ดํ•˜๊ธฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
e9ua1 Apr 8, 2026
f65fca7
build: MySQL ์ปค๋„ฅํ„ฐ ์˜์กด์„ฑ ์ถ”๊ฐ€
e9ua1 Apr 8, 2026
2b129e5
build: application ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ฐ mainClass ์„ค์ • ์ถ”๊ฐ€
e9ua1 Apr 8, 2026
e5b05ff
docs: ์‹คํ–‰ ๋ฐฉ๋ฒ• ์ถ”๊ฐ€ ๋ฐ DB ๋น„๋ฐ€๋ฒˆํ˜ธ ์ œ๊ฑฐ
e9ua1 Apr 8, 2026
8a3e097
refactor: JanggiApplication main ๋ฉ”์„œ๋“œ ๋‹จ์ˆœํ™”
e9ua1 Apr 8, 2026
395cefe
refactor: DBConnector ์˜ˆ์™ธ๋ฅผ IllegalStateException์œผ๋กœ ๋ณ€๊ฒฝ
e9ua1 Apr 8, 2026
799a406
refactor: toTeamString() ์ฑ…์ž„์„ PieceFactory๋กœ ์ด๋™ ๋ฐ RuntimeException โ†’ Ilโ€ฆ
e9ua1 Apr 8, 2026
09c9b3a
refactor: save/update ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ ์ถ”๊ฐ€
e9ua1 Apr 8, 2026
e91cdf6
refactor: GameState์— PLAYING ์ดˆ๊ธฐ ์ƒํƒœ ์ถ”๊ฐ€๋กœ while ๋ฃจํ”„ ์ดˆ๊ธฐ๊ฐ’ ๋ช…ํ™•ํ™”
e9ua1 Apr 8, 2026
2ec7161
refactor: Board ์ƒ์„ฑ์ž๋ฅผ private์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ์ •์  ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ from() ์ถ”๊ฐ€
e9ua1 Apr 8, 2026
12945d7
refactor: findBoardById()์— ๊ฒŒ์ž„ ์กด์žฌ ์—ฌ๋ถ€ ์‚ฌ์ „ ๊ฒ€์ฆ ์ถ”๊ฐ€
e9ua1 Apr 8, 2026
ca17737
refactor: BoardFactory ์ด์ค‘ for๋ฌธ์„ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ณ€๊ฒฝ (depth ๊ทœ์น™ ์ค€์ˆ˜)
e9ua1 Apr 8, 2026
a32a6cb
refactor: movePiece()์—์„œ ์ž…๋ ฅ ํŒŒ์‹ฑ ๋กœ์ง์„ parsePositions()๋กœ ๋ถ„๋ฆฌ
e9ua1 Apr 8, 2026
43c9d67
refactor: Board ์ž…๋ ฅ ๊ฒ€์ฆ ์ˆœ์„œ ๋ณ€๊ฒฝ (๋นˆ์นธ โ†’ ๊ฐ™์€ ์ขŒํ‘œ โ†’ ํ„ด)
e9ua1 Apr 8, 2026
6ef0cf7
refactor: Path โ†’ PiecesOnPath๋กœ rename (๊ฒฝ๋กœ ์œ„ ๊ธฐ๋ฌผ ์ƒํƒœ ์˜๋„ ๋ช…ํ™•ํ™”)
e9ua1 Apr 10, 2026
2fa1c0e
refactor: ์ ์ˆ˜ ๊ณ„์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ScoreResult๋กœ ์‘์ง‘ํ™”
e9ua1 Apr 10, 2026
7d37b7c
fix: ๋ฆฌ๋ฒ ์ด์Šค ์ถฉ๋Œ ํ•ด๊ฒฐ ๋ฐ PiecesOnPath ์ ์šฉ ๋ณต๊ตฌ
e9ua1 Apr 10, 2026
02fb6b4
refactor: hasDistancePair โ†’ matchesDistance๋กœ ๋ฉ”์„œ๋“œ๋ช… ๊ฐœ์„ 
e9ua1 Apr 10, 2026
71c53a6
refactor: Palace ๋‚ด๋ถ€ ์›์‹œ๊ฐ’์„ Position์œผ๋กœ ํ‘œํ˜„ํ•˜๊ณ  of(Team) ์ถ”๊ฐ€
e9ua1 Apr 10, 2026
00e6f32
refactor: FakeGameRepository๋ฅผ test ํŒจํ‚ค์ง€๋กœ ์ด๋™
e9ua1 Apr 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 83 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,58 @@

---

## ์‹คํ–‰ ๋ฐฉ๋ฒ•

### DB ์„ค์ •

1. MySQL ์„ค์น˜ ํ›„ ์ ‘์†
```bash
mysql -u root -p
```

2. ์•„๋ž˜ SQL ์‹คํ–‰:
```sql
CREATE DATABASE janggi;
USE janggi;

CREATE TABLE janggi_game (
id BIGINT NOT NULL AUTO_INCREMENT,
turn VARCHAR(8) NOT NULL,
PRIMARY KEY (id)
);

CREATE TABLE piece (
id BIGINT NOT NULL AUTO_INCREMENT,
janggi_game_id BIGINT NOT NULL,
row_pos INT NOT NULL,
col_pos INT NOT NULL,
team VARCHAR(8) NOT NULL,
type VARCHAR(16) NOT NULL,
PRIMARY KEY (id)
);
```

3. `src/main/java/janggi/infrastructure/DBConnector.java`์˜ `USER`, `PASSWORD`๋ฅผ ๋ณธ์ธ ํ™˜๊ฒฝ์— ๋งž๊ฒŒ ์ˆ˜์ •

```java
private static final String URL = "jdbc:mysql://localhost:3306/janggi";
private static final String USER = "root"; // ๋ณธ์ธ MySQL ์‚ฌ์šฉ์ž๋ช…
private static final String PASSWORD = ""; // ๋ณธ์ธ MySQL ๋น„๋ฐ€๋ฒˆํ˜ธ
```

### ๊ฒŒ์ž„ ์‹คํ–‰

IntelliJ์—์„œ `JanggiApplication.java`์˜ `main` ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

### ๊ฒŒ์ž„ ๋ฐฉ๋ฒ•

- ์ƒˆ ๊ฒŒ์ž„: `1` ์ž…๋ ฅ โ†’ ์ฐจ๋ฆผ ์„ ํƒ โ†’ ๊ฒŒ์ž„ ์‹œ์ž‘
- ์ด์–ดํ•˜๊ธฐ: `2` ์ž…๋ ฅ โ†’ ๊ฒŒ์ž„ ๋ฒˆํ˜ธ ์ž…๋ ฅ โ†’ ๊ฒŒ์ž„ ์žฌ๊ฐœ
- ์ด๋™: `์ถœ๋ฐœ์ขŒํ‘œ ๋„์ฐฉ์ขŒํ‘œ` ํ˜•์‹์œผ๋กœ ์ž…๋ ฅ (์˜ˆ: `11 21`)
- ์ข…๋ฃŒ: `end` ์ž…๋ ฅ

---

## ๊ตฌํ˜„ํ•  ๊ธฐ๋Šฅ ๋ชฉ๋ก

### ์—ด ์ขŒํ‘œ (Column)
Expand Down Expand Up @@ -44,25 +96,29 @@
5. ๊ฒ€์ฆ ํ†ต๊ณผ ์‹œ ๋ณด๋“œ ์œ„ ๊ธฐ๋ฌผ์˜ ์‹ค์ œ ์ด๋™ ์‹คํ–‰

### ์žฅ(General) / ์‚ฌ(Guard)
- [X] ๊ถ์„ฑ ๋‚ด์—์„œ ์ง€์ •๋œ ์„ ์„ ๋”ฐ๋ผ ์ง์„  1์นธ ์ด๋™ ์‹œ ์˜ฌ๋ฐ”๋ฅธ ๊ฒฝ๋กœ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
- [X] ๊ถ์„ฑ ๋‚ด ์ง€์ •๋œ ์„ ์ด ์•„๋‹Œ ๋Œ€๊ฐ์„ ์œผ๋กœ ์ด๋™ํ•˜๋ ค ํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] 1์นธ์„ ์ดˆ๊ณผํ•˜์—ฌ ์ด๋™ํ•˜๋ ค ํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] ๊ถ์„ฑ ๋‚ด์—์„œ ์ง์„ ์œผ๋กœ 1์นธ ์ด๋™ ์‹œ ์˜ฌ๋ฐ”๋ฅธ ๊ฒฝ๋กœ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
- [X] ๊ถ์„ฑ ๋‚ด ๋Œ€๊ฐ์„  ์„ ์„ ๋”ฐ๋ผ 1์นธ ์ด๋™ ์‹œ ์˜ฌ๋ฐ”๋ฅธ ๊ฒฝ๋กœ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
- [X] ๊ถ์„ฑ ๋ฐ–์œผ๋กœ ์ด๋™ํ•˜๋ ค ํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] ๋Œ€๊ฐ์„  ์„  ์œ„๊ฐ€ ์•„๋‹Œ ๊ณณ์œผ๋กœ ๋Œ€๊ฐ์„  ์ด๋™ํ•˜๋ ค ํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] ๋„์ฐฉํ•  ์œ„์น˜์— ์•„๊ตฐ ๊ธฐ๋ฌผ์ด ์žˆ์œผ๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] ๋„์ฐฉํ•  ์œ„์น˜์— ์ ๊ตฐ ๊ธฐ๋ฌผ์ด ์žˆ์œผ๋ฉด ์ •์ƒ์ ์œผ๋กœ ์ด๋™(๊ณต๊ฒฉ) ๊ฐ€๋Šฅํ•˜๋‹ค.

### ์ฐจ (Chariot)
- [X] ์ƒํ•˜์ขŒ์šฐ ์ง์„  ๋ฐฉํ–ฅ์œผ๋กœ ์ด๋™ ์‹œ ์ถœ๋ฐœ์ง€๋ถ€ํ„ฐ ๋„์ฐฉ์ง€๊นŒ์ง€์˜ ๊ฒฝ๋กœ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
- [X] ๊ถ์„ฑ ๋Œ€๊ฐ์„  ์„ ์„ ๋”ฐ๋ผ 1์นธ ์ด๋™ ์‹œ ๋นˆ ๊ฒฝ๋กœ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
- [X] ๊ถ์„ฑ ๋Œ€๊ฐ์„  ์„ ์„ ๋”ฐ๋ผ 2์นธ ์ด๋™ ์‹œ ์ค‘์‹ฌ ์œ„์น˜๋ฅผ ๊ฒฝ๋กœ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
- [X] ํ•œ ๋ฒˆ์— ์—ฌ๋Ÿฌ ๋ฐฉํ–ฅ(๋Œ€๊ฐ์„ , ๊บพ์ž„ ๋“ฑ)์œผ๋กœ ์ด๋™ํ•˜๋ ค ํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] ์ด๋™ํ•˜๋Š” ๋„์ค‘์˜ ๊ฒฝ๋กœ(List) ์•ˆ์— ๋นˆ์นธ(EmptyPiece)์ด ์•„๋‹Œ ๋‹ค๋ฅธ ๊ธฐ๋ฌผ์ด ์กด์žฌํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] ์ด๋™ํ•˜๋Š” ๋„์ค‘์˜ ๊ฒฝ๋กœ์— ๋นˆ์นธ์ด ์•„๋‹Œ ๊ธฐ๋ฌผ์ด ์กด์žฌํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] ๋„์ฐฉํ•  ์œ„์น˜์— ์•„๊ตฐ ๊ธฐ๋ฌผ์ด ์žˆ์œผ๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

### ํฌ (Cannon)
- [X] ์ƒํ•˜์ขŒ์šฐ ์ง์„  ๋ฐฉํ–ฅ์ด ์•„๋‹Œ ๋ฐฉํ–ฅ์œผ๋กœ ์ด๋™ํ•˜๋ ค ํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] ์ด๋™ํ•˜๋Š” ๋„์ค‘์˜ ๊ฒฝ๋กœ์— ๋›ฐ์–ด๋„˜์„ ๊ธฐ๋ฌผ์ด ์—†๊ฑฐ๋‚˜(0๊ฐœ) 2๊ฐœ ์ด์ƒ ์กด์žฌํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. (๋ฐ˜๋“œ์‹œ 1๊ฐœ๋งŒ ๋„˜์–ด์•ผ ํ•จ)
- [X] ๊ถ์„ฑ ๋Œ€๊ฐ์„  2์นธ ์ด๋™ ์‹œ ์ค‘์‹ฌ ์œ„์น˜๋ฅผ ๊ฒฝ๋กœ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
- [X] ๊ถ์„ฑ ๋Œ€๊ฐ์„  1์นธ ์ด๋™์€ ๋„˜์„ ๊ธฐ๋ฌผ์ด ์—†์–ด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] ์ด๋™ํ•˜๋Š” ๋„์ค‘์˜ ๊ฒฝ๋กœ์— ๋›ฐ์–ด๋„˜์„ ๊ธฐ๋ฌผ์ด ์—†๊ฑฐ๋‚˜(0๊ฐœ) 2๊ฐœ ์ด์ƒ ์กด์žฌํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] ๋›ฐ์–ด๋„˜์–ด์•ผ ํ•˜๋Š” ๊ธฐ๋ฌผ์ด ๊ฐ™์€ 'ํฌ'์ผ ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] ๋„์ฐฉํ•  ์œ„์น˜์— ์•„๊ตฐ ๊ธฐ๋ฌผ์ด ์žˆ์œผ๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] ๋„์ฐฉํ•  ์œ„์น˜(์žก์œผ๋ ค๋Š” ๋Œ€์ƒ)๊ฐ€ ์ƒ๋Œ€๋ฐฉ์˜ 'ํฌ'์ผ ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] ์œ„์˜ ๋ชจ๋“  ์ œ์•ฝ ์กฐ๊ฑด์„ ์ง€ํ‚ค๋ฉฐ ํ•œ ๋ฐฉํ–ฅ ์ง์„ ์œผ๋กœ ์ด๋™ ์‹œ ์ •์ƒ์ ์œผ๋กœ ๊ฒฝ๋กœ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

### ๋งˆ (Horse)
- [X] ์ง์„  ๋ฐฉํ–ฅ์œผ๋กœ 1์นธ, ์ด์–ด์„œ ๋Œ€๊ฐ์„  ๋ฐฉํ–ฅ์œผ๋กœ 1์นธ ์ด๋™ ์‹œ (๋งˆ๋ฐญ ์ด๋™) ์˜ฌ๋ฐ”๋ฅธ ๊ฒฝ๋กœ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
Expand All @@ -81,6 +137,8 @@

### ์กธ/๋ณ‘ (Soldier)
- [X] ์ „์ง„ ๋˜๋Š” ์ขŒ์šฐ๋กœ ์ง์„  1์นธ ์ด๋™ ์‹œ ์ •์ƒ์ ์ธ ๊ฒฝ๋กœ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
- [X] ๊ถ์„ฑ ๋‚ด ๋Œ€๊ฐ์„  ์„  ์œ„์—์„œ ์ „์ง„ ๋ฐฉํ–ฅ ๋Œ€๊ฐ์„  1์นธ ์ด๋™ ์‹œ ์ •์ƒ์ ์ธ ๊ฒฝ๋กœ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
- [X] ๊ถ์„ฑ ๋‚ด์—์„œ ํ›„์ง„ ๋Œ€๊ฐ์„ ์œผ๋กœ ์ด๋™ํ•˜๋ ค ํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] ๋Œ€๊ฐ์„ ์œผ๋กœ ์ด๋™ํ•˜๋ ค ํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] ์ž์‹ ์˜ ์ง„์˜ ๊ธฐ์ค€์œผ๋กœ ๋’ค๋กœ ํ›„ํ‡ดํ•˜๋ ค ํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
- [X] ํ•œ ๋ฒˆ์— 1์นธ์„ ์ดˆ๊ณผํ•˜์—ฌ ์ด๋™ํ•˜๋ ค ํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
Expand All @@ -94,6 +152,25 @@
- [X] ๋ชจ๋“  ๊ฒ€์ฆ์„ ํ†ต๊ณผํ•˜๊ณ  ์ด๋™์ด ์™„๋ฃŒ๋˜๋ฉด, ๊ธฐ์กด ์ถœ๋ฐœ ์ขŒํ‘œ์˜ ์œ„์น˜๋Š” ๋นˆ์นธ(EmptyPiece) ์ƒํƒœ๊ฐ€ ๋œ๋‹ค.
- [X] ๊ธฐ์กด ์ถœ๋ฐœ ์ขŒํ‘œ์— ์žˆ๋˜ ๊ธฐ๋ฌผ ๊ฐ์ฒด๋Š” ๋„์ฐฉ ์ขŒํ‘œ์˜ ์œ„์น˜๋กœ ๊ฐฑ์‹ ๋œ๋‹ค.

### ๊ถ์„ฑ (Palace)
- [X] ๊ถ์„ฑ ๋ฒ”์œ„ ๋‚ด ์œ„์น˜๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํŒ๋ณ„ํ•œ๋‹ค.
- [X] ๊ถ์„ฑ ๋Œ€๊ฐ์„  ์„  ์œ„์˜ ์œ„์น˜(๊ผญ์ง“์ , ์ค‘์‹ฌ)๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํŒ๋ณ„ํ•œ๋‹ค.
- [X] ๋Œ€๊ฐ์„  ์„  ์œ„ 1์นธ/2์นธ ์ด๋™ ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํŒ๋ณ„ํ•œ๋‹ค.
- [X] 2์นธ ๋Œ€๊ฐ์„  ์ด๋™ ์‹œ ์ค‘์‹ฌ ์œ„์น˜๋ฅผ ๊ฒฝ๋กœ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
- [X] 1์นธ ๋Œ€๊ฐ์„  ์ด๋™ ์‹œ ๋นˆ ๊ฒฝ๋กœ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

### ์ ์ˆ˜ (Score)
- [X] ๊ธฐ๋ฌผ๋ณ„ ์ ์ˆ˜๋ฅผ ํ•ฉ์‚ฐํ•˜์—ฌ ํŒ€์˜ ์ ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค.
- [X] ํ•œ๋‚˜๋ผ ์ ์ˆ˜์—๋Š” ๋ค(1.5์ )์ด ์ ์šฉ๋œ๋‹ค.
- [X] ์ดˆ๋‚˜๋ผ ์ ์ˆ˜์—๋Š” ๋ค์ด ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค.
- [X] ์ ์ˆ˜๊ฐ€ ๋” ๋†’์€ ํŒ€์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํŒ๋ณ„ํ•œ๋‹ค.

### ๊ฒŒ์ž„ ์ข…๋ฃŒ (์ŠนํŒจ ํŒ์ •)
- [X] ์žฅ์ด ์žกํžˆ๋ฉด ์ฆ‰์‹œ ๊ฒŒ์ž„์„ ์ข…๋ฃŒํ•˜๊ณ  ์žก์€ ํŒ€์„ ์Šน๋ฆฌ์ž๋กœ ์ถœ๋ ฅํ•œ๋‹ค.
- [X] ์žฅ์ด ์žกํžˆ๋ฉด ์ตœ์ข… ์ ์ˆ˜๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
- [X] end ์ž…๋ ฅ ์‹œ ํ˜„์žฌ ์ ์ˆ˜๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ์ ์ˆ˜ ์šฐ์„ธ ํŒ€์„ ์ถœ๋ ฅํ•œ๋‹ค.
- [X] ์ ์ˆ˜๊ฐ€ ๋™์ผํ•˜๋ฉด ๋ฌด์Šน๋ถ€๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

---

## ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์š”๊ตฌ์‚ฌํ•ญ
Expand Down
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
plugins {
id 'java'
id 'application'
}

version '1.0-SNAPSHOT'
Expand All @@ -13,6 +14,11 @@ dependencies {
testImplementation platform('org.assertj:assertj-bom:3.27.3')
testImplementation('org.junit.jupiter:junit-jupiter')
testImplementation('org.assertj:assertj-core')
implementation 'mysql:mysql-connector-java:8.0.33'
}

application {
mainClass = 'janggi.JanggiApplication'
}

java {
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/janggi/JanggiApplication.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package janggi;

import janggi.domain.GameRepository;
import janggi.infrastructure.GameRepositoryImpl;

public class JanggiApplication {

public static void main(String[] args) {
JanggiGame.initialize().start();
GameRepository gameRepository = new GameRepositoryImpl();
JanggiGame.from(gameRepository).start();
}
}
63 changes: 55 additions & 8 deletions src/main/java/janggi/JanggiGame.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package janggi;

import janggi.domain.GameRepository;
import janggi.domain.GameState;
import janggi.domain.ScoreResult;
import janggi.domain.Team;
import janggi.domain.board.Board;
import janggi.domain.board.BoardFactory;
Expand All @@ -17,15 +19,37 @@ public class JanggiGame {
private static final int POSITION_INPUT_SIZE = 2;

private final Board board;
private final GameRepository gameRepository;
private final long gameId;

private JanggiGame(Board board) {
private JanggiGame(Board board, GameRepository gameRepository, long gameId) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JanggiGame์€ ์•„์ดํ๊ฐ€ ์ƒ๊ฐํ–ˆ์„๋•Œ ๋„๋ฉ”์ธ์ธ๊ฐ€์š”? ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ณ„์ธต์ธ๊ฐ€์š”?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JanggiGame์€ ์•„์ดํ๊ฐ€ ์ƒ๊ฐํ–ˆ์„๋•Œ ๋„๋ฉ”์ธ์ธ๊ฐ€์š”? ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ณ„์ธต์ธ๊ฐ€์š”?

JanggiGame์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ณ„์ธต์œผ๋กœ ๋ณด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
๊ฒŒ์ž„์˜ ํ๋ฆ„ ์ œ์–ด(play, progressTurn)์™€ ์ž…์ถœ๋ ฅ(InputView, OutputView) ์‚ฌ์ด๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ์—ญํ• ์„ ํ•˜๊ณ  ์žˆ์–ด,
์ˆœ์ˆ˜ํ•œ ๋„๋ฉ”์ธ ๋กœ์ง๋ณด๋‹ค๋Š” ์œ ์Šค์ผ€์ด์Šค๋ฅผ ์กฐ์œจํ•˜๋Š” ์ฑ…์ž„์— ๊ฐ€๊น๋‹ค๊ณ  ํŒ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.
๋‹ค๋งŒ Board, GameRepository ๊ฐ™์€ ๋„๋ฉ”์ธ ๊ฐ์ฒด์— ์ง์ ‘ ์˜์กดํ•˜๊ณ  ์žˆ์–ด ๊ฒฝ๊ณ„๊ฐ€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์€ ๋ถ€๋ถ„์ด ์žˆ๋Š”๋ฐ,
์ด ๋ถ€๋ถ„์— ๋Œ€ํ•ด ์–ด๋–ป๊ฒŒ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„์ง€ ์˜๊ฒฌ์„ ๋“ฃ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ง€๊ธˆ์€ JanggiGame์€ InputView, OutputView, GameRepository๊นŒ์ง€ ํ•จ๊ป˜ ์•Œ๊ณ  ์žˆ์–ด์„œ ์ˆœ์ˆ˜ํ•œ ๋„๋ฉ”์ธ ๊ฐ์ฒด๋ผ๊ณ  ๋ณด๊ธฐ๋Š” ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ง€๊ธˆ ๊ตฌ์กฐ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐ์ฒด๋ผ๊ณ  ์ •๋ฆฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๊ณ  ํฌ๊ฒŒ ์ด๊ฒฌ์€ ์—†์Šต๋‹ˆ๋‹ค~

๋‹ค๋งŒ ๊ฐœ์ธ์ ์œผ๋กœ๋Š” ๊ฒŒ์ž„ ์ž์ฒด๋Š” ๋„๋ฉ”์ธ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ด์š”. ํ„ด์ด ์–ด๋–ป๊ฒŒ ์ง„ํ–‰๋˜๋Š”์ง€, ์–ธ์ œ ๊ฒŒ์ž„์ด ์ข…๋ฃŒ๋˜๋Š”์ง€, ์ด๋™์ด ์„ฑ๊ณตํ–ˆ์„ ๋•Œ ์ƒํƒœ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋ฐ”๋€Œ๋Š”์ง€ ๊ฐ™์€ ํ๋ฆ„ ์ž์ฒด๊ฐ€ ์žฅ๊ธฐ ๊ทœ์น™์˜ ์ผ๋ถ€๋‹ˆ๊นŒ์š”. ๋‹จ์ˆœํžˆ ํ™”๋ฉด๊ณผ ์ €์žฅ์†Œ๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ์ ˆ์ฐจ๋ผ๊ธฐ๋ณด๋‹ค ๊ฒŒ์ž„์ด๋ผ๋Š” ๋„๋ฉ”์ธ์ด ์Šค์Šค๋กœ ์„ค๋ช…ํ•ด์•ผ ํ•˜๋Š” ์ƒํƒœ ๋ณ€ํ™”์— ๋” ๊ฐ€๊น์ง€ ์•Š๋‚˜์š”?

์˜ˆ๋ฅผ ๋“ค์–ด ์ดํ›„ ์›น ๋ฒ„์ „๊นŒ์ง€ ํ•จ๊ป˜ ๊ณ ๋ คํ•œ๋‹ค๊ณ  ํ–ˆ์„ ๋•Œ, ์ž…๋ ฅ์„ ์–ด๋–ป๊ฒŒ ๋ฐ›๊ณ  ๊ฒฐ๊ณผ๋ฅผ ์–ด๋–ป๊ฒŒ ๋ณด์—ฌ์ค„์ง€๋Š” ๋ถ„๋ช… ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ณ„์ธต์ด ๋ฐ”๋€Œ๋Š” ๋ฌธ์ œ์ธ๋ฐ, ๊ฒŒ์ž„์˜ ํ๋ฆ„ ์ž์ฒด๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€๋˜์–ด์•ผ ํ•˜์ž–์•„์š”. ๊ทธ๋Ÿฐ๋ฐ ์ง€๊ธˆ ๊ตฌ์กฐ๋Š” ๊ทธ ํ๋ฆ„๊นŒ์ง€ InputView, OutputView, Repository์™€ ํ•œ ๊ฐ์ฒด ์•ˆ์— ๋ฌถ์—ฌ ์žˆ์–ด์„œ, ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋ฐ”๋€Œ๋ฉด ๊ฒฐ๊ตญ ์ƒˆ๋กœ์šด ๊ฒŒ์ž„ ํ๋ฆ„ ๊ฐ์ฒด๋ฅผ ๋‹ค์‹œ ๋งŒ๋“ค๊ฒŒ ๋  ๊ฐ€๋Šฅ์„ฑ์ด ์ปค ๋ณด์—ฌ์š”. ๊ทธ๋ž˜์„œ ์ œ ๊ธฐ์ค€์—์„œ๋Š” ์ฝ˜์†”์ด๋“  ์›น์ด๋“  ์ƒ๊ด€์—†์ด ๊ณตํ†ต์œผ๋กœ ์œ ์ง€๋˜์–ด์•ผ ํ•˜๋Š” ํ„ด ์ง„ํ–‰, ์ข…๋ฃŒ ํŒ๋‹จ, ์ƒํƒœ ๋ณ€ํ™” ๊ฐ™์€ ๊ฒŒ์ž„ ๊ทœ์น™์€ ๋„๋ฉ”์ธ์— ๋‚จ๊ณ , ์ž…์ถœ๋ ฅ๊ณผ ์ €์žฅ/๋ณต๊ตฌ orchestration๋งŒ ๋ฐ”๊นฅ ๊ณ„์ธต์ด ๋งก์•„์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

this.board = board;
this.gameRepository = gameRepository;
this.gameId = gameId;
}

public static JanggiGame initialize() {
public static JanggiGame from(GameRepository gameRepository) {
String mode = InputView.readGameMode();
if (mode.equals("1")) {
return initialize(gameRepository);
}
return load(gameRepository);
}

private static JanggiGame initialize(GameRepository gameRepository) {
String hanSetup = InputView.readHanSetup();
String choSetup = InputView.readChoSetup();
return new JanggiGame(BoardFactory.create(hanSetup, choSetup));
Board board = BoardFactory.create(hanSetup, choSetup);
long gameId = gameRepository.save(board, Team.CHO);
OutputView.printGameId(gameId);
return new JanggiGame(board, gameRepository, gameId);
}

private static JanggiGame load(GameRepository gameRepository) {
long gameId = InputView.readGameId();
Board board = gameRepository.findBoardById(gameId)
.orElseThrow(() -> new IllegalArgumentException("[ERROR] ๊ฒŒ์ž„์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: " + gameId));
return new JanggiGame(board, gameRepository, gameId);
}

public void start() {
Expand All @@ -34,19 +58,21 @@ public void start() {
}

private void play() {
Team currentTeam = Team.CHO;
GameState state = GameState.TURN_SUCCESS;
Team currentTeam = gameRepository.findTurnById(gameId);
GameState state = GameState.PLAYING;
while (state.isPlaying()) {
String input = InputView.readPosition(currentTeam.getDisplayName());
state = progressTurn(input, currentTeam);
if (state.isTurnSuccess()) {
currentTeam = currentTeam.convert();
gameRepository.update(gameId, board, currentTeam);
}
}
}

private GameState progressTurn(String input, Team currentTeam) {
if (input.equals(END_COMMAND)) {
printScoreResult();
OutputView.printGameEnd();
return GameState.FINISHED;
}
Expand All @@ -58,6 +84,7 @@ private GameState processTurn(String input, Team currentTeam) {
Map<Position, Piece> updatedBoard = movePiece(input, currentTeam);
if (board.isGeneralCaptured()) {
OutputView.printBoard(updatedBoard);
printScoreResult();
OutputView.printWinner(currentTeam);
return GameState.FINISHED;
}
Expand All @@ -69,12 +96,32 @@ private GameState processTurn(String input, Team currentTeam) {
}
}

private void printScoreResult() {
ScoreResult result = board.calculateScoreResult();
OutputView.printScore(result.hanScore(), result.choScore());
if (result.isHanWin()) {
OutputView.printScoreWinner(Team.HAN);
return;
}
if (result.isChoWin()) {
OutputView.printScoreWinner(Team.CHO);
return;
}
OutputView.printDraw();
}

private Map<Position, Piece> movePiece(String input, Team currentTeam) {
List<String> positions = parsePositions(input);
return board.move(
Position.from(positions.getFirst()),
Position.from(positions.getLast()),
currentTeam);
}

private List<String> parsePositions(String input) {
List<String> positions = List.of(input.split(" "));
validateInputSize(positions);
Position from = Position.from(positions.getFirst());
Position to = Position.from(positions.getLast());
return board.move(from, to, currentTeam);
return positions;
}

private void validateInputSize(List<String> positions) {
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/janggi/domain/GameRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package janggi.domain;

import janggi.domain.board.Board;
import java.util.Optional;

public interface GameRepository {
long save(Board board, Team currentTeam);
void update(long gameId, Board board, Team currentTeam);
Optional<Board> findBoardById(long gameId);
Team findTurnById(long gameId);
}
1 change: 1 addition & 0 deletions src/main/java/janggi/domain/GameState.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package janggi.domain;

public enum GameState {
PLAYING,
TURN_SUCCESS,
TURN_FAILED,
FINISHED,
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/janggi/domain/Score.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package janggi.domain;

public class Score {

private static final double HAN_BONUS = 1.5;

private final double value;

private Score(double value) {
this.value = value;
}

public static Score of(double value) {
return new Score(value);
}

public Score applyHanBonus() {
return new Score(value + HAN_BONUS);
}

public boolean isHigherThan(Score other) {
return this.value > other.value;
}

public double getValue() {
return value;
}
}
32 changes: 32 additions & 0 deletions src/main/java/janggi/domain/ScoreResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package janggi.domain;

public class ScoreResult {

private final Score hanScore;
private final Score choScore;

public ScoreResult(Score hanScore, Score choScore) {
this.hanScore = hanScore;
this.choScore = choScore;
}

public Score hanScore() {
return hanScore;
}

public Score choScore() {
return choScore;
}

public boolean isHanWin() {
return hanScore.isHigherThan(choScore);
}

public boolean isChoWin() {
return choScore.isHigherThan(hanScore);
}

public boolean isDraw() {
return !isHanWin() && !isChoWin();
}
}
Loading