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

[자동차 경주] 김원태 미션 제출합니다. #203

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,13 @@ Randoms.pickNumberInRange(0, 9)
- **Git의 커밋 단위는 앞 단계에서 `docs/README.md`에 정리한 기능 목록 단위**로 추가한다.
- [커밋 메시지 컨벤션](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 가이드를 참고해 커밋 메시지를 작성한다.
- 과제 진행 및 제출 방법은 [프리코스 과제 제출](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) 문서를 참고한다.

## 기능 목록

- Player 도메인 구현하기 v
- 사용자에게 보여주는 기능을 할 printGame 부분 구현하기 v
- 기본적인 게임을 제공할 틀 만들기 v
- 사용자로부터 입력을 받을 수 있는 기능 만들기 v
- 받은 값을 저장할 수 있도록 기능 만들기 v
- 실제 게임을 진행하는 기능 만들기 v
- 게임이 다 끝난 후 출력 만들기 v
7 changes: 6 additions & 1 deletion src/main/kotlin/racingcar/Application.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package racingcar

import racingcar.service.CarPlayGameImpl
import racingcar.service.CarPrintGame

fun main() {
// TODO: 프로그램 구현
val playGame = CarPlayGameImpl(CarPrintGame())

playGame.playGame()
}
14 changes: 14 additions & 0 deletions src/main/kotlin/racingcar/domain/Player.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package racingcar.domain

data class Player(
val name: String,
var winCount: Int = 0
) {
fun addWinCount() {
winCount++
}

companion object {
fun toPlayer(name: String): Player = Player(name, 0)
}
}
85 changes: 85 additions & 0 deletions src/main/kotlin/racingcar/service/CarPlayGameImpl.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package racingcar.service

import camp.nextstep.edu.missionutils.Console
import camp.nextstep.edu.missionutils.Randoms
import racingcar.domain.Player
import kotlin.math.max

class CarPlayGameImpl(
private val printGame: PrintGame
) : PlayGame {

private var round: Int = 0
private var players: List<Player> = listOf()
override fun initGame() {
printGame.printInit()
val inputPlayers = Console.readLine()
val names = inputPlayers.split(",")
initPlayers(names)
printGame.tryCount()
round = Console.readLine().toInt()
}

override fun initPlayers(names: List<String>) {
players = names.map { name ->
validCheck(name)
Player.toPlayer(name)
}
}

override fun playGame() {
initGame()

for (loop in 0..<round) {
playRound()
println()
}

val winnerCount = getCurrentWinnerCount()

endGame(winnerCount)
}

override fun playRound() {
players.forEach { player ->
// 1 : go 0 : stop
if (canIGo()) player.addWinCount()
printGame.printGame(player.name, player.winCount)
}
}

override fun endGame(winnerCount: Int) {
val winnerList = mutableListOf<String>()
players.forEach { player ->
if (player.winCount == winnerCount) winnerList.add(player.name)
}

printGame.printWinner(winnerList)
}

// 5자 이하의 이름인지 확인하는 메서드
private fun validCheck(name: String) {
require(name.length < 6) {
"이름의 길이는 5자이하 여야 합니다."
}
}

// 랜덤으로 값을 뽑아 전진이 가능한지 확인하는 메서드
// 4 이상 부터 전진한다.
private fun canIGo(): Boolean {
return Randoms.pickNumberInRange(0, 9) > RUN_OR_STOP_STANDARD
}

// 현재 가장 많이 전진한 사람의 count를 가져오는 메서드
private fun getCurrentWinnerCount(): Int {
var maxGoCount = 0

players.forEach { player -> maxGoCount = max(maxGoCount, player.winCount) }

return maxGoCount
}

companion object {
const val RUN_OR_STOP_STANDARD = 3
}
}
29 changes: 29 additions & 0 deletions src/main/kotlin/racingcar/service/CarPrintGame.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package racingcar.service


class CarPrintGame : PrintGame {
override fun printInit() {
println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)")
}

override fun tryCount() {
println("시도할 횟수는 몇 회인가요?")
}

override fun printGame(playerName: String, goCount: Int) {
print("$playerName : ")
for (loop in 0..<goCount) {
print("-")
}
println()
}

override fun printWinner(names: List<String>) {
print("최종 우승자 : ")
//마지막에서 한명을 제외하고 ", " 형식으로 뽑기위해서 -2를 사용한다
for (loop in 0..<names.lastIndex) {
print("${names[loop]}, ")
}
print(names.last())
}
}
18 changes: 18 additions & 0 deletions src/main/kotlin/racingcar/service/PlayGame.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package racingcar.service

interface PlayGame {
// 게임 셋팅
fun initGame()

// 플레이어 값 초기화
fun initPlayers(names: List<String>)

// 게임의 전체 진행을 위한 메서드
fun playGame()

// 게임의 각 라운드를 위한 메서드
fun playRound()

// 게임 종료시 호출될 메서드
fun endGame(winnerCount: Int)
}
15 changes: 15 additions & 0 deletions src/main/kotlin/racingcar/service/PrintGame.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package racingcar.service

interface PrintGame {
//초기화 시 프린트 하는 메서드
fun printInit()

//시도할 횟수에 대한 프린트 하는 메서드
fun tryCount()

// 게임 진행시 결과를 프린트 하는 메서드
fun printGame(playerName: String, goCount: Int)

// 게임 승리자를 프린트 하는 메서드
fun printWinner(names: List<String>)
}
87 changes: 82 additions & 5 deletions src/test/kotlin/racingcar/ApplicationTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ class ApplicationTest : NsTest() {
@Test
fun `전진 정지`() {
assertRandomNumberInRangeTest(
{
run("pobi,woni", "1")
assertThat(output()).contains("pobi : -", "woni : ", "최종 우승자 : pobi")
},
MOVING_FORWARD, STOP
{
run("pobi,woni", "1")
assertThat(output()).contains("pobi : -", "woni : ", "최종 우승자 : pobi")
},
MOVING_FORWARD, STOP
)
}

Expand All @@ -26,6 +26,83 @@ class ApplicationTest : NsTest() {
}
}

@Test
fun `단독 우승`() {
assertRandomNumberInRangeTest(
{
run("pobi,woni", "2")
assertThat(output()).contains("pobi : ", "woni : --", "최종 우승자 : woni")
},
STOP, MOVING_FORWARD, STOP, MOVING_FORWARD
)
}

@Test
fun `혼자 경기한 경우`() {
assertRandomNumberInRangeTest(
{
run("pobi", "2")
assertThat(output()).contains("pobi : ", "최종 우승자 : pobi")
},
STOP, STOP
)
}

@Test
fun `1, 3번째가 우승한 경우`() {
assertRandomNumberInRangeTest(
{
run("pobi,woni,rilla", "3")
assertThat(output()).contains("pobi : --", "woni : ", "rilla : --", "최종 우승자 : pobi, rilla")
},
MOVING_FORWARD, STOP, MOVING_FORWARD, STOP, STOP, MOVING_FORWARD, MOVING_FORWARD, STOP, STOP
)
}

@Test
fun `공동 우승`() {
assertRandomNumberInRangeTest(
{
run("pobi,woni", "1")
assertThat(output()).contains("pobi : -", "woni : -", "최종 우승자 : pobi, woni")
},
MOVING_FORWARD, MOVING_FORWARD
)
}

@Test
fun `모두 전진 실패`() {
assertRandomNumberInRangeTest(
{
run("pobi,woni", "3")
assertThat(output()).contains("pobi : ", "woni : ", "최종 우승자 : pobi, woni")
},
STOP, STOP, STOP, STOP, STOP, STOP
)
}

@Test
fun `모두 전진 성공`() {
assertRandomNumberInRangeTest(
{
run("pobi,woni", "2")
assertThat(output()).contains("pobi : --", "woni : --", "최종 우승자 : pobi, woni")
},
MOVING_FORWARD, MOVING_FORWARD, MOVING_FORWARD, MOVING_FORWARD
)
}

@Test
fun `전진 스탑 스탑 전진`() {
assertRandomNumberInRangeTest(
{
run("pobi,woni", "2")
assertThat(output()).contains("pobi : -", "woni : -", "최종 우승자 : pobi, woni")
},
MOVING_FORWARD, STOP, STOP, MOVING_FORWARD
)
}

public override fun runMain() {
main()
}
Expand Down