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

step3 자동차 경주 구현 #1528

Open
wants to merge 1 commit into
base: wjddn279
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
37 changes: 37 additions & 0 deletions src/main/kotlin/racingcar/Racing.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package racingcar

import racingcar.car.Runnable
import racingcar.view.InputView
import racingcar.view.ResultView

class Racing<T: Runnable>(private val racingCarFactory: () -> T) {
fun race() {
Copy link

Choose a reason for hiding this comment

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

자동차 경주 단계부터는 실행할 수 있는 main 함수를 만들어주셔야합니다. 실제로 경주가 잘 되는지 확인도 해야하구요.

val carCount = InputView.getCarCount()
val racingCount = InputView.getRacingCount()

doRacing(carCount, racingCount)
}

fun doRacing(carCount: Int, racingCount: Int) {
val racingCars = getRacingCars(carCount)
val doRacingEachRound = racingEachRound(racingCount)

doRacingEachRound(racingCars, 0)
}

private fun getRacingCars(carCount: Int): List<T> {
return Array(carCount) {it + 1}.map { racingCarFactory() }
}

private fun racingEachRound(totalRound: Int): (List<Runnable>, Int) -> Unit {
return { cars, round ->
if (round == totalRound) {
// over the recursion
} else {
val nextCars = cars.map { it.run() }
ResultView.printPositions(nextCars.map { it.position })
racingEachRound(totalRound)(nextCars, round + 1)
}
}
}
}
18 changes: 18 additions & 0 deletions src/main/kotlin/racingcar/car/RacingCar.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package racingcar.car

import racingcar.utils.RandomGenerator

class RacingCar(override val position: Int = 0) : Runnable {
companion object {
private const val RANDOM_THRESHOLD = 10
}

override fun run(): RacingCar {
return RacingCar(move())
}

override fun getDistance(): Int {
val randomNumber = RandomGenerator.getRandomIntNumber(RANDOM_THRESHOLD)
return if (randomNumber >= 4) 1 else 0
Comment on lines +14 to +16
Copy link

Choose a reason for hiding this comment

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

수업 자료나 수업 다시보기 영상을 참고해서 테스트 가능한 구조로 구현해보시면 좋을 것 같아요. 랜덤을 만들어내는 부분을 도메인 바깥으로 분리하는 게 핵심이 되겠네요.
부족한 테스트도 자연스럽게 해결될 것 같습니다.

}
}
13 changes: 13 additions & 0 deletions src/main/kotlin/racingcar/car/Runnable.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package racingcar.car

interface Runnable {
val position: Int

fun run(): Runnable

fun move(): Int {
return position + getDistance()
}

fun getDistance(): Int
}
9 changes: 9 additions & 0 deletions src/main/kotlin/racingcar/utils/RandomGenerator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package racingcar.utils

import java.util.*
Copy link

Choose a reason for hiding this comment

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

코틀린에도 Random 패키지가 존재합니다. 코틀린 과정이니만큼 코틀린 패키지를 사용해보셔도 좋을 것 같아요.


object RandomGenerator {
fun getRandomIntNumber(threshold: Int): Int {
return Random().nextInt(threshold)
}
}
13 changes: 13 additions & 0 deletions src/main/kotlin/racingcar/view/InputView.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package racingcar.view

object InputView {
fun getCarCount(): Int {
println("자동차 대수는 몇 대 인가요?")
return readln().toInt()
}

fun getRacingCount(): Int {
println("경주 횟수는 몇 대 인가요?")
return readln().toInt()
}
}
15 changes: 15 additions & 0 deletions src/main/kotlin/racingcar/view/ResultView.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package racingcar.view

object ResultView {
fun printResult() {
println("주행 결과")
}

fun printPosition(position: Int) {
println("-".repeat(position))
}
fun printPositions(positions: List<Int>) {
positions.forEach { printPosition(it) }
println()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import org.junit.jupiter.api.Test

internal class SimpleFourBasicOperationTest {
private val operation = SimpleFourBasicOperation

@Test
fun addTest() {
assertThat(operation.add(3.0, 4.0)).isEqualTo(7.0)
Expand Down
12 changes: 12 additions & 0 deletions src/test/kotlin/racingcar/RacingTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package racingcar

import io.kotest.core.spec.style.FunSpec
import racingcar.car.RacingCar

class RacingTest: FunSpec({
// SystemOutExtension을 사용하여 콘솔 출력을 캡처
context("racing 통합 테스트") {
val racing = Racing { RacingCar() }
racing.doRacing(3, 5)
Comment on lines +7 to +10
Copy link

Choose a reason for hiding this comment

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

요구사항을 꼼꼼하게 체크해보시면
image
View에 대한 테스트는 작성하지 않으셔도 됩니다. 도메인 객체의 테스트에 집중해서 구현해보시면 좋을 것 같아요.

}
})
17 changes: 17 additions & 0 deletions src/test/kotlin/racingcar/car/CarTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package racingcar.car

import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.collections.shouldBeIn
import io.kotest.matchers.shouldBe

class CarTest: FunSpec({
context("자동차의 초기 위치는 0이다.") {
val car = RacingCar()
car.position shouldBe 0
}

context("한번 움직인 자동차의 위치는 0 아니면 1이어야 한다.") {
val car = RacingCar().run()
car.position shouldBeIn listOf<Int>(0, 1)
}
})
12 changes: 12 additions & 0 deletions src/test/kotlin/racingcar/utils/RandomGeneratorTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package racingcar.utils

import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.collections.shouldBeIn

class RandomGeneratorTest : FunSpec({
context("랜덤 값은 0이상, 지정한 값 이하여야 한다.") {
val threshold = 10
val randomIntNumbers = RandomGenerator.getRandomIntNumber(threshold)
randomIntNumbers shouldBeIn (0..threshold).toList().toTypedArray()
}
})