-
Notifications
You must be signed in to change notification settings - Fork 206
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
🚀 3단계 - 지뢰 찾기(게임 실행) #408
Open
moto6
wants to merge
100
commits into
next-step:moto6
Choose a base branch
from
moto6:step3
base: moto6
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
🚀 3단계 - 지뢰 찾기(게임 실행) #408
Changes from all commits
Commits
Show all changes
100 commits
Select commit
Hold shift + click to select a range
4bf62bc
refactor : 코틀린 컨벤션 순서 참조
5d66b78
test : 학습테스트를 작성
b76f53d
refactor : 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않기 위해 외곽사이즈의 크기를 포장함
8efa264
refactor : named argment 와 trailling comma 를 사용하도록 수정
8395dd4
refactor : named argment 와 trailling comma 를 사용하도록 수정
130530b
refactor : named argment 와 trailling comma 를 사용하도록 수정
274825e
refactor : 클래스 이름 수정 boardLimit
ac3cf20
refactor : 보드 사이즈를 제한하는 클래스를 사용하도록 수정
f8f60d1
test : 코틀린 컨벤션 순서를 지키고 기억하자는 의미에서 학습테스트를 작성하였다
4fc5844
refactor : BoardLimit 클래스를 사용하도록 리팩토링
b46fc35
refactor : BoardLimit 클래스를 사용하도록 리팩토링
7b0b2c7
refactor : 리미트를 Int형으로 받다가 각자의 타입에 맞는 클래스로 받아들이도록 수정
b2d4c4f
refactor : 보드의 최대크기를 나타내는 Int, Int 에서 이를 래핑하는 클래스를 사용하도록 수정
89a9ad6
refactor : 달라진 아규먼트에 맞게 코드 수정
6760990
style : 스타일 포메팅
f7667f9
test : 테스트 가독성을 위해서 각각의 테스트를 둘로 분할
d075ae1
test : 테스트 클래스 추가
5bdd373
feat : 지뢰찾기를 실행할 어플리케이션 계층을 생성
00fea6f
feat : 지뢰찾기를 실행할때 필요한 입력 출력 메시지 추가
2cb8f2b
feat : 파싱하는 유틸클래스를 분리해냄
59ddf5b
feat : 지뢰찾기를 시도하는 도메인클래스 메시지 추가
e9c3a4a
refactor : 지뢰찾기 문자열 파싱 알고리즘을 추가
783bf43
style : klint 가 피팅 해준 문자열을 수정
44f01b3
refactor : 패키지명 오타 수정
e5dbc0f
feat : 새로 구현해야할 전략클래스 생성
74bcb69
refactor : 클래스 이름 수정Attribute >> TileType
c1bb891
feat : 게임 진행상태에 따라 보이고 안보이고 노출 처리를 변경하는 기능의 클래스 추가
8affdb6
feat : 스트랭글러 전략으로 리팩토링하기 위해서 코드를 남겨둠
331650d
refactor : tile 이 아닌 attribute 클래스에 랜더링 전략을 의존하도록 수정
13d3064
feat : 가려진건지, 보이는지에 대한 속성을 추가하고 생성하는 클래스 설계
22a3129
feat : 불필요한 생성자가 반복되지 않도록 확장함수 추가
de7a90a
refactor : 패키지 수정반영
b5ccebe
refactor : Attribute 에 프라이빗 가시성 변경자 키워드 제거
ddb46b5
refactor : 적절한 용어로 이넘값 수정
7610bb8
refactor : vsion 정보 추가
f14adef
refactor : 불필요한 정보 제거
fc83bc9
refactor : 불필요한 정보 제거
c628184
refactor : 불필요한 클래스 제거
45cee03
refactor : tileType >> Attribute 로 이름 다시 수정
876adad
refactor : 보유 데이터 형식을 Map<> 에서 Set<> 으로 수정
3df712e
refactor : Mine, None 두가지 이넘타입클래스로 수정
3dffbda
refactor : 게임의 상태(진행중인지, 패배한건지, 이긴건지) 출력하는 클래스 달성
68697b8
refactor : points 클래스를 제거하고 board 에 통합
819ea92
refactor : 컬럼 명 수정
2529b4c
refactor : 수직범위, 수평범위를 리턴하는 기능 추가
bb2a3c4
refactor : stateless 한 오브젝트 메서드로 사용할 수 있도록 수정
bf8066b
refactor : 테스트코드에서 사용할 픽스쳐 함수 추가
3e53739
feat : 게임진행에 필요한 메서드인 tryOpen 추가
d59f995
feat : 출력전략 수정
af06755
refactor : 어트리뷰트 명 수정
867d1c5
refactor : 리드미 추가
80144be
refactor : 인접한 칸이 열리도록 수정
da31248
feat : 기능추가
08654b5
feat : mutalble 리스트로 수정
ac4c949
feat : 지뢰찾기의 주변 땅 열림 기능 구현을 위해서 메서드 추가
40200f7
feat : 지뢰찾기의 주변 땅 열림 기능 구현
85dcedd
style : 스타일 맞춤
ae94dd3
refactor : 게임의 화면반응이 한프레임 늦게 반영되는 문제를 해결
94dff79
refactor : 불필요한 로컬변수 생성 제거
b1847fd
refactor : 이넘 이름 변경 NONE -> GROUND
1737685
refactor : 패키지 이동
0e0dcd3
refactor : 패키지 이동
e09a747
refactor : ENUM 클래스 내용 수정
a8673e4
refactor : 읽기전용 프로퍼티로 수정
8dd3116
refactor : 메시지를 사용하도록 수정
59a5102
refactor : 불필요한 변환메서드를 간단하게 수정
6de90e1
refactor : 스타일 맞춤
08db826
refactor : 안정적인 구조로 리팩토링
4579e7b
refactor : 도메인모델에서 뷰 레이어 의존 제거
d21cc09
Update src/main/kotlin/minesweeper/model/board/Board.kt
moto6 bd1199d
refactor : 과도하게 거대한 board 클래스의 역할과 책임을 분리해냄
22d20bc
test : 깨진 테스트코드 수정
348604f
refactor : 읽기 전용 프로퍼티 도입
70e9364
refactor : 메서드명 간결하게
e7cdc9c
docs : 리드미에 실행 로그 첨부
25a1aec
docs : 리드미에 설명 추가
5dcf606
refactor : 탐색엔진을 인터페이스 화
144561b
refactor : 책임과 역할에 따라 위임
c559640
test : 리팩토링으로 인해 깨지는 코드 수정
a743900
refactor : 책임 위임
ce5a3b6
refactor : 불필요한 코드 제거
b169e04
test : 테스트코드 추가
f1ae26e
test : 테스트코드 추가하면서 발견한 버그를 수정함
251b5b3
bugfix : 수동테스트를 진행하며 임시로 수정한 코드를 실수로 커밋해버려 버그가 발생했었다. 해당 부분을 수정
93cbeb2
test : 테스트코드 추가
27a198b
refactor : 불필요한 코드 제거
a4845a6
style : 스타일 맞춤
d274757
test : 지뢰관련 기능 테스트코드 추가
7323a69
test : 보드 범위 관련 테스트코드 추가
d16eeb9
refactor : 읽기 전용 프로퍼티 수정
f2a01fa
refactor : 읽기 전용 프로퍼티 수정
bfab3a5
test : 매설된 지뢰를 여는 작업을 테스트한다
0f9d2ee
test : 잘못된 좌표를 수정한다
bab80d1
refactor : 1 범위 초과하는 부분을 수정한다
a0f77ba
test : 테스트코드 추가
1aa655c
refactor : 불필요한 파일 제거
07f5e7c
test : 테스트코드 설명 수정
046aa43
test : 전략의 클래스 이름을 수정
c317245
test : 전략의 클래스 이름을 수정
0e0704b
test : 테스트 설명 수정
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,18 @@ | ||
package minesweeper | ||
|
||
import minesweeper.app.MineSweeperGame | ||
import minesweeper.model.board.Board | ||
import minesweeper.model.board.toBoardLimit | ||
import minesweeper.view.InputView | ||
import minesweeper.view.OutputView | ||
import minesweeper.view.reder.impl.AdjacentMineCountRenderingStrategy | ||
import minesweeper.view.render.impl.ExploringDefaultClosedAreaRenderingStrategy | ||
|
||
fun main() { | ||
val mapHeight: Int = InputView.mapHeight() | ||
val mapWidth: Int = InputView.mapWidth() | ||
val minesCount: Int = InputView.countOfMines() | ||
val board = Board(minesCount, mapHeight, mapWidth) | ||
val outputView = OutputView(AdjacentMineCountRenderingStrategy(board)) | ||
outputView.printMineMap(board) | ||
val board = Board(minesCount, (mapHeight to mapWidth).toBoardLimit()) | ||
val outputView = OutputView(ExploringDefaultClosedAreaRenderingStrategy) | ||
val game = MineSweeperGame(InputView, outputView) | ||
game.start(board) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package minesweeper.app | ||
|
||
enum class GameStatus { | ||
RUNNING, | ||
LOSE, | ||
WIN, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package minesweeper.app | ||
|
||
import minesweeper.model.board.Board | ||
import minesweeper.view.CoordinateParser | ||
import minesweeper.view.InputView | ||
import minesweeper.view.OutputView | ||
|
||
class MineSweeperGame( | ||
private val inputView: InputView, | ||
private val outputView: OutputView, | ||
) { | ||
fun start(board: Board) { | ||
initialize() | ||
run(board) | ||
finalize() | ||
} | ||
|
||
private fun initialize() { | ||
outputView.gameStart() | ||
} | ||
|
||
private fun run(board: Board) { | ||
do { | ||
val status = board.tryOpen(inputView.openCoordinate(CoordinateParser)) | ||
outputView.printMineMap(board) | ||
} while (GameStatus.RUNNING == status) | ||
} | ||
|
||
private fun finalize() { | ||
outputView.printGameResult() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,51 +1,63 @@ | ||
package minesweeper.model.board | ||
|
||
import minesweeper.model.board.impl.EvenlyStrategy | ||
import minesweeper.app.GameStatus | ||
import minesweeper.model.board.minedeploy.impl.EvenlyStrategy | ||
import minesweeper.model.board.traversal.SearchEngine | ||
import minesweeper.model.board.traversal.impl.SearchBfs | ||
import minesweeper.model.point.Attribute | ||
import minesweeper.model.point.Coordinate | ||
import minesweeper.model.point.Delta | ||
import minesweeper.model.point.Delta.Companion.deltas | ||
import minesweeper.model.point.Points | ||
import minesweeper.model.vison.impl.VisionTotalCoveringStrategy | ||
|
||
class Board( | ||
val points: Points, | ||
val verticalSize: Int, | ||
val horizontalSize: Int, | ||
val mines: Mines, | ||
private val vision: Vision = Vision(emptySet()), | ||
val limit: BoardLimit, | ||
) { | ||
private val isWin: Boolean | ||
get() = mines.count == vision.coveredCount | ||
|
||
val minesCount: Int | ||
get() = mines.count | ||
|
||
constructor( | ||
mineCount: Int, | ||
verticalSize: Int, | ||
horizontalSize: Int, | ||
limit: BoardLimit, | ||
) : this( | ||
points = EvenlyStrategy(mineCount).deployPoints(verticalSize, horizontalSize), | ||
verticalSize = verticalSize, | ||
horizontalSize = horizontalSize | ||
mines = Mines(EvenlyStrategy(mineCount).deployPoints(limit), limit), | ||
vision = Vision(VisionTotalCoveringStrategy.coordinates(limit)), | ||
limit = limit, | ||
) | ||
|
||
fun minesCount(): Int { | ||
return points.countOfMine() | ||
fun isCovered(coordinate: Coordinate): Boolean { | ||
return vision.isCovered(coordinate) | ||
} | ||
|
||
fun tryOpen(coordinate: Coordinate): GameStatus { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Board의 공개된 메서드들의 테스트 코드가 없는 경우가 있는것 같습니다. 테스트 코드를 추가해주시면 좋을것 같습니다. |
||
if (isMineDeployed(coordinate)) { | ||
discoveredAllMines() | ||
return GameStatus.LOSE | ||
} | ||
if (isWin) { | ||
return GameStatus.WIN | ||
} | ||
discoveredAdjacentGround(coordinate) | ||
return GameStatus.RUNNING | ||
} | ||
|
||
fun adjacentMineCount(coordinate: Coordinate): Int { | ||
return this.adjacentPointTraversal(coordinate) | ||
.asSequence() | ||
.map { points.attribute(it) } | ||
.count { it == Attribute.MINE } | ||
private fun discoveredAdjacentGround(coordinate: Coordinate) { | ||
val coordinates: Set<Coordinate> = adjacentGroundCoordinates(coordinate) | ||
vision.exposeAll(coordinates) | ||
} | ||
|
||
private fun adjacentPointTraversal(coordinate: Coordinate): List<Coordinate> { | ||
return deltas.asSequence() | ||
.filter { delta -> inRange(coordinate, delta) } | ||
.map { coordinate.moveTo(it) } | ||
.toList() | ||
private fun adjacentGroundCoordinates(coordinate: Coordinate): Set<Coordinate> { | ||
val searchEngine: SearchEngine = SearchBfs(this.limit, this.mines) | ||
return searchEngine.traversal(coordinate) | ||
} | ||
|
||
private fun inRange(coordinate: Coordinate, delta: Delta): Boolean { | ||
return coordinate.movePossible( | ||
delta = delta, | ||
verticalLimit = verticalSize, | ||
horizontalLimit = horizontalSize | ||
) | ||
private fun discoveredAllMines() { | ||
vision.exposeAll(mines.coordinates) | ||
} | ||
|
||
private fun isMineDeployed(coordinate: Coordinate): Boolean = | ||
mines.attribute(coordinate) == Attribute.MINE | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package minesweeper.model.board | ||
|
||
import minesweeper.model.point.Horizontal | ||
import minesweeper.model.point.Vertical | ||
|
||
data class BoardLimit( | ||
val verticalLimit: Vertical, | ||
val horizontalLimit: Horizontal, | ||
) { | ||
val area: Int | ||
get() = this.verticalLimit.value * this.horizontalLimit.value | ||
|
||
fun verticalRange(): IntRange { | ||
return this.verticalLimit.range() | ||
} | ||
|
||
fun horizontalRange(): IntRange { | ||
return this.horizontalLimit.range() | ||
} | ||
} | ||
|
||
fun Pair<Int, Int>.toBoardLimit(): BoardLimit { | ||
return BoardLimit( | ||
Vertical(this.first), | ||
Horizontal(this.second) | ||
) | ||
} |
7 changes: 0 additions & 7 deletions
7
src/main/kotlin/minesweeper/model/board/MineDeployStrategy.kt
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package minesweeper.model.board | ||
|
||
import minesweeper.model.point.Attribute | ||
import minesweeper.model.point.Coordinate | ||
import minesweeper.model.point.Delta | ||
|
||
class Mines( | ||
private val deployedCoordinate: Map<Coordinate, Attribute>, | ||
private val limit: BoardLimit, | ||
) { | ||
|
||
val count: Int | ||
get() = deployedCoordinate.values.count { it == Attribute.MINE } | ||
|
||
val coordinates: Set<Coordinate> | ||
get() = deployedCoordinate.keys | ||
|
||
private fun isDeployedCoordinate(coordinate: Coordinate): Boolean { | ||
return deployedCoordinate.containsKey(coordinate) | ||
} | ||
|
||
fun attribute(coordinate: Coordinate): Attribute { | ||
return when (this.isDeployedCoordinate(coordinate)) { | ||
true -> Attribute.MINE | ||
false -> Attribute.GROUND | ||
} | ||
} | ||
|
||
fun isGround(coordinate: Coordinate): Boolean = | ||
this.attribute(coordinate) == Attribute.GROUND | ||
|
||
fun isAdjacentMineCountZero(coordinate: Coordinate): Boolean = | ||
this.adjacentMineCount(coordinate) == 0 | ||
|
||
fun adjacentMineCount(coordinate: Coordinate): Int { | ||
return Delta.deltas.asSequence() | ||
.filter { delta -> inRange(coordinate, delta) } | ||
.map { this.attribute(coordinate.moveTo(it)) } | ||
.count { it.isMine() } | ||
} | ||
|
||
private fun inRange(coordinate: Coordinate, delta: Delta): Boolean { | ||
return coordinate.movePossible( | ||
delta = delta, | ||
limit = limit | ||
) | ||
} | ||
} | ||
|
||
fun Map<Coordinate, Attribute>.toMines(limit: BoardLimit): Mines { | ||
return Mines(this, limit) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package minesweeper.model.board | ||
|
||
import minesweeper.model.point.Coordinate | ||
|
||
class Vision(coordinates: Set<Coordinate>) { | ||
|
||
private val coveredCoordinates: MutableSet<Coordinate> | ||
|
||
val coveredCount: Int | ||
get() = coveredCoordinates.size | ||
|
||
init { | ||
this.coveredCoordinates = coordinates.toMutableSet() | ||
} | ||
|
||
fun exposeAll(coordinates: Set<Coordinate>) { | ||
this.coveredCoordinates.removeAll(coordinates) | ||
} | ||
|
||
fun isCovered(coordinate: Coordinate): Boolean { | ||
return coveredCoordinates.contains(coordinate) | ||
} | ||
} | ||
|
||
fun Set<Coordinate>.toVision(): Vision { | ||
return Vision(this) | ||
} |
9 changes: 9 additions & 0 deletions
9
src/main/kotlin/minesweeper/model/board/minedeploy/MineDeployStrategy.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package minesweeper.model.board.minedeploy | ||
|
||
import minesweeper.model.board.BoardLimit | ||
import minesweeper.model.point.Attribute | ||
import minesweeper.model.point.Coordinate | ||
|
||
interface MineDeployStrategy { | ||
fun deployPoints(boardLimit: BoardLimit): Map<Coordinate, Attribute> | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요 부분을 인스턴스 변수를 2개로 줄이려고 했는데, 조금 어려워서요... 다음번 PR 에서 수정해도 괜찮을까요? ㅠㅠ