From 7fcba44a0c732ed3bf12f3f1d6724b1b0132b91a Mon Sep 17 00:00:00 2001 From: ParkHyeonkyu <162525426+ParkHyeonkyu@users.noreply.github.com> Date: Fri, 14 Feb 2025 00:56:39 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20README=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 구현할 기능 목록 정리 --- README.md | 10 ++++++++++ src/App.js | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e078fd4..70ae259 100644 --- a/README.md +++ b/README.md @@ -1 +1,11 @@ # javascript-racingcar-precourse + +# 기능구현 +1. 자동차 선수 구현 +2. 자동차 게임 실행 +3. 예외 처리 + +# 예외 처리 +1. 자동차 이름이 5자를 초과하는 경우 +2. 무작위 값이 범위 밖인 경우 +3. 이동 입력이 잘못된 경우 \ No newline at end of file diff --git a/src/App.js b/src/App.js index 091aa0a..0d90822 100644 --- a/src/App.js +++ b/src/App.js @@ -2,4 +2,4 @@ class App { async run() {} } -export default App; +export default App; \ No newline at end of file From 351d9201e6509a3d703e33b1de433861e6e1baf3 Mon Sep 17 00:00:00 2001 From: ParkHyeonkyu <162525426+ParkHyeonkyu@users.noreply.github.com> Date: Fri, 14 Feb 2025 01:16:40 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20Car=20class=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Car 클래스 구현 --- src/App.js | 32 +++++++++++++++++++++++++++++++- src/index.js | 2 +- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/App.js b/src/App.js index 0d90822..07ad3f8 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,35 @@ +import { Console, Random } from "@woowacourse/mission-utils"; + +class Car { + constructor(name) { + this.name = name; + this.position = 0; + } + + move() { + const randomNumber = Random.pickNumberInRange(0,9); + if (randomNumber >= 4) { + this.position++; + } + } + + get nowPosition() { + return "-".repeat(this.position); + } +} + class App { - async run() {} + async play() { + try{ + const carName = await Console.readLineAsync(`자동차 이름을 입력하세요.: \n`); + const car = new Car(carName); + Console.print("자동차 이름: " + car.name); + car.move(); + Console.print(car.position); + }catch(error){ + throw error; + } + } } export default App; \ No newline at end of file diff --git a/src/index.js b/src/index.js index 02a1d38..93eda32 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,4 @@ import App from "./App.js"; const app = new App(); -await app.run(); +await app.play(); From 275c9069fac7023351717a805066a9520ebddeb4 Mon Sep 17 00:00:00 2001 From: ParkHyeonkyu <162525426+ParkHyeonkyu@users.noreply.github.com> Date: Fri, 14 Feb 2025 02:30:47 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20RacingGame=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Car 클래스를 배열로 받는 RacingGame 클래스 구현 --- README.md | 7 ++++--- src/App.js | 43 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 70ae259..8e625de 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ 3. 예외 처리 # 예외 처리 -1. 자동차 이름이 5자를 초과하는 경우 -2. 무작위 값이 범위 밖인 경우 -3. 이동 입력이 잘못된 경우 \ No newline at end of file +1. 자동차 이름 + 1-1. 5자를 초과하는 경우 + 1-2. 동일한 이름이 존재하는 경우 +2. 이동 입력이 잘못된 경우 \ No newline at end of file diff --git a/src/App.js b/src/App.js index 07ad3f8..5855f99 100644 --- a/src/App.js +++ b/src/App.js @@ -2,30 +2,59 @@ import { Console, Random } from "@woowacourse/mission-utils"; class Car { constructor(name) { + if (name.length > 5) { + throw new Error("이름은 5자 이하만 가능합니다.") + } this.name = name; this.position = 0; } - move() { const randomNumber = Random.pickNumberInRange(0,9); if (randomNumber >= 4) { this.position++; } } - get nowPosition() { return "-".repeat(this.position); } } +class RacingGame { + constructor(carNames, counts) { + this.cars = carNames.split(",").map((name) => new Car(name)); + this.counts = counts; + } + + gameStart() { + for (let i = 0; i < this.counts; i++) { + Console.print(`\n${i + 1}차 시도`); + this.cars.forEach(car => { + car.move(); + Console.print(`${car.name} : ${car.nowPosition}`); + }); + } + } + + get winner(){ + const maxPosition = Math.max(...this.cars.map((car) => car.position)); + const winners = this.cars.filter((car) => car.position === maxPosition); + return winners.map((winner) => winner.name).join(", "); + } + +} + class App { async play() { try{ - const carName = await Console.readLineAsync(`자동차 이름을 입력하세요.: \n`); - const car = new Car(carName); - Console.print("자동차 이름: " + car.name); - car.move(); - Console.print(car.position); + const cars = await Console.readLineAsync(`경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분) \n`); + if(!cars){ + throw new Error("자동차 이름을 최소 1개 입력하세요.") + } + const inputCounts = await Console.readLineAsync("시도할 회수는 몇회인가요?") + const counts = parseInt(inputCounts); + const game = new RacingGame(cars, counts); + game.gameStart(); + Console.print("최종 우승자 : " + game.winner); }catch(error){ throw error; } From 390a8fbc14bb380413b2423af2561953bb7acf0a Mon Sep 17 00:00:00 2001 From: ParkHyeonkyu <162525426+ParkHyeonkyu@users.noreply.github.com> Date: Fri, 14 Feb 2025 11:23:35 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20=EC=98=88=EC=99=B8=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 자동차 이름, 시도 횟수 관련 예외처리 구현 --- README.md | 3 ++- src/App.js | 23 ++++++++++++++++++++--- src/index.js | 2 +- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 8e625de..c7763c1 100644 --- a/README.md +++ b/README.md @@ -8,5 +8,6 @@ # 예외 처리 1. 자동차 이름 1-1. 5자를 초과하는 경우 - 1-2. 동일한 이름이 존재하는 경우 + 1-2. 이름이 공백인 경우 + 1-3. 중복되는는 이름이 존재하는 경우 2. 이동 입력이 잘못된 경우 \ No newline at end of file diff --git a/src/App.js b/src/App.js index 5855f99..bb1ebe0 100644 --- a/src/App.js +++ b/src/App.js @@ -2,6 +2,9 @@ import { Console, Random } from "@woowacourse/mission-utils"; class Car { constructor(name) { + if (name.length < 1) { + throw new Error("이름은 최소 1자 이상입니다.") + } if (name.length > 5) { throw new Error("이름은 5자 이하만 가능합니다.") } @@ -21,7 +24,15 @@ class Car { class RacingGame { constructor(carNames, counts) { - this.cars = carNames.split(",").map((name) => new Car(name)); + + const nameArray = carNames.split(",").map((name) => name.trim()); + + const nameCheck = new Set(nameArray); + if(nameCheck.size !== nameArray.length) { + throw new Error("중복된 이름이 있습니다. 모든 자동차 이름은 고유해야 합니다.") + } + + this.cars = nameArray.map((name) => new Car(name)); this.counts = counts; } @@ -44,17 +55,23 @@ class RacingGame { } class App { - async play() { + async run() { try{ const cars = await Console.readLineAsync(`경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분) \n`); if(!cars){ - throw new Error("자동차 이름을 최소 1개 입력하세요.") + throw new Error("이름이 입력되지 않았습니다.") } const inputCounts = await Console.readLineAsync("시도할 회수는 몇회인가요?") + if(inputCounts < 1){ + throw new Error("최소 1회 이상 시도해야 합니다.") + } const counts = parseInt(inputCounts); + const game = new RacingGame(cars, counts); game.gameStart(); + Console.print("최종 우승자 : " + game.winner); + }catch(error){ throw error; } diff --git a/src/index.js b/src/index.js index 93eda32..02a1d38 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,4 @@ import App from "./App.js"; const app = new App(); -await app.play(); +await app.run(); From c67a9a6e203b46ffee4ec2dda965b3149c2de8ea Mon Sep 17 00:00:00 2001 From: ParkHyeonkyu <162525426+ParkHyeonkyu@users.noreply.github.com> Date: Fri, 14 Feb 2025 11:42:36 +0900 Subject: [PATCH 5/6] =?UTF-8?q?refactor:=20playRound=20=ED=95=A8=EC=88=98?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20test=20=ED=86=B5=EA=B3=BC?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 복잡한 구조를 피하기 위해 gameStart메서드의 기능을 playRound로 분리하고, 코드가 ApplicationTest.js를 통과할 수 있도록 수정했습니다. --- src/App.js | 56 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/src/App.js b/src/App.js index bb1ebe0..296aa14 100644 --- a/src/App.js +++ b/src/App.js @@ -3,16 +3,18 @@ import { Console, Random } from "@woowacourse/mission-utils"; class Car { constructor(name) { if (name.length < 1) { - throw new Error("이름은 최소 1자 이상입니다.") + //이름은 최소 1자 이상입니다. + throw new Error("[ERROR]"); } if (name.length > 5) { - throw new Error("이름은 5자 이하만 가능합니다.") + //이름은 5자 이하만 가능합니다. + throw new Error("[ERROR]"); } this.name = name; this.position = 0; } move() { - const randomNumber = Random.pickNumberInRange(0,9); + const randomNumber = Random.pickNumberInRange(0, 9); if (randomNumber >= 4) { this.position++; } @@ -24,46 +26,57 @@ class Car { class RacingGame { constructor(carNames, counts) { - const nameArray = carNames.split(",").map((name) => name.trim()); const nameCheck = new Set(nameArray); - if(nameCheck.size !== nameArray.length) { - throw new Error("중복된 이름이 있습니다. 모든 자동차 이름은 고유해야 합니다.") + if (nameCheck.size !== nameArray.length) { + throw new Error( + //중복된 이름이 있습니다. 모든 자동차 이름은 고유해야 합니다. + "[ERROR]" + ); } this.cars = nameArray.map((name) => new Car(name)); this.counts = counts; } + playRound() { + this.cars.forEach((car) => { + car.move(); + Console.print(`${car.name} : ${car.nowPosition}`); + }); + } + gameStart() { for (let i = 0; i < this.counts; i++) { Console.print(`\n${i + 1}차 시도`); - this.cars.forEach(car => { - car.move(); - Console.print(`${car.name} : ${car.nowPosition}`); - }); + this.playRound(); } } - get winner(){ + get winner() { const maxPosition = Math.max(...this.cars.map((car) => car.position)); const winners = this.cars.filter((car) => car.position === maxPosition); return winners.map((winner) => winner.name).join(", "); } - } class App { async run() { - try{ - const cars = await Console.readLineAsync(`경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분) \n`); - if(!cars){ - throw new Error("이름이 입력되지 않았습니다.") + try { + const cars = await Console.readLineAsync( + `경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분) \n` + ); + if (!cars) { + //이름이 입력되지 않았습니다. + throw new Error("[ERROR]"); } - const inputCounts = await Console.readLineAsync("시도할 회수는 몇회인가요?") - if(inputCounts < 1){ - throw new Error("최소 1회 이상 시도해야 합니다.") + const inputCounts = await Console.readLineAsync( + "시도할 회수는 몇회인가요?" + ); + if (inputCounts < 1) { + //최소 1회 이상 시도해야 합니다. + throw new Error("[ERROR]"); } const counts = parseInt(inputCounts); @@ -71,11 +84,10 @@ class App { game.gameStart(); Console.print("최종 우승자 : " + game.winner); - - }catch(error){ + } catch (error) { throw error; } } } -export default App; \ No newline at end of file +export default App; From ba0db457a88aaa1d7f230fd7fbee2a0885e88821 Mon Sep 17 00:00:00 2001 From: ParkHyeonkyu <162525426+ParkHyeonkyu@users.noreply.github.com> Date: Fri, 14 Feb 2025 15:22:48 +0900 Subject: [PATCH 6/6] =?UTF-8?q?refactor:=20setTimeout=EC=9D=84=20=ED=99=9C?= =?UTF-8?q?=EC=9A=A9=ED=95=9C=20delay=ED=95=A8=EC=88=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 게임의 시도를 명확하게 하기 위해 setTimeout을 활용한 delay함수를 추가함 --- src/App.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/App.js b/src/App.js index 296aa14..48b84f0 100644 --- a/src/App.js +++ b/src/App.js @@ -47,10 +47,15 @@ class RacingGame { }); } - gameStart() { + async delay(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } + + async gameStart() { for (let i = 0; i < this.counts; i++) { Console.print(`\n${i + 1}차 시도`); this.playRound(); + await this.delay(1000); } } @@ -81,7 +86,7 @@ class App { const counts = parseInt(inputCounts); const game = new RacingGame(cars, counts); - game.gameStart(); + await game.gameStart(); Console.print("최종 우승자 : " + game.winner); } catch (error) {