-
Notifications
You must be signed in to change notification settings - Fork 56
[자동차 경주] 김가윤 미션 제출합니다. #49
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
base: main
Are you sure you want to change the base?
Changes from all commits
bf0d4bf
8ab850c
f114ffd
d0cd272
ab02643
56dd1df
af2ea78
379bfd2
d82f09f
d2e8ef3
6e1eece
c6f4d5a
0f9e890
5bea804
e9e74d3
217e8d1
444f4c6
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 |
|---|---|---|
| @@ -1 +1,25 @@ | ||
| # kotlin-racingcar-precourse | ||
| # 자동차 경주 | ||
| ## 기능 목록 | ||
| 1. 입력 | ||
| - 자동차 이름 입력 | ||
| - 시도할 횟수 입력 | ||
|
|
||
| 2. 경주 준비 | ||
| - 이름 쉼표 단위 분리 | ||
| - 이름 5자 이하 확인 | ||
|
|
||
| 3. 경주 시작 | ||
| - 무작위 값 부여 | ||
| - 정해진 횟수만큼 반복 | ||
|
|
||
| 4. 경주 결과 | ||
| - 우승자 결정 | ||
|
|
||
| 5. 출력 | ||
| - 중간 과정 출력 | ||
| - 우승자 출력 | ||
|
|
||
| ### 스스로 판단한 사항 | ||
| - 이름으로 공백 입력할 경우 예외 발생 | ||
| - 시도 횟수 0 이하인 경우 예외 발생 | ||
| - 중복된 이름 사용할 경우 예외 발생 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,8 @@ | ||
| package racingcar | ||
|
|
||
| import racingcar.controller.RacingController | ||
|
|
||
| fun main() { | ||
| // TODO: 프로그램 구현 | ||
| } | ||
| val racingController = RacingController() | ||
| racingController.run() | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package racingcar.controller | ||
|
|
||
| import racingcar.model.Car | ||
| import racingcar.model.RacingGame | ||
| import racingcar.view.InputView | ||
| import racingcar.view.OutputView | ||
|
|
||
| class RacingController( | ||
| private val inputView: InputView = InputView(), | ||
| private val outputView: OutputView = OutputView() | ||
| ) { | ||
| fun run() { | ||
| val names = inputView.readCarNames() | ||
| val count = inputView.readRoundCount() | ||
|
|
||
| val cars = names.map { Car(it) } | ||
| val game = RacingGame(cars) | ||
|
|
||
| outputView.printGameStart() | ||
| repeat(count) { | ||
| game.playRound() | ||
| outputView.printRoundResult(cars) | ||
| } | ||
|
|
||
| outputView.printWinner(game.judgeResult()) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package racingcar.model | ||
|
|
||
| import camp.nextstep.edu.missionutils.Randoms | ||
|
|
||
| class Car(val name: String) { | ||
| var position: Int = 0 | ||
|
|
||
| fun move() { | ||
| if (Randoms.pickNumberInRange(0, 9) >= 4) position++ | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package racingcar.model | ||
|
|
||
| import racingcar.view.OutputView | ||
|
|
||
| class RacingGame(private val cars: List<Car>) { | ||
| fun playRound() { | ||
| cars.forEach { it.move() } | ||
| } | ||
|
|
||
| fun judgeResult(): List<String> { | ||
| val maxPosition = cars.maxOf { it.position } | ||
| val winners = cars.filter { it.position == maxPosition }.map { it.name } | ||
|
|
||
| return winners | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package racingcar.model.validator | ||
|
|
||
| object CarValidator { | ||
| fun parse(input: String): List<String> { | ||
| val names = input.split(",").map { it.trim() } | ||
| validateCarName(names) | ||
|
|
||
| return names | ||
| } | ||
|
|
||
| private fun validateCarName(names: List<String>) { | ||
| require(names.all { it.isNotBlank() }) { throw IllegalArgumentException("자동차 이름은 비어 있을 수 없습니다.") } | ||
| require(names.all { it.length <= 5 }) { throw IllegalArgumentException("자동차 이름은 5자 이하만 가능합니다.") } | ||
| require(names.distinct().size == names.size) { throw IllegalArgumentException("자동차 이름은 중복될 수 없습니다.") } | ||
| } | ||
| } | ||
|
Comment on lines
+3
to
+16
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. CarValidator에 validate 말고도 parse도 있네요. parse를 따로 parser 클래스에 두시거나 Car 클래스에 두시는 것도 좋았을 것 같습니다. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package racingcar.model.validator | ||
|
|
||
| object RoundCountValidator { | ||
| fun validate(countInput: String): Int { | ||
| val number = countInput.toIntOrNull() | ||
| ?: throw IllegalArgumentException("시도 횟수는 숫자여야 합니다.") | ||
| require(number > 0) { "시도 횟수는 1 이상이어야 합니다." } | ||
|
|
||
| return number | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package racingcar.view | ||
|
|
||
| import camp.nextstep.edu.missionutils.Console | ||
| import racingcar.model.validator.CarValidator | ||
| import racingcar.model.validator.RoundCountValidator | ||
|
|
||
| class InputView { | ||
| fun readCarNames(): List<String> { | ||
| println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)") | ||
| val carsInput = Console.readLine() | ||
|
|
||
| return CarValidator.parse(carsInput) | ||
| } | ||
|
Comment on lines
+8
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. 저도 지적받은 사항인데, InputView에서는 parse와 같은 다른 처리를 두지 않고 입력만 처리하면 좋을 것 같습니다! |
||
|
|
||
| fun readRoundCount(): Int { | ||
| println("시도할 횟수는 몇 회인가요?") | ||
| val countInput = Console.readLine() | ||
|
|
||
| return RoundCountValidator.validate(countInput) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package racingcar.view | ||
|
|
||
| import racingcar.model.Car | ||
|
|
||
| class OutputView { | ||
| fun printGameStart() { | ||
| println("실행 결과") | ||
| } | ||
|
|
||
| fun printRoundResult(cars: List<Car>) { | ||
| cars.forEach { car -> | ||
| println("${car.name} : ${"-".repeat(car.position)}") | ||
| } | ||
| println("") | ||
| } | ||
|
|
||
| fun printWinner(names: List<String>) { | ||
| println("최종 우승자 : ${names.joinToString(", ")}") | ||
| } | ||
| } |
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.
InputView, OutputView는 프로젝트 내에서 여러 번 할당되지도 않고 상태도 갖고 있지 않기에 object 클래스로 선언하여 static 처럼 쓰시는 게 좋을 거 같습니다!