Skip to content
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

[자동차 경주] 김민지 미션 제출합니다. #217

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
37 changes: 37 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# :car: 자동차 경주 :car:
우아한 테크코스 프리코스 2주차


## :potato: 기능 정리 :potato:
### :one: 게임 진행 문장 출력
* [X] 자동차 이름 입력에 대한 요청 문구를 출력하는 기능
* [X] 시도할 횟수 입력에 대한 질의 문구를 출력하는 기능
* [X] 실행 결과 출력에 대한 알림 문구를 출력하는 기능

### :two: 자동차 이름 입력
* [X] 유저로부터 자동차 이름을 입력 받는 기능
* [X] 유저의 입력에 대한 예외처리 기능

### :three: 시도할 횟수 입력
* [X] 유저로부터 시도할 횟수를 입력 받는 기능
* [X] 유저의 입력에 대한 예외처리 기능

### :four: 경기 진행
* [X] 모든 자동차에 대해 무작위 값을 구하는 기능
* [X] 모든 자동차의 무작위 값에 대해 전진 여부를 구하는 기능
* [X] 모든 자동차에 대해 실행 결과를 출력하는 기능

### :five: 우승자 출력
* [X] 실행 결과에 따라 우승자를 결정하는 기능
* [X] 최종 우승자를 출력하는 기능

<br/>

## :triangular_ruler: 예외처리 :triangular_ruler:
### :one: 자동차 이름 입력에 대한 예외처리
* 5자를 초과하는 입력 (ex.abcdef)
* 우승자를 명확하게 알릴 수 없게 하는 중복된 자동차 이름의 입력 (ex.abcde,abcde)

### :two: 시도할 횟수 입력에 대한 예외처리
* 숫자 이외의 입력 (ex.가, $%^)
* 양의 정수가 아닌 숫자의 입력 (ex.0, -1, 1.5)
3 changes: 2 additions & 1 deletion src/main/kotlin/racingcar/Application.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package racingcar

fun main() {
// TODO: 프로그램 구현
val game = Game()
game.run()
}
32 changes: 32 additions & 0 deletions src/main/kotlin/racingcar/Car.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package racingcar

import camp.nextstep.edu.missionutils.Randoms

class Car(name: String) {
private val name: String
private var location: Int
private val minRandomNumber: Int = 0
private val baseRandomNumber: Int = 4
private val maxRandomNumber: Int = 9

fun getName() = name
fun getLocation() = location

init {
this.name = name
this.location = 0
}

private fun canMoveForward(): Boolean {
val randomNumber = Randoms.pickNumberInRange(minRandomNumber, maxRandomNumber)
return randomNumber >= baseRandomNumber
}

fun tryToMoveForward() {
if (canMoveForward()) location++
}

fun showResult() {
println("${this.name} : ${"-".repeat(location)}")
}
}
83 changes: 83 additions & 0 deletions src/main/kotlin/racingcar/Game.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package racingcar

import camp.nextstep.edu.missionutils.Console

class Game {
private lateinit var carList: List<Car>
private var tryNumber: Int = 0

private enum class ProgressMessage(val message: String) {
RequestCarName("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"),
RequestTryNumber("시도할 횟수는 몇 회인가요?"),
DescribeNextResult("\n실행결과");

fun show() {
println(this.message)
}
}

fun run() {
ProgressMessage.RequestCarName.show()
getCarList()

ProgressMessage.RequestTryNumber.show()
getTryNumber()

ProgressMessage.DescribeNextResult.show()
startRace()
showWinnerList()
}

private fun initCarList(inputCarList: List<Car>) {
this.carList = inputCarList
}

private fun initTryNumber(inputNumber: Int) {
this.tryNumber = inputNumber
}

private fun getCarList() {
val carList = Console.readLine().split(",")
verifyCarList(carList)
initCarList(carList.map { Car(it) })
}

private fun getTryNumber() {
val tryNumber = Console.readLine()
verifyTryNumber(tryNumber)
initTryNumber(tryNumber.toInt())
}

private fun startRace() {
repeat(tryNumber) {
carList.forEach {
it.tryToMoveForward()
it.showResult()
}
print("\n")
}
}

private fun makeWinnerList(): List<String> {
var winnerList = mutableListOf<String>()
var winnerLocation = 0

for (car in carList) {
var carLocation = car.getLocation()
if (carLocation > winnerLocation) {
winnerLocation = carLocation
winnerList = mutableListOf()
winnerList.add(car.getName())
} else if (carLocation == winnerLocation) {
winnerList.add(car.getName())
}
}

return winnerList
}

private fun showWinnerList() {
var winnerList = makeWinnerList()
println("최종 우승자 : ${winnerList.joinToString(", ")}")
}
}
20 changes: 20 additions & 0 deletions src/main/kotlin/racingcar/Validators.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package racingcar

fun verifyCarList(carList: List<String>) {
require(carList.size == carList.distinct().size) { "자동차 이름은 중복될 수 없습니다." }
carList.forEach { verifyCarName(it) }
}

fun verifyCarName(name: String) {
val minNameLength = 1
val maxNameLength = 5

require(name.length >= minNameLength) { "1자 이상의 자동차 이름을 입력하세요." }
require(name.length <= maxNameLength) { "5자 이하의 자동차 이름을 입력하세요." }
}

fun verifyTryNumber(number: String) {
val tryNumber = number.toIntOrNull()
require(tryNumber != null) { "정수를 입력하세요." }
require(tryNumber > 0) { "양수를 입력하세요." }
}
22 changes: 22 additions & 0 deletions src/test/kotlin/racingcar/ApplicationTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,28 @@ class ApplicationTest : NsTest() {
assertSimpleTest {
assertThrows<IllegalArgumentException> { runException("pobi,javaji", "1") }
}
assertSimpleTest {
assertThrows<IllegalArgumentException> { runException("min,", "1") }
}
assertSimpleTest {
assertThrows<IllegalArgumentException> { runException("", "1") }
}
assertSimpleTest {
assertThrows<IllegalArgumentException> { runException("min,min", "1") }
}
}

@Test
fun `실행 횟수에 대한 예외 처리`() {
assertSimpleTest {
assertThrows<IllegalArgumentException> { runException("min,ji", "-1") }
}
assertSimpleTest {
assertThrows<IllegalArgumentException> { runException("min,ji", "1.5") }
}
assertSimpleTest {
assertThrows<IllegalArgumentException> { runException("min,ji", "가나다") }
}
}

public override fun runMain() {
Expand Down