-
Notifications
You must be signed in to change notification settings - Fork 230
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
[코드 리뷰용 PR입니다!] - 재구현 스터디 #248
base: main
Are you sure you want to change the base?
Changes from all commits
fbeb443
563d670
27c0fd4
1087ebe
fbcefd2
5982e61
7031314
a8a0177
ffc60cf
53d6d0b
e4ceee5
29fbb0b
8e1ebce
5bbfafc
3109358
5ec8f5a
ecdc227
bae4f2c
a3315d3
98afa52
6eda278
167cfbe
5c8ee0f
21d9d3c
95ba52c
49f2120
e66299b
afdf4c2
78f0763
93f47cd
e8d7eee
f35bf5f
9e78c64
6ad661b
43de2d9
bcff196
cbfb946
786b7e0
0b68cf7
d475be5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
# 기능 목록(순서 무관) | ||
|
||
- 난수 생성 기능 | ||
- 힌트 결정(= 난수와 플레이어 입력값 비교) 기능 | ||
- 플레이어 입력 받는 기능 (“숫자를 입력해주세요: “) | ||
- 입력받은 값의 유효성 검사 기능 (플레이어의 입력에 문제가 있는지) | ||
- `IllegalArgumentException`을 발생시킨 후 애플리케이션은 종료하는 기능 | ||
- 힌트와 게임 종료 조건 비교 기능 (힌트가 3스트라이크와 같은지 아닌지) | ||
- 게임 재시작 여부 결정 기능(= 사용자에게 1 또는 2를 입력받아 재시작 여부를 결정하는 기능) | ||
- 힌트를 출력하는 기능 | ||
- 게임 종료 멘트 출력 기능 (”3개의 숫자를 모두 맞히셨습니다! 게임 종료”) | ||
- 게임 시작 멘트 출력 기능 (”숫자 야구 게임을 시작합니다.”) | ||
|
||
# 🌱 정리 | ||
|
||
|
||
### 플레이어 | ||
|
||
- 1~9 사이의 숫자로 구성된 서로 다른 세 자리 수로 구성된 수를 시스템에 입력 | ||
- 게임 종료 후, 재시작 여부를 시스템에 입력 | ||
|
||
### 상대방(컴퓨터) | ||
|
||
- 난수 생성 후 저장 | ||
- 시스템으로 받은 값으로 스트라이크, 볼, 낫싱 힌트 결정 | ||
- 저장된 난수와 비교 | ||
- 힌트 결정 | ||
- 힌트를 시스템에 전달 | ||
|
||
### 시스템 | ||
|
||
- 게임 시작 문구 출력 | ||
|
||
`숫자 야구 게임을 시작합니다.` | ||
|
||
- 플레이어의 입력을 받음 | ||
|
||
`숫자를 입력해주세요 : ㅇㅇㅇ` | ||
|
||
- 플레이어의 입력값 유효성 검사 | ||
- 플레이어가 문제없는 값을 입력한 경우, 값을 상대방(컴퓨터)에게 전달 | ||
|
||
(문제가 없는 값 ⇒ 1~9 사이의 숫자로 구성된 서로 다른 세 자리 수) | ||
|
||
- 플레이어가 잘못된 값을 입력할 경우 `IllegalArgumentException`을 발생시킨 후 애플리케이션은 종료 | ||
- 전달받은 힌트 확인 | ||
|
||
if) 힌트 == 3스트라이크 | ||
|
||
- 게임종료 멘트 출력 | ||
|
||
`3개의 숫자를 모두 맞히셨습니다! 게임 종료` | ||
|
||
- 종료할 지, 재시작할 지 사용자에게 입력 받음 | ||
|
||
`게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.` | ||
|
||
else) 힌트 출력 기능 실행 | ||
|
||
- 힌트 출력 | ||
|
||
ex) `1볼 2스트라이크` | ||
|
||
|
||
# 프로그램 흐름 | ||
|
||
|
||
**시스템)** 게임 시작 출력 | ||
|
||
- `숫자 야구 게임을 시작합니다.` | ||
|
||
**컴퓨터) 난수 생성 후 저장** | ||
|
||
**시스템) 플레이어에게 입력을 받음** | ||
|
||
- `숫자를 입력해주세요 :` | ||
|
||
**플레이어)** 3자리수 입력 | ||
|
||
**시스템)** 입력 값이 유효한 지 검사 | ||
|
||
- 유효하지 않을 경우 ⇒ `IllegalArgumentException`을 발생시킨 후 애플리케이션은 종료 | ||
- 유효한 경우 ⇒ 컴퓨터에게 전달 | ||
|
||
**컴퓨터)** 저장된 난수와 비교 후 힌트 결정 (힌트 - 낫싱, 볼, 스트라이크) | ||
|
||
**컴퓨터)** 시스템에게 힌트 전달 | ||
|
||
**시스템)** 전달받은 힌트 확인 | ||
|
||
- if) 힌트 == 3스트라이크 | ||
|
||
- **시스템)** 종료 프로세스 시작 | ||
|
||
- 종료 프로세스 [ | ||
- **시스템)** 게임종료 멘트 출력 | ||
- `게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.` | ||
- **플레이어)** 1 또는 2 입력 | ||
|
||
if) 1 입력 | ||
|
||
- **[ 컴퓨터) 난수 생성 후 저장 ] 단계**로 돌아감 | ||
|
||
if) 2 입력 | ||
|
||
- 프로그램 종료 | ||
|
||
] | ||
|
||
- else) | ||
- **시스템)** 전달받은 힌트 출력 | ||
|
||
- **시스템)** **[ 시스템) 플레이어에게 입력을 받음 ] 단계**로 돌아감 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,11 @@ | ||
package baseball | ||
|
||
import baseball.controller.System | ||
|
||
fun main() { | ||
TODO("프로그램 구현") | ||
val system = System() | ||
system.gameStart() | ||
} | ||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package baseball.controller | ||
|
||
import baseball.model.Computer | ||
import baseball.util.C.FINISH_CONDITION | ||
import baseball.util.Validator.checkUserInputValid | ||
import baseball.view.GameInputView | ||
import baseball.view.GameOutputView | ||
|
||
class System { | ||
|
||
private var userInputList: List<String> = listOf() | ||
private var userInput: String = "" | ||
private var isFinished = false | ||
private var result: Pair<Int, Int> = Pair(0, 0) | ||
private val computer = Computer() | ||
private val gamerOutputView = GameOutputView() | ||
private val gameInputView = GameInputView() | ||
|
||
init { | ||
gamerOutputView.printGameStart() | ||
computer.makeRandomNums() | ||
} | ||
|
||
//게임 실행 함수 | ||
fun gameStart() { | ||
while (!isFinished) { | ||
handleGameStart() | ||
handleGameResult() | ||
if (isGameFinished()) { | ||
handleGameEnd() | ||
} | ||
} | ||
} | ||
|
||
private fun handleGameStart() { | ||
gamerOutputView.printInput().apply { | ||
userInput = gameInputView.getUserInput() | ||
checkUserInputValid(userInput) | ||
userInputList = gameInputView.makeUserInputList(userInput) | ||
} | ||
} | ||
|
||
private fun handleGameResult() { | ||
result = computer.getGameResult(userInputList) | ||
gamerOutputView.printGameResult(result) | ||
} | ||
|
||
private fun handleGameEnd() { | ||
gamerOutputView.printGameEnded() | ||
if (gameInputView.endGame()) isFinished = true | ||
else computer.makeRandomNums() | ||
} | ||
|
||
private fun isGameFinished() = result.first == FINISH_CONDITION | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package baseball.model | ||
|
||
data class Ball( | ||
var strike:Int = 0, | ||
var ball:Int = 0 | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package baseball.model | ||
|
||
import baseball.util.C.RANDOM_SIZE | ||
import camp.nextstep.edu.missionutils.Randoms | ||
|
||
data class Computer( | ||
var randomNums: MutableList<String> = mutableListOf() | ||
) { | ||
fun makeRandomNums() { | ||
var temp = "" | ||
randomNums = mutableListOf<String>() | ||
while (randomNums.size < RANDOM_SIZE) { | ||
temp = Randoms.pickNumberInRange(1, 9).toString() | ||
if (!randomNums.contains(temp)) { | ||
randomNums.add(temp) | ||
} | ||
} | ||
} | ||
|
||
//게임 결과를 도출하는 함수 | ||
fun getGameResult(userInputList: List<String>): Pair<Int, Int> { | ||
var (strike, ball) = Pair(0, 0) | ||
for (i in userInputList.indices) { | ||
if (userInputList[i] == randomNums[i]) strike++ | ||
else if ((userInputList[i] != randomNums[i]) && randomNums.contains(userInputList[i])) ball++ | ||
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. 이 부분에서 |
||
} | ||
return Pair(strike, ball) | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package baseball.util | ||
|
||
object C { | ||
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. C라는 이름 보다는 Constants라는 이름으로 정확한 의도를 드러내는 것이 나아보여요! |
||
const val GAME_START_MSG = "숫자 야구 게임을 시작합니다." | ||
const val GAME_END_MSG = "3개의 숫자를 모두 맞히셨습니다! 게임 종료" | ||
const val GAME_RESTART_MSG = "게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요." | ||
const val GET_INPUT_MSG = "숫자를 입력해주세요 : " | ||
|
||
const val STRIKE_STRING = "스트라이크" | ||
const val BALL_STRING = "볼" | ||
const val NOTHING = "낫싱" | ||
|
||
const val RANDOM_SIZE = 3 | ||
const val FINISH_CONDITION = 3 | ||
|
||
const val INPUT_REGEX = "[1-9]{3}" | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package baseball.util | ||
|
||
object Validator { | ||
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. 1주차 피드백 내용에는 이름을 통하여 의도가 드러났다면 주석을 사용하지 않는 것이 좋다고 나와있습니다! |
||
//플레이어의 입력값이 유효한 지 검사하는 함수 | ||
fun checkUserInputValid(userInput: String) { | ||
if (!checkRegexMatch(userInput) || !checkDiffNums(userInput)) throw IllegalArgumentException() | ||
} | ||
|
||
//정규표현식과 일치하는 지 확인하는 함수 | ||
private fun checkRegexMatch(userInput: String): Boolean { | ||
val regex = C.INPUT_REGEX.toRegex() //1-9사이의 숫자로 구성된 세 자릿수 정규표현식 | ||
return regex.matches(userInput) | ||
} | ||
|
||
Comment on lines
+10
to
+14
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. .toRegex()라는 내장함수이 있다는 것은 알았는데 이렇게도 활용이 가능하다는 것은 처음 알았네요.😄 |
||
//중복된 숫자가 없는 지 확인하는 함수 | ||
private fun checkDiffNums(userInput: String): Boolean = (userInput.length == userInput.toSet().size) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package baseball.view | ||
|
||
import camp.nextstep.edu.missionutils.Console | ||
|
||
class GameInputView { | ||
//플레이어 입력을 받는 함수 | ||
fun getUserInput() = Console.readLine().toString() //플레이어 입력 | ||
//재시작 여부를 받는 함수 | ||
fun endGame(): Boolean { | ||
val userInput = Console.readLine() | ||
return when (userInput) { | ||
"1" -> false //종료 O, 재시작 X | ||
"2" -> true //종료 X , 재시작 O | ||
Comment on lines
+12
to
+13
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.
|
||
else -> throw IllegalArgumentException() | ||
} | ||
} | ||
fun makeUserInputList(userInput: String) = userInput.chunked(1) | ||
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.
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package baseball.view | ||
|
||
import baseball.util.C | ||
|
||
class GameOutputView { | ||
//게임 시작을 출력하는 함수 | ||
fun printGameStart() { | ||
println(C.GAME_START_MSG) | ||
} | ||
fun printInput(){ | ||
print(C.GET_INPUT_MSG) | ||
} | ||
|
||
//게임 결과를 출력하는 함수 | ||
fun printGameResult(result: Pair<Int, Int>) { | ||
val (strike, ball) = result | ||
val resultText = when { | ||
strike > 0 && ball == 0 -> "$strike${C.STRIKE_STRING}" | ||
strike == 0 && ball > 0 -> "$ball${C.BALL_STRING}" | ||
strike == 0 && ball == 0 -> C.NOTHING | ||
else -> "$ball${C.BALL_STRING} $strike${C.STRIKE_STRING}" | ||
} | ||
println(resultText) | ||
} | ||
//게임 종료를 출력하는 함수 | ||
fun printGameEnded() { | ||
println(C.GAME_END_MSG) | ||
println(C.GAME_RESTART_MSG) | ||
} | ||
} |
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.
저는 주로 run만을 사용하였는데 이렇게 apply를 사용하니까 이런 상황에서는 더 가독성이 좋아지네요.