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

[자동차 경주 step1] 김종경 미션 제출합니다. #21

Open
wants to merge 23 commits into
base: JONG-KYEONG
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
# kotlin-racingcar
# kotlin-racingcar
### 요구사항
-[x] 각 자동차에 이름을 부여할 수 있다.
-[x] 자동차 이름은 5자를 초과할 수 없다.
-[x] 자동차 이름은 공백을 포함할 수 없다.
-[x] 자동차 이름은 쉼표(,)를 기준으로 구분한다.
-[x] 시도할 횟수를 입력할 수 있어야 한다.
-[x] 잘못된 입력을 받으면 IllegalArgumentException을 발생시켜야한다.
-[x] 자동차는 전진 또는 멈출 수 있다.
-[x] 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다.
-[x] 전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다.
-[x] 자동차의 상태를 화면에 출력한다.
-[x] 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다.
-[x] 우승자는 한 명 이상일 수 있다.
26 changes: 26 additions & 0 deletions src/main/kotlin/racingcar/controller/CarController.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package racingcar.controller

import racingcar.domain.Car
import racingcar.domain.CarService
import racingcar.view.Input
import racingcar.view.Output

class CarController {
fun setGame(){
val names = Input().readCarName()
val cars = CarService().createNewCars(names)
val repeatTime = Input().readTryNumber()
startGame(cars,repeatTime)
endGame(cars)
}
fun startGame(carList : List<Car>, repeatTime : Int){
Output().printMessage()
repeat(repeatTime!!) {
CarService().progressGame(carList)
Output().printExecutionResult(carList) }
}
fun endGame(carList : List<Car>){
val winnerList = CarService().getWinners(carList)
Output().printFinalResult(winnerList)
}
}
18 changes: 18 additions & 0 deletions src/main/kotlin/racingcar/domain/Car.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package racingcar.domain

import kotlin.random.Random

class Car(val name : String){
var position : Int = 0
private set
init {
require(name.length <= CAR_NAME_LENGTH) { "자동차 이름은 5글자를 초과할 수 없습니다." }
require(!name.contains(" ")) { "자동차 이름은 공백을 포함 할 수 없습니다." }
}
fun move(){
position++
}
companion object {
private const val CAR_NAME_LENGTH = 5
}
}
20 changes: 20 additions & 0 deletions src/main/kotlin/racingcar/domain/CarService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package racingcar.domain

class CarService {
fun createNewCars(names: List<String>?): List<Car> {
return names!!.map { name -> Car(name) }
}
Comment on lines +4 to +6
Copy link
Contributor

Choose a reason for hiding this comment

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

newCars 를 만드는데 인자가 nullable 일 필요가 있을까요?
이 객체의 테스트도 빠졌습니다 :(

fun progressGame(carList : List<Car>) {
carList.forEach { car ->
if(RandomNumber().getRandomNumber() >= CAR_MOVE_CONDITION)
car.move()
Comment on lines +9 to +10
Copy link
Contributor

Choose a reason for hiding this comment

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

의존하고 있어 테스트하기 힘든 구조인데 어떻게 할 수 있을까요?

}
}
fun getWinners(carList: List<Car>) : List<Car>{
val maxDistance = carList.maxOfOrNull { it.position }
return carList.filter { car -> car.position == maxDistance }
}
companion object {
private const val CAR_MOVE_CONDITION = 4
}
}
9 changes: 9 additions & 0 deletions src/main/kotlin/racingcar/domain/RandomNumber.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package racingcar.domain

class RandomNumber {
fun getRandomNumber(): Int = (MIN_NUMBER_RANGE..MAX_NUMBER_RANGE).random()
companion object {
private const val MIN_NUMBER_RANGE = 0
private const val MAX_NUMBER_RANGE = 9
}
}
3 changes: 3 additions & 0 deletions src/main/kotlin/racingcar/main.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package racingcar

import racingcar.controller.CarController

fun main() {
// TODO: 프로그램 구현
CarController().setGame()
}
13 changes: 13 additions & 0 deletions src/main/kotlin/racingcar/view/Input.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package racingcar.view

class Input {
fun readCarName(): List<String>? {
println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분).")
return readlnOrNull()?.split(",")
}

fun readTryNumber() : Int {
println("시도할 횟수는 몇 회인가요?")
return readln().toIntOrNull() ?: throw IllegalArgumentException()
}
}
27 changes: 27 additions & 0 deletions src/main/kotlin/racingcar/view/Output.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package racingcar.view

import racingcar.domain.Car

class Output {
fun printExecutionResult(carList : List<Car>){
carList.forEach { car ->
print(car.name + " : ")
repeat(car.position) {
print("-")
}
println()
}
Comment on lines +7 to +13
Copy link
Contributor

Choose a reason for hiding this comment

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

이런식으로 짧은 코드도 가능합니다.ㅎㅎ

Suggested change
carList.forEach { car ->
print(car.name + " : ")
repeat(car.position) {
print("-")
}
println()
}
carList.forEach { car ->
println(car.name + " : " + "-".repeat(car.position))
}

println()
}

fun printMessage(){
println()
println("실행 결과")
}

fun printFinalResult(winnerList : List<Car>){
print("최종 우승자: ")
print(winnerList.joinToString(", ") { it.name })
}

}
4 changes: 4 additions & 0 deletions src/test/kotlin/study/controller/CarControllerTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package study.controller

class CarControllerTest {
}
44 changes: 44 additions & 0 deletions src/test/kotlin/study/domain/CarTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package study.domain

import org.junit.jupiter.api.Test
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.assertThrows
import racingcar.domain.Car


class CarTest {
@Test
fun `각 자동차에 이름을 부여할 수 있다`() {
//Given
var car = Car("김종경")
//Then
assertThat(car.name).isEqualTo("김종경")
}

@Test
fun `init 자동차 이름은 5자를 초과할 수 없다`() {
assertThrows<IllegalArgumentException> {
Car("김종경자동차")
}
}

@Test
fun `init 자동차 이름은 공백을 포함할 수 없다`() {
assertThrows<IllegalArgumentException> {
Car("김 종경")
}
}

@Test
fun `자동차는 전진 또는 멈출 수 있다`() {
//Given
var car1 = Car("김종경")
car1.move()

var car2 = Car("양두영")
car2.move()
//Then
assertThat(car1.position==0 && car2.position==1)
}

}
4 changes: 4 additions & 0 deletions src/test/kotlin/study/domain/RandomNumberTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package study.domain

class RandomNumberTest {
}
48 changes: 48 additions & 0 deletions src/test/kotlin/study/view/InputTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package study.view

import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import racingcar.view.Input
import java.io.ByteArrayInputStream

class InputTest {
@Test
fun `자동차 이름은 쉼표(,)를 기준으로 구분한다`() {
// Given
val input = "김종경,양두영,윤성원\n"
System.setIn(ByteArrayInputStream(input.toByteArray()))

// When
val result = Input().readCarName()

// Then
val expected = listOf("김종경", "양두영", "윤성원")
Assertions.assertEquals(expected, result)
}

@Test
fun `시도할 횟수를 입력할 수 있어야 한다`() {
// Given
val input = "5\n"
System.setIn(ByteArrayInputStream(input.toByteArray()))

// When
val result = Input().readTryNumber()

// Then
val expected = 5
Assertions.assertEquals(expected, result)
}

@Test
fun `시도할 횟수 입력 시 잘못된 입력을 받으면 IllegalArgumentException을 발생시켜야한다`() {
val input = "김종경\n"
System.setIn(ByteArrayInputStream(input.toByteArray()))

assertThrows<IllegalArgumentException> {
Input().readTryNumber()
}
}

}
49 changes: 49 additions & 0 deletions src/test/kotlin/study/view/OutputTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package study.view

import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import racingcar.domain.Car
import racingcar.domain.RandomNumber
import racingcar.view.Output
import java.io.ByteArrayOutputStream
import java.io.PrintStream

class OutputTest {

@Test
fun `전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다`() {
// given
var car1 = Car("김종경")
car1.move()
var carlist = mutableListOf<Car>()
carlist.add(car1)

//when
val outputStream = ByteArrayOutputStream()
System.setOut(PrintStream(outputStream))
Output().printExecutionResult(carlist)

// then
val expectedOutput = "김종경 : \n"
Assertions.assertEquals(expectedOutput.trim(), outputStream.toString().trim())
}

@Test
fun `전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다`() {
// given
var car1 = Car("김종경")
car1.move()
car1.move()
var carlist = mutableListOf<Car>()
carlist.add(car1)

//when
val outputStream = ByteArrayOutputStream()
System.setOut(PrintStream(outputStream))
Output().printExecutionResult(carlist)

// then
val expectedOutput = "김종경 : \n"
Assertions.assertEquals(expectedOutput.trim(), outputStream.toString().trim())
}
}