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

[Sdk0808] 프리코스 미션 제출합니다. #2

Open
wants to merge 2 commits into
base: main
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
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
# kotlin-racingcar-precourse
# kotlin-racingcar-precourse

## 요구 사항
- [ ] 참여자 이름을 받아 자동차를 생성
- [ ] 이름은 5자 이하, 쉼표로 구분
- [ ] 자동차는 0~9의 랜덤값이 4이상일 경우 전진
- [ ] 횟수를 입력받아 횟수만큼 자동차 전진
- [ ] 우승자 출력(복수 가능)
10 changes: 10 additions & 0 deletions src/main/kotlin/Main.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import logic.Input
import random.Random

fun main(args: Array<String>) {
val carGame = CarGame(
inputUtil = Input(),
randomUtil = Random(),
)
carGame.run()
}
48 changes: 48 additions & 0 deletions src/main/kotlin/RunGame.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import car.Car
import logic.InputUtil
import logic.Logic
import random.RandomUtil
import view.View


class CarGame(
inputUtil: InputUtil,
private val randomUtil: RandomUtil,
) {

private val view = View(
logic = Logic(),
input = inputUtil,
)

fun run() {
val carList = inputUserNamesAndMakeCarList()
repeat(REPEAT_TIME) {
carsMove(carList)
}
printWinner(carList)
}

private fun printWinner(carList: List<Car>) {
view.printWinner(carList)
}

private fun carsMove(carList: List<Car>) {
carList.forEach {
it.move(randomUtil.generateNumber())
}
}

private fun inputUserNamesAndMakeCarList(): List<Car> {
val splitName = view.printInputInfo()
val carList = mutableListOf<Car>()
splitName.forEach {
carList.add(Car(participantName = it))
}
return carList
}

companion object{
const val REPEAT_TIME = 5
}
}
29 changes: 29 additions & 0 deletions src/main/kotlin/car/Car.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package car

import move.MoveStrategy

class Car(
val participantName: String,
position: Int = 0,
private val moveStrategy: MoveStrategy = MoveStrategy(),
) {

var position = position
private set

init {
require(participantName.length <= NAME_LENGTH_VALIDATION) {
throw IllegalArgumentException("이름은 5자 이하여야 합니다.")
}
}

fun move(number : Int){
if(moveStrategy.isMovable(number)){
position++
}
}

companion object{
const val NAME_LENGTH_VALIDATION = 5
}
}
13 changes: 13 additions & 0 deletions src/main/kotlin/logic/Input.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package logic

interface InputUtil{
fun inputName() : String
}

class Input : InputUtil {
override fun inputName(): String {
return readLine() ?: throw IllegalArgumentException()
}
}

fun splitName(inputNames : String) = inputNames.split(",")
16 changes: 16 additions & 0 deletions src/main/kotlin/logic/Logic.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package logic

import car.Car

class Logic {
fun findWinner(inputCars: List<Car>): List<String> {
val maxValue = inputCars.maxOfOrNull {
it.position
}

return inputCars
.filter { it.position == maxValue }
.map { it.participantName }
.toList()
}
}
14 changes: 14 additions & 0 deletions src/main/kotlin/move/MoveStrategy.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package move

class MoveStrategy {

fun isMovable(number: Int): Boolean {
if (number < MOVE_THRESHOLD)
return false
return true
}

companion object{
const val MOVE_THRESHOLD = 4
}
}
18 changes: 18 additions & 0 deletions src/main/kotlin/random/RandomUtil.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package random

import java.security.SecureRandom

interface RandomUtil {
fun generateNumber(): Int
}

class Random : RandomUtil {
override fun generateNumber(): Int {
return secureRandom.nextInt(UPPER_BOUND)
}

companion object {
private val secureRandom = SecureRandom()
const val UPPER_BOUND = 9
}
}
31 changes: 31 additions & 0 deletions src/main/kotlin/view/View.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package view

import car.Car
import logic.InputUtil
import logic.Logic
import logic.splitName

class View(
private val logic: Logic,
private val input: InputUtil,
) {

fun printInputInfo(): List<String> {
println("경주에 참여할 참여자들을 입력해주세요")
println("입력시 이름은 , 으로 구분됩니다.")
println("입력 예시 : >> junuu,hong,chong,ggam << ")
val result = input.inputName()
val splitResult = splitName(result)
println("입력 결과 : $splitResult")
return splitResult
}

fun printWinner(inputCars: List<Car>) : List<String> {
val result = logic.findWinner(inputCars)
println("=======우승자========")
result.forEach {
println(it)
}
return result
}
}
24 changes: 24 additions & 0 deletions src/test/kotlin/IntegratedTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import car.Car
import logic.splitName
import org.junit.jupiter.api.Test
import random.RandomForTest
import view.InputForTest

class IntegratedTest {
@Test
fun `사용자는 이름을 입력하고 게임을 진행하여 우승자를 찾을 수 있다`() {
//given
val carGame = CarGame(
inputUtil = InputForTest(),
randomUtil = RandomForTest(),
)

//when
carGame.run()

//then
//RandomForTest()의 경우 3만 반환하며, InputForTest()는 junuu,hong,chong,ggam만 반환합니다.
//따라서 결과는 항상 모두 0칸을 가며 우승자는 모두입니다.

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

import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource

class CarTest {

@ParameterizedTest
@ValueSource(strings = ["junuu","hong"])
fun `참여자 이름으로 차를 생성`(input: String){
//given

//when
val car = Car(participantName = input)

//then
Assertions.assertNotNull(car)
Assertions.assertEquals(car.participantName, input)
}

@ParameterizedTest
@ValueSource(strings = ["junuu1","hong35"])
fun `참여자의 이름은 5자 이하여야 한다`(input: String){
//given

//when, then
Assertions.assertThrows(IllegalArgumentException::class.java){
Car(participantName = input)
}
}

@Test
fun `랜덤값으로 4,5,2가 호출되면 위치는 2칸 전진해야 한다`(){
//given
val car = Car(participantName = "junuu")

//when
car.move(4)
car.move(5)
car.move(2)

//then
Assertions.assertEquals(car.position, 2)
}
}
34 changes: 34 additions & 0 deletions src/test/kotlin/logic/InputTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package logic

import logic.splitName
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import view.InputForTest

class InputTest {
@Test
fun `이름은 쉼표로 구분한다`() {
//given
val inputNames = "junuu,hong,ggam,chong"

//when
val result = splitName(inputNames)

//then
Assertions.assertEquals(result.size, 4)
Assertions.assertEquals(result, listOf("junuu", "hong", "ggam", "chong"))
}

@Test
fun `사용자는 자동차 게임 유저를 입력할 수 있다`(){
//given
val inputUtil = InputForTest()

//when
val result = inputUtil.inputName()

//then
Assertions.assertEquals(result, "junuu,hong,chong,ggam")

}
}
63 changes: 63 additions & 0 deletions src/test/kotlin/logic/LogicTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package logic

import car.Car
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test

class LogicTest {

@Test
fun `position 가장 높은 차가 우승한다`(){
//given
val hong = Car(
participantName = "hong",
position = 4,
)
val junuu = Car(
participantName = "chong",
position = 1,
)
val input = listOf(junuu, hong)
val logic = Logic()

//when
val result = logic.findWinner(input)

//then
Assertions.assertEquals(result, listOf("hong"))
}

@Test
fun `우승자는 여러명일 수 있다`() {
//given
val junuu = Car(
participantName = "junuu",
position = 2,
)
val hong = Car(
participantName = "hong",
position = 2,
)
val chong = Car(
participantName = "chong",
position = 1,
)

val input = listOf(junuu, hong, chong)
val logic = Logic()

//when
val result = logic.findWinner(input)

//then
Assertions.assertEquals(result, listOf("junuu","hong"))

}

@Test
fun `maxOrNull 테스트`(){
val list = listOf(1,2,6,4,5,6)
val result = list.maxOrNull()
println(result)
}
}
Loading