Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ea8a875
refactor: Game๊ฐ์ฒด null์— ๋Œ€ํ•œ ๋ฐฉ์–ด์  ์ฝ”๋“œ ๋ณ€๊ฒฝ(์ƒ์„ฑ์ž๋กœ ๋ณ€๊ฒฝ ๋ฐ ์ฃผ์ž…)
armd482 Mar 31, 2026
0392115
refactor: ๋ฏธ์‚ฌ์šฉ ์ƒ์ˆ˜ ์ œ๊ฑฐ
armd482 Mar 31, 2026
bce6ed8
rename: Turn ์ถ”์ƒ ํด๋ž˜์Šค ๋ฐ ์ž์‹ turn ํด๋ž˜๋ช… ๋ณ€๊ฒฝ
armd482 Mar 31, 2026
bc7846a
refactor: PieceManifest ์ด๋ฆ„ ๋ณ€๊ฒฝ
armd482 Mar 31, 2026
0bc4f56
feat: dx,dy์— ๋Œ€ํ•œ ์ •์  ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„
armd482 Apr 1, 2026
20564a3
refactor: Linear Piece ๊ฒฝ๋กœ ๊ณ„์‚ฐ ๋ฐฉ์‹ Movement๋กœ ๋ณ€๊ฒฝ
armd482 Apr 1, 2026
0314ed8
refactor: ๊ณตํ†ต ๋กœ์ง ์ƒ์œ„ ๋‹จ์œผ๋กœ ์ด๋™
armd482 Apr 1, 2026
89b3f7a
feat: ๊ถ์„ฑ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
armd482 Apr 1, 2026
5bebc61
feat: ์ ์ˆ˜ ๊ณ„์‚ฐ ๋กœ์ง ์ถ”๊ฐ€
armd482 Apr 1, 2026
8e63e17
test: board, materialScore ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
armd482 Apr 1, 2026
23514d6
feat: ์ข…๋ฃŒ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
armd482 Apr 1, 2026
200784c
docs: readme ์—…๋ฐ์ดํŠธ
armd482 Apr 1, 2026
b99a5f2
feat: ์ ์ˆ˜ ๋†’์€ ์ง„์˜์— ๋Œ€ํ•œ ์Šน๋ฆฌ ์ถœ๋ ฅ ๊ตฌํ˜„
armd482 Apr 1, 2026
aa8337e
test: ์ง์„  ๋ฐ ๊ถ์„ฑ ๋Œ€๊ฐ์„  ๋Œ€ํ•œ ๋ฐฉํ–ฅ, ๊ธธ์ด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ถ”๊ฐ€
armd482 Apr 1, 2026
b0b67d9
feat: max turn ๊ธฐ๋Šฅ ๊ตฌํ˜„
armd482 Apr 2, 2026
54d5e64
refactor: ์ง์„  ํŒ๋ณ„ Linear๋กœ ์ด๋™
armd482 Apr 2, 2026
e38c5ec
chore: ๋ฏธ์‚ฌ์šฉ import ์ œ๊ฑฐ
armd482 Apr 2, 2026
fc60b03
feat: ๊ฒŒ์ž„ ๋ฐฉ ๊ฐ€์ ธ์˜ค๋Š” dao ๊ตฌํ˜„
armd482 Apr 2, 2026
cb946b8
feat: ๊ฒŒ์ž„ ๋ฐฉ ์ถœ๋ ฅ ๋ฐ ์„ ํƒ ์ž…๋ ฅ ์ถ”๊ฐ€
armd482 Apr 2, 2026
e47ab05
feat: ๊ฒŒ์ž„ ๊ธฐ๋ฌผ ๋ฐ์ดํ„ฐ ์ €์žฅ, ๊ฐ€์ ธ์˜ค๊ธฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„
armd482 Apr 2, 2026
e56bb2e
feat: gameRoom turn, side ์—ฐ๊ฒฐ ๋ฐ move ์‹œ ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ ์ถ”๊ฐ€
armd482 Apr 2, 2026
b8c0b00
feat: main๋ฌธ ๋งˆ์ง€๋ง‰์— connection close ์ถ”๊ฐ€
armd482 Apr 2, 2026
346c19b
fix: ์ง„์˜ ์ €์žฅ ์˜ค๋ฅ˜ ์ˆ˜์ •
armd482 Apr 2, 2026
ef592d6
refactor: ํŠธ๋žœ์žญ์…˜ ๋ถ„๋ฆฌ
armd482 Apr 3, 2026
00ed4b0
refactor: runner ๋ถ„๋ฆฌ ๋ฐ ์ž˜๋ชป ์ž…๋ ฅ ์‹œ ๋ฐ˜๋ณต ์‹คํ–‰ ์ถ”๊ฐ€
armd482 Apr 3, 2026
2ae0b21
refactor: ๋ณด๋“œ ๊ฐ€์ ธ์˜ค๊ธฐ index ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฐฉ์‹ ๋ณ€๊ฒฝ
armd482 Apr 3, 2026
4fdd10b
docs: readme ๊ธฐ๋Šฅ ์—…๋ฐ์ดํŠธ
armd482 Apr 3, 2026
b42a62c
refactor: ๋นˆ ๊ฐ์ฒด ์ œ์™ธํ•˜๊ณ  ์ „๋‹ฌ
armd482 Apr 3, 2026
95941a1
refactor: ์‹œ์ž‘ ํ„ด 0์œผ๋กœ ๋ณ€๊ฒฝ
armd482 Apr 3, 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
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
- ์‹œ์ž‘ ์‹œ ์ดˆ/ํ•œ ์ง„์˜์˜ ๊ธฐ๋ณธ ๊ธฐ๋ฌผ ๋ฐฐ์น˜์™€ ๋งˆ์ƒ ๋ฐฐ์น˜๋ฅผ ๋ฐ˜์˜ํ•ด ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
- ์žฅ๊ธฐํŒ์€ ํ˜„์žฌ ์œ„์น˜์˜ ๊ธฐ๋ฌผ ์กฐํšŒ, ๋นˆ ์นธ ์—ฌ๋ถ€, ์•„๊ตฐ/์ ๊ตฐ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•œ๋‹ค.
- ์žฅ๊ธฐํŒ์€ ๊ธฐ๋ฌผ ์ด๋™ ์š”์ฒญ์„ ๋ฐ›์•„ ์‹ค์ œ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•œ๋‹ค.
- ์žฅ๊ธฐํŒ์€ ์ƒ๋Œ€ ๊ธฐ๋ฌผ์„ ์žก์•˜์„ ๋•Œ ํ•ด๋‹น ์ง„์˜์˜ ์ ์ˆ˜๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ฐจ๊ฐํ•œ๋‹ค.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

๊ธฐ๋Šฅ๋ชฉ๋ก ๐Ÿ’ฏ

- ์žฅ๊ธฐํŒ์€ ์–ด๋А ํ•œ ์ง„์˜์˜ ๊ถ์ด ์žกํžˆ๋ฉด ์ฆ‰์‹œ ๊ฒŒ์ž„ ์ข…๋ฃŒ ์ƒํƒœ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค.

### ๊ธฐ๋ฌผ
- ๊ธฐ๋ฌผ์€ ์ข…๋ฅ˜์™€ ์ง„์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ง„๋‹ค.
Expand All @@ -23,20 +25,27 @@
- ์ขŒํ‘œ๋Š” ์ž…๋ ฅ๊ฐ’์„ ๊ฒ€์ฆํ•˜์—ฌ ์ƒ์„ฑํ•œ๋‹ค.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

๊ณ„์ธต๊ณผ ์—ญํ• 

๋‹น์—ฐํžˆ ์–ด๋– ํ•œ ์ •๋‹ต์€ ์žˆ๋Š”๊ฒŒ ์•„๋‹ˆ๊ธฐ์— ์ €์˜ ๊ธฐ์ค€์„ ์–˜๊ธฐํ• ๊ฒŒ์š”. ์ €๋Š” ํ•„์š”์— ์˜ํ•ด ์“ฐ๋Š” ๊ฒƒ ๊ฐ™์•„์š”. ์•„๋ฌด๋ž˜๋„ view์˜ ๋ณ€๊ฒฝ์ด ๋งŽ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— controller์—์„œ view๋กœ ๋„˜์–ด๊ฐˆ ๋•Œ๋Š” DTO๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, DAO์™€ ์„œ๋น„์Šค ์‚ฌ์ด์—๋Š” ์ฃผ๋กœ ์“ฐ์ง€ ์•Š์•„์š”. ์ƒ๊ฐ๋ณด๋‹ค DAO์˜ ๋ณ€๊ฒฝ์€ ์‹ ์ค‘์„ ๊ฐ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋น„์Šค์˜ ๋ณ€๊ฒฝ์œผ๋กœ ์ธํ•ด DAO๊ฐ€ ๋ณ€ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ view-controller์— ๋น„ํ•ด ์ ๊ธฐ ๋•Œ๋ฌธ์ด์—์š”. ๋„˜๊ฒจ์•ผ ๋˜๋Š” ์ธ์ž๊ฐ€ ๋งŽ์œผ๋ฉด ํ•„์š”ํ•˜๋‹ค๊ณ  ๋А๊ปด์„œ ์“ฐ๊ธฐ๋„ ํ•˜๊ณ ์š”.

์ถ”๊ฐ€๋กœ, ๋ ˆ์ด์–ด ๊ฐ„ ์˜์กด ๋ฐฉํ–ฅ์„ ์ง€ํ‚ค๊ธฐ ์œ„ํ•ด DTO๋ฅผ ์“ฐ๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์–ด์š”. ๋„๋ฉ”์ธ ๊ฐ์ฒด๋ฅผ DAO๊นŒ์ง€ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌํ•˜๋ฉด DAO๊ฐ€ ๋„๋ฉ”์ธ ๋ชจ๋ธ ๊ตฌ์กฐ๋ฅผ ์•Œ์•„์•ผ ํ•˜๊ณ , DB ์Šคํ‚ค๋งˆ๊ฐ€ ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ ๋„๋ฉ”์ธ ๊ฐ์ฒด๊นŒ์ง€ ์˜ํ–ฅ์ด ์ „ํŒŒ๋  ์ˆ˜ ์žˆ๊ฑฐ๋“ ์š”. DTO๊ฐ€ ๋‘ ๋ ˆ์ด์–ด ์‚ฌ์ด์˜ ๊ฒฝ๊ณ„๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๋งŒ๋“ค์–ด์„œ ์„œ๋กœ ๋…๋ฆฝ์ ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค„ ์ˆ˜๋„ ์žˆ์–ด์š”.

ํ…Œ์ŠคํŠธ ๋‹จ์œ„

  • ์–ด๋””๊นŒ์ง€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒŒ ๋งž์„ ์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค: ์ž‘์„ฑํ•œ ์ฝ”๋“œ์˜ ๋ชจ๋“  ๋ถ€๋ถ„์„ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์—†๋‚˜์š”? ๋ถˆ๊ฐ€๋Šฅํ•˜๊ฑฐ๋‚˜ ํ•„์š”์—†๋Š” ๋ถ€๋ถ„์ด ์žˆ์„๊นŒ์š”?
  • ์–ด๋А ๋ถ€๋ถ„์„ ํ…Œ์ŠคํŠธ ํ•ด์•ผํ•  ์ง€์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์ด ์žˆ์Šต๋‹ˆ๋‹ค: ์‚ฌ์šฉ์ž์˜ Use case๋ถ€ํ„ฐ ์ ‘๊ทผํ•ด๋ณด๋Š”๊ฑด ์–ด๋–ค๊ฐ€์š”? ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘ ์‹œ, ๊ฒŒ์ž„์„ ์ƒ์„ฑํ•˜๋ฉด ์ €์žฅ์ด ๋˜๋‹ˆ๊นŒ '๊ฒŒ์ž„์ด ์ €์žฅ๋œ๋‹ค'๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด๋ณผ ์ˆ˜ ์žˆ๊ฒ ๋„ค์š”.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

์ „์ฒด์ ์œผ๋กœ ํ…Œ์ŠคํŠธ๊ฐ€ ๋ถ€์กฑํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค! ๋ชจ๋“  ์ผ€์ด์Šค์— ๋Œ€ํ•ด ํ…Œ์ŠคํŠธ๊ฐ€ ์ปค๋ฒ„๋˜์—ˆ๋Š”์ง€ ํ™•์ธ ๋ถ€ํƒ๋“œ๋ฆด๊ฒŒ์š”!

- ์ขŒํ‘œ๋Š” ๋ณด๋“œ ๋ฒ”์œ„(ํ–‰ 1~10, ์—ด 1~9)๋ฅผ ๋ฒ—์–ด๋‚  ์ˆ˜ ์—†๋‹ค.
- ์ขŒํ‘œ๋Š” ์ด๋™๊ฐ’(`Movement`)์„ ์ ์šฉํ•ด ๋‹ค์Œ ์œ„์น˜๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค.
- ์ขŒํ‘œ๋Š” ๋‹ค๋ฅธ ์œ„์น˜์— ๋Œ€ํ•ด์„œ ์„ ํ˜•(์ง์„ , ๋Œ€๊ฐ์„ )์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋‹ค.
- ์ขŒํ‘œ๋Š” ํŠน์ • ์ขŒํ‘œ ๋ฒ”์œ„(ํ•œ: 1~3ํ–‰/4~6์—ด, ์ดˆ: 8~10ํ–‰/4~6์—ด)๋ฅผ '๊ถ์„ฑ'์œผ๋กœ ์ •์˜ํ•œ๋‹ค.

### ์ด๋™ ์ „๋žต
- ๊ฐ ๊ธฐ๋ฌผ์€ ๋ชฉ์ ์ง€๊นŒ์ง€์˜ ๊ฒฝ๋กœ๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค.
- ๊ฒฝ๋กœ ๊ฒ€์ฆ์€ `RoutePolicy`๋ฅผ ํ†ตํ•ด ์ˆ˜ํ–‰ํ•œ๋‹ค.
- ์ผ๋ฐ˜ ๊ธฐ๋ฌผ์€ ๊ฒฝ๋กœ๊ฐ€ ๋น„์–ด ์žˆ๊ณ  ๋„์ฐฉ ์ง€์ ์— ์•„๊ตฐ์ด ์—†์„ ๋•Œ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋‹ค.
- ํฌ๋Š” ์ด๋™ ๊ฒฝ๋กœ ์ค‘ ์ •ํ™•ํžˆ ํ•˜๋‚˜์˜ ๊ธฐ๋ฌผ์„ ๋„˜์–ด์•ผ ํ•˜๋ฉฐ, ํฌ๋ฅผ ๋„˜์„ ์ˆ˜ ์—†๋‹ค.
- ๊ถ์„ฑ ๋‚ด๋ถ€์— ์œ„์น˜ํ•œ ๊ธฐ๋ฌผ(๊ถ, ์‚ฌ, ์ฐจ, ํฌ, ์กธ)์€ ๊ถ์„ฑ ๋ผ์ธ์„ ๋”ฐ๋ฅธ ๋Œ€๊ฐ์„  ์ด๋™์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
- ๋ชฉ์ ์ง€ ์ž์ฒด๊ฐ€ ์ด๋™ ๊ทœ์น™์— ๋งž์ง€ ์•Š์œผ๋ฉด ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

### ๊ฒŒ์ž„ ์ง„ํ–‰
- ๊ฒŒ์ž„์€ ์ดˆ ์ง„์˜๋ถ€ํ„ฐ ์‹œ์ž‘ํ•œ๋‹ค.
- ํ”Œ๋ ˆ์ด์–ด๋Š” ํ„ด๋งˆ๋‹ค ์‹œ์ž‘ ์ขŒํ‘œ์™€ ๋„์ฐฉ ์ขŒํ‘œ๋ฅผ ์ž…๋ ฅํ•œ๋‹ค.
- ์‚ฌ์šฉ์ž๊ฐ€ ์‹œ์ž‘ ์ขŒํ‘œ ์ž…๋ ฅ ์‹œ '์ข…๋ฃŒ'๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๊ฒŒ์ž„ ์ค‘๋‹จ ์—ฌ๋ถ€๋ฅผ ์žฌํ™•์ธํ•œ๋‹ค.
- ์ƒ๋Œ€ํŽธ์ด ๋™์˜(์ข…๋ฃŒ ์ž…๋ ฅ)ํ•˜๋ฉด ๊ฒŒ์ž„์„ ์ฆ‰์‹œ ์ข…๋ฃŒํ•œ๋‹ค.
- ๋™์˜ํ•˜์ง€ ์•Š์œผ๋ฉด(์ข…๋ฃŒ๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ๊ฐ’์„ ์ž…๋ ฅ) ํ˜„์žฌ ํ„ด์„ ์œ ์ง€ํ•˜๋ฉฐ ๋‹ค์‹œ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค.
- ํ˜„์žฌ ํ„ด์˜ ์ง„์˜๋งŒ ์ž์‹ ์˜ ๊ธฐ๋ฌผ์„ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋‹ค.
- ์ด๋™์ด ์™„๋ฃŒ๋˜๋ฉด ํ„ด์ด ์ƒ๋Œ€ ์ง„์˜์œผ๋กœ ๋„˜์–ด๊ฐ„๋‹ค.
- ๊ฒŒ์ž„ ์ƒํƒœ๋Š” `ChoTurn`, `HanTurn`, `Finish`๋กœ ๊ตฌ๋ถ„๋œ๋‹ค.
- 200ํ„ด์ด ๋„˜์–ด๊ฐ€๋ฉด ์ข…๋ฃŒ๋œ๋‹ค.

### ์ดˆ๊ธฐ ๋ฐฐ์น˜
- ์ดˆ์™€ ํ•œ์€ ๊ฐ๊ฐ ๋งˆ์ƒ ๋ฐฐ์น˜๋ฅผ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋‹ค.
Expand All @@ -46,16 +55,27 @@
### ์ž…๋ ฅ
- ํ•œ ์ง„์˜์˜ ๋งˆ์ƒ ๋ฐฐ์น˜๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค.
- ์ดˆ ์ง„์˜์˜ ๋งˆ์ƒ ๋ฐฐ์น˜๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค.
- ์ด๋™ํ•  ๊ธฐ๋ฌผ์˜ ์‹œ์ž‘ ์ขŒํ‘œ๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. (์˜ˆ: `3,4`)
- ์ด๋™ํ•  ๊ธฐ๋ฌผ์˜ ์‹œ์ž‘ ์ขŒํ‘œ ๋˜๋Š” ์ข…๋ฃŒ๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. (์˜ˆ: `3,4` ๋˜๋Š” `์ข…๋ฃŒ` )
- ์ข…๋ฃŒ ์žฌํ™•์ธ ์‹œ ์ข…๋ฃŒ ๋™์˜ ์—ฌ๋ถ€๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. (์˜ˆ: `์ข…๋ฃŒ`)
- ์ด๋™ํ•  ๊ธฐ๋ฌผ์˜ ๋„์ฐฉ ์ขŒํ‘œ๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค. (์˜ˆ: `4,4`)
- ์ž˜๋ชป๋œ ์ž…๋ ฅ์ด ๋“ค์–ด์˜ค๋ฉด ์˜ˆ์™ธ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ๋‹ค์‹œ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค.

### ์ถœ๋ ฅ
- ํ˜„์žฌ ์žฅ๊ธฐํŒ ์ƒํƒœ๋ฅผ ํ–‰/์—ด ์ขŒํ‘œ์™€ ํ•จ๊ป˜ ์ถœ๋ ฅํ•œ๋‹ค.
- ์ดˆ์™€ ํ•œ ๊ธฐ๋ฌผ์€ ANSI ์ƒ‰์ƒ์œผ๋กœ ๊ตฌ๋ถ„ํ•ด ์ถœ๋ ฅํ•œ๋‹ค.
- ํ˜„์žฌ ํ„ด์˜ ์ง„์˜์„ ์ถœ๋ ฅํ•œ๋‹ค.
- ๋งค ํ„ด ์ด๋™์ด ์„ฑ๊ณตํ•˜๋ฉด ํ˜„์žฌ ์–‘ ์ง„์˜์˜ ์ ์ˆ˜ ํ•ฉ๊ณ„๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
- ๊ฒŒ์ž„ ์ข…๋ฃŒ ์‹œ ์ตœ์ข… ์ ์ˆ˜์™€ ํ•จ๊ป˜ ์Šน๋ฆฌํ•œ ์ง„์˜์„ ์ถœ๋ ฅํ•œ๋‹ค.
- ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด `[ERROR]` ํ˜•์‹์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

### ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
- ํ˜„์žฌ DB์— ์ €์žฅ๋œ ์ „์ฒด ์žฅ๊ธฐ ๊ฒŒ์ž„๋ฐฉ ๋ชฉ๋ก์„ ์กฐํšŒํ•œ๋‹ค.
- ์„ ํƒํ•œ ๊ฒŒ์ž„๋ฐฉ์˜ ID๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ด๋‹น ํŒ์˜ ๋ชจ๋“  ๊ธฐ๋ฌผ ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์™€ ๋ณด๋“œ๋ฅผ ๋ณต์›ํ•œ๋‹ค.
- ์ƒˆ๋กœ์šด ๊ฒŒ์ž„ ์‹œ์ž‘ ์‹œ ์ž…๋ ฅ๋ฐ›์€ ๊ฒŒ์ž„๋ฐฉ ์ •๋ณด(์ด๋ฆ„, ์ƒ์„ฑ ์‹œ๊ฐ„ ๋“ฑ)๋ฅผ DB์— ์ €์žฅํ•œ๋‹ค.
- ์ƒˆ๋กœ์šด ๊ฒŒ์ž„์˜ ์ดˆ๊ธฐ ๊ธฐ๋ฌผ ๋ฐฐ์น˜ ์ •๋ณด๋ฅผ DB์— ์ผ๊ด„ ์ €์žฅํ•œ๋‹ค.
- ๊ธฐ๋ฌผ ์ด๋™ ์‹œ, ์ด์ „ ์œ„์น˜์˜ ๊ธฐ๋ฌผ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ญ์ œํ•˜๊ณ  ์ƒˆ๋กœ์šด ์œ„์น˜์˜ ์ •๋ณด๋ฅผ ์—…๋ฐ์ดํŠธํ•˜์—ฌ ์ƒํƒœ๋ฅผ ์˜์†ํ™”ํ•œ๋‹ค.
- ๊ฒŒ์ž„ ์ข…๋ฃŒ ์‹œ(๊ถ์ด ์žกํžˆ๊ฑฐ๋‚˜ ์ค‘๋‹จ ๋™์˜ ์‹œ, ๋˜๋Š” 200ํ„ด์„ ๋„˜๊ธธ ์‹œ) ํ•ด๋‹น ๊ฒŒ์ž„๋ฐฉ๊ณผ ๊ด€๋ จ๋œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ DB์—์„œ ์‚ญ์ œํ•œ๋‹ค.

### ์˜ˆ์™ธ ์ฒ˜๋ฆฌ
- ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋งˆ์ƒ ๋ฐฐ์น˜๋ฅผ ์ž…๋ ฅํ•œ ๊ฒฝ์šฐ
- ์ˆซ์ž๊ฐ€ ์•„๋‹Œ ์ขŒํ‘œ๋ฅผ ์ž…๋ ฅํ•œ ๊ฒฝ์šฐ
Expand All @@ -65,3 +85,4 @@
- ํ˜„์žฌ ํ„ด์˜ ์ง„์˜์ด ์•„๋‹Œ ๊ธฐ๋ฌผ์„ ์›€์ง์ด๋ ค๋Š” ๊ฒฝ์šฐ
- ๊ธฐ๋ฌผ์˜ ์ด๋™ ๊ทœ์น™์— ๋งž์ง€ ์•Š๋Š” ๋ชฉ์ ์ง€๋ฅผ ์ž…๋ ฅํ•œ ๊ฒฝ์šฐ
- ์ด๋™ ๊ฒฝ๋กœ๊ฐ€ ๋ง‰ํ˜€ ์žˆ๊ฑฐ๋‚˜ ๋„์ฐฉ ์ง€์ ์— ์•„๊ตฐ ๊ธฐ๋ฌผ์ด ์žˆ๋Š” ๊ฒฝ์šฐ
- ์ ์ˆ˜ ์ฐจ๊ฐ ์‹œ ์œ ํšจํ•˜์ง€ ์•Š์€ ์ ์ˆ˜๊ฐ’(์Œ์ˆ˜ ๋“ฑ)์ด ๊ณ„์‚ฐ๋˜๋Š” ๊ฒฝ์šฐ
8 changes: 8 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 @@ -9,12 +10,19 @@ repositories {
}

dependencies {
implementation 'org.xerial:sqlite-jdbc:3.46.0.0'
implementation 'org.slf4j:slf4j-simple:2.0.9'

testImplementation platform('org.junit:junit-bom:5.11.4')
testImplementation platform('org.assertj:assertj-bom:3.27.3')
testImplementation('org.junit.jupiter:junit-jupiter')
testImplementation('org.assertj:assertj-core')
}

application {
mainClass = 'janggi.Application'
}

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
Expand Down
Empty file added janggi.db
Empty file.
27 changes: 25 additions & 2 deletions src/main/java/janggi/Application.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,31 @@
package janggi;

import janggi.dao.GameRoom;
import janggi.dao.Piece;
import janggi.db.SQLManager;
import janggi.db.TransactionManager;
import janggi.domain.Game;

public class Application {
public static void main(String[] args) {
Runner runner = new Runner();
runner.run();
SQLManager sqlManager = new SQLManager("jdbc:sqlite:src/main/resources/janggi.db");
TransactionManager transactionManager = new TransactionManager(sqlManager);

GameRoom gameRoom = new GameRoom(sqlManager);
gameRoom.initTable();

Piece piece = new Piece(sqlManager);
piece.initTable();

JanggiService janggiService = new JanggiService(transactionManager, gameRoom, piece);

Game game = new Game();

Runner runner = new Runner(janggiService, game);

int gameId = runner.initBoard();
runner.runJanggi(gameId);

sqlManager.closeConnection();
}
}
59 changes: 59 additions & 0 deletions src/main/java/janggi/JanggiService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package janggi;

import janggi.dao.GameRoom;
import janggi.dao.Piece;
import janggi.db.TransactionManager;
import janggi.domain.Position;
import janggi.domain.Side;
import janggi.domain.piece.PieceType;
import janggi.dto.GameDto;
import janggi.dto.GameResponseDto;
import janggi.dto.PieceDto;
import janggi.dto.TurnDto;
import java.util.List;

public class JanggiService {
private final TransactionManager transactionManager;
private final GameRoom gameRoom;
private final Piece piece;

public JanggiService(TransactionManager transactionManager, GameRoom gameRoom, Piece piece) {
this.transactionManager = transactionManager;
this.gameRoom = gameRoom;
this.piece = piece;
}

public List<GameResponseDto> getEntireGame() {
return gameRoom.findAllGames();
}

public int addGameData(GameDto gameDto, List<PieceDto> pieceDtos) {
return transactionManager.sync((connection) -> {
int gameId = gameRoom.insertGame(connection, gameDto);
piece.updatePieces(connection, gameId, pieceDtos);

return gameId;
});
}

public void removeGame(int id) {
transactionManager.sync((connection) -> {
gameRoom.removeGame(connection, id);
});
}

public List<PieceDto> getPieceInitInfos(int gameId) {
return piece.getAllPieces(gameId);
}


public void movePiece(int gameId, Position start, Position end, Side side, PieceType pieceType, TurnDto turnDto) {
transactionManager.sync(connection -> {
gameRoom.updateGameTurn(connection, gameId, turnDto);
piece.deletePiece(connection, gameId, start.getX(), start.getY());

PieceDto pieceDto = new PieceDto(end.getX(), end.getY(), pieceType.getName(), side.getName());
piece.updatePiece(connection, gameId, pieceDto);
});
}
}
159 changes: 133 additions & 26 deletions src/main/java/janggi/Runner.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,110 @@

import janggi.domain.Arrangement;
import janggi.domain.Game;
import janggi.domain.GameInfo;
import janggi.domain.GameInfos;
import janggi.domain.GameName;
import janggi.domain.MoveResult;
import janggi.domain.PieceInitInfo;
import janggi.domain.Position;
import janggi.domain.Side;
import janggi.domain.SideScore;
import janggi.domain.piece.PieceType;
import janggi.dto.GameDto;
import janggi.dto.PieceDto;
import janggi.dto.TurnDto;
import janggi.view.InputView;
import janggi.view.OutputView;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Runner {
public static final String END_TEXT = "์ข…๋ฃŒ";

private static final String UNEXPECTED_SERVER_ERROR_LOG_MESSAGE = "์˜ˆ์ธกํ•˜์ง€ ๋ชปํ•œ ์‹œ์Šคํ…œ ์˜ค๋ฅ˜ ๋ฐœ์ƒ";
private static final String SYSTEM_ERROR_MESSAGE = "์‹œ์Šคํ…œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ๊ฒŒ์ž„์„ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.";

private static final Logger logger = Logger.getLogger(Runner.class.getName());
private Game game;

public void run() {
initArrangeGame();
turnGame();
private final JanggiService janggiService;
private final Game game;

public Runner(JanggiService janggiService, Game game) {
this.janggiService = janggiService;
this.game = game;
}

public int initBoard() {
Optional<Integer> previousBoard = getPreviousBoard();
return previousBoard.orElseGet(() -> createNewBoard().id());
}

private void initArrangeGame() {
public void runJanggi(int gameId) {
while (playTurnGame(gameId)) {
}
endGame(gameId);
}

private Optional<Integer> getPreviousBoard() {
GameInfos gameInfos = new GameInfos(janggiService.getEntireGame().stream()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

์—ฌ๊ธฐ๋„ ๋น„์Šทํ•˜๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๊ฒ ๋„ค์š”.

.map(gameResponseDto -> new GameInfo(gameResponseDto.id(), gameResponseDto.name(), gameResponseDto.createdAt(), gameResponseDto.updatedAt(), Side.from(gameResponseDto.side()), gameResponseDto.turn()))
.toList());


if(gameInfos.isEmpty()) {
return Optional.empty();
}

GameInfo selectedGame = askUntilValid(() -> getSelectedGame(gameInfos));

List<PieceInitInfo> pieceInitInfos = janggiService.getPieceInitInfos(selectedGame.id()).stream().map(pieceDto -> new PieceInitInfo(new Position(pieceDto.x(), pieceDto.y()), Side.from(pieceDto.side()),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

PieceType.from(pieceDto.pieceType()))).toList();

game.init(pieceInitInfos, selectedGame.side(), selectedGame.turn());
return Optional.of(selectedGame.id());
}

private GameInfo getSelectedGame(GameInfos gameInfos) {
OutputView.printGameRoom(gameInfos.getGameInfos());
Optional<Integer> input = InputView.askLoadGame();

if(input.isEmpty()) {
return createNewBoard();
}
return gameInfos.getGameInfo(input.get());
}

private GameInfo createNewBoard() {
GameName gameName = new GameName(InputView.askGameName());
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formattedNow = LocalDateTime.now().format(formatter);

String hanArrangementInput = InputView.askHanArrangement();
Arrangement hanArrangement = Arrangement.from(hanArrangementInput);

String choArrangementInput = InputView.askChoArrangement();
Arrangement choArrangement = Arrangement.from(choArrangementInput);

game = new Game(choArrangement, hanArrangement);
}
List<PieceDto> pieceDtos = game.init(choArrangement, hanArrangement).stream()
.map(pieceInitInfo -> new PieceDto(pieceInitInfo.position().getX(), pieceInitInfo.position().getY(), pieceInitInfo.pieceType().getName(), pieceInitInfo.side().getName()))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

PieceDto์—์„œ ์ •์  ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™์€๋ฐ, ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์‹œ๋‚˜์š”?

Suggested change
.map(pieceInitInfo -> new PieceDto(pieceInitInfo.position().getX(), pieceInitInfo.position().getY(), pieceInitInfo.pieceType().getName(), pieceInitInfo.side().getName()))
.map(PieceDto::from)

.toList();

private void turnGame() {
while (playTurnGame()) {
}
int id = janggiService.addGameData(new GameDto(gameName.name(), formattedNow, formattedNow, Side.CHO.getName(), 1), pieceDtos);
return new GameInfo(id, gameName.name(), formattedNow, formattedNow, Side.CHO, 1);
}

private boolean playTurnGame() {
private boolean playTurnGame(int gameId) {
try {
printCurrentStatus();
movePiece();
return isFinishedGame();
OutputView.printLine();
OutputView.printBoard(game.getCurrentBoardDto());
OutputView.printTurn(game.getCurrentSide());

return executeTurn(gameId);
} catch (IllegalArgumentException e) {
OutputView.printErrorMessage(e.getMessage());
return true;
Expand All @@ -51,26 +116,68 @@ private boolean playTurnGame() {
}
}

private void printCurrentStatus() {
OutputView.printBoard(game.getCurrentBoardDto());
OutputView.printTurn(game.getCurrentSide());
}
private boolean executeTurn(int gameId) {
Optional<List<Integer>> startPositionInput = InputView.askStartPosition();

private void movePiece() {
List<Integer> startPositionInput = InputView.askStartPosition();
Position startPosition = Position.from(startPositionInput);
if(startPositionInput.isEmpty()) {
return consentEndGame(gameId);
}

Position startPosition = Position.from(startPositionInput.get());

List<Integer> endPositionInput = InputView.askEndPosition();
Position endPosition = Position.from(endPositionInput);

game.move(startPosition, endPosition);
OutputView.printLine();

MoveResult moveResult = game.move(startPosition, endPosition);
TurnDto turnDto = new TurnDto(moveResult.turnAttribute().side().getName(), moveResult.turnAttribute().turn());
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

๋””๋ฏธํ„ฐ ๋ฒ•์น™ ์œ„๋ฐ˜์ด๋„ค์š”. ์–ด๋–ป๊ฒŒ ๊ฐœ์„ ํ•ด๋ณผ ์ˆ˜ ์žˆ์„๊นŒ์š”?

ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์š”๊ตฌ์‚ฌํ•ญ: ํ•œ ์ค„์— ์ ์„ ํ•˜๋‚˜๋งŒ ์ฐ๋Š”๋‹ค.


janggiService.movePiece(gameId, startPosition, endPosition, moveResult.pieceAttribute().side(), moveResult.pieceAttribute().pieceType(), turnDto);

OutputView.printScore(game.getCurrentSideScore());
return !game.isFinished();
}

private boolean isFinishedGame() {
if (game.isFinished()) {
OutputView.printWinner(game.getWinnerSide());
private void endGame(int gameId) {
janggiService.removeGame(gameId);

Side winnerSide = game.getWinnerSide();

if(winnerSide == null) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

  1. null์ด ๋  ์ˆ˜ ์žˆ๋‚˜์š”? Side.Empty๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋‚˜์š”?
  2. null๋กœ ๋‹ค๋ฃจ๋Š”๊ฒŒ ๋งž๋‚˜์š”?
  3. ํ•ด๋‹น ๋กœ์ง์„ game์—์„œ ๋‹ค๋ฃฐ ์ˆ˜ ์—†๋‚˜์š”? (game.hasXXX()?๊ฐ™์€)
  4. ํ•ด๋‹น ๋กœ์ง์€ ํ…Œ์ŠคํŠธ๋กœ ์ปค๋ฒ„ ๋˜์—ˆ๋‚˜์š”?

OutputView.printScore(game.getCurrentSideScore());
printScoreWinner();
return;
}
OutputView.printWinner(winnerSide);
}

private boolean consentEndGame(int gameId) {
String consentInput = InputView.consentEnd();

if(consentInput.equals(END_TEXT)) {
return false;
}
return true;

return executeTurn(gameId);
}

private void printScoreWinner() {
SideScore score = game.getCurrentSideScore();
if(score.cho() > score.han()) {
Comment on lines +166 to +167
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

getter๋กœ ๊บผ๋‚ด์™€์„œ ๋น„๊ตํ•ด์•ผํ•˜๋‚˜์š”?

OutputView.printWinner(Side.CHO);
return;
}
OutputView.printWinner(Side.HAN);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

๋™์  ์ƒํ™ฉ์—์„œ๋„ HAN ์Šน๋ฆฌ๋ฅผ ์ถœ๋ ฅํ•˜๋‚˜์š”?

}

private static <T> T askUntilValid(Supplier<T> supplier) {
while (true) {
try {
return supplier.get();
} catch (Exception e) {
System.out.println(e.getMessage());
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

OutputView๊ฐ€ ์žˆ๋Š”๋ฐ๋„, ์—ฌ๊ธฐ์„œ ์ถœ๋ ฅํ•˜๋Š” ์ด์œ ๊ฐ€ ์žˆ๋‚˜์š”?

}
}
}
}
Loading