Skip to content
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
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,19 @@
# javascript-racingcar-precourse
1. 경주할 자동차 이름을 입력받는다.
2. 자동차 이름은 쉼표(,)를 기준으로 분리
3. 자동차 이름은 5자 이하인지 검증한다.(초과 시 Error)
4. 시도할 횟수를 입력받는다.
5. 시도할 횟수가 유효한 숫자인지 검증한다.(숫자 아님/음수/0등이 적힐 경우 Error)
6. 사용자가 잘못된 값을 입력할 경우 [Error] 메시지와 함께 Error를 발생시킨다.

7. 주어진 횟수만큼 게임을 반복 실행한다.
8. 자동차별로 0에서 9사이의 무작위 값을 구한다.
9. 무작위 값이 4 이상일 경우 해당 자동차는 전진한다.
10. 각 차수별 실행 결과를 자동차 이름과 전진거리(-)로 출력한다.
11. 매 차수 실행 사이에 빈 줄을 출력하여 구분한다.

12. 경주 게임 완료 후 가장 많이 전진한 거리를 계산한다.
13. 최대 전진 거리를 가진 자동차들을 우승자로 선정한다.
14. 우승자가 한 명일 경우 우승자 이름을 출력한다.
15. 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분하여 출력한다.
16. 최종 결과를 "최종 우승자:[이름]" 형식으로 출력한다.
32 changes: 30 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,33 @@
import { Console } from "@woowacourse/mission-utils";
import RacingGame from "./RacingGame.js"; // RacingGame 가져오기

class App {
async run() {}
async run() {
const game = new RacingGame();

try {
// 1.1, 1.4번 기능을 위해 사용자 입력 받기
const carNames = await Console.readLineAsync("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)\n");
game.setCars(carNames);

const attemptsInput = await Console.readLineAsync("시도할 횟수는 몇 회인가요?\n");
game.setAttempts(attemptsInput);

// 2.4번 기능: 실행 결과 헤더 출력
Console.print("\n실행 결과");

// 2.1번 기능: 경주 시작
game.startRace();

// 3.1~3.5번 기능: 우승자 출력
const winners = game.getWinners();
Console.print(`최종 우승자 : ${winners.join(', ')}`);

} catch (error) {
// 1.6번 기능: [ERROR] 출력 후 종료
Console.print(error.message);
}
}
}

export default App;
export default App;
30 changes: 30 additions & 0 deletions src/Car.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
class Car {
constructor(name) {
// 1.3번 기능 구현: 자동차 이름 5자 이하 검증
if (name.length > 5) {
throw new Error("[ERROR] 자동차 이름은 5자 이하만 가능합니다.");
}
if (name.length === 0) {
throw new Error("[ERROR] 자동차 이름은 공백일 수 없습니다.");
}

this.name = name;
this.position = 0;
}
// 이어서 전진 로직(9)이 들어갈 메서드
move() {
// MissionUtils.Random.pickNumberInRange(0, 9)를 사용한다고 가정
const randomNumber = MissionUtils.Random.pickNumberInRange(0, 9);

if (randomNumber >= 4) {
this.position += 1; // 9번: 4 이상일 경우 전진
}
}

// 이어서 출력 로직(10)이 들어갈 메서드
getDisplay() {
return `${this.name} : ${'-'.repeat(this.position)}`;
}
}

export default Car;
76 changes: 76 additions & 0 deletions src/RacingGame.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// src/RacingGame.js

import { Random } from "@woowacourse/mission-utils";
import Car from "./Car.js";

class RacingGame {
constructor() {
this.cars = [];
this.attempts = 0;
}

// 1, 2번 기능이 들어갈 메서드
setCars(carNamesInput) {
const names = carNamesInput.split(',');

if (names.some(name => name.length === 0)) {
throw new Error("[ERROR] 자동차 이름은 공백일 수 없습니다.");
}

// 3번 검증은 Car 생성자에서 처리됨
this.cars = names.map(name => new Car(name.trim()));
}

// 4번 기능이 들어갈 메서드
setAttempts(attemptsInput) {
const attempts = parseInt(attemptsInput.trim(), 10);

// 5번 기능: 유효한 숫자인지 검증
if (isNaN(attempts)) {
throw new Error("[ERROR] 시도 횟수는 숫자여야 합니다.");
}
if (attempts <= 0) {
throw new Error("[ERROR] 시도 횟수는 1회 이상이어야 합니다.");
}

this.attempts = attempts;
}

// 5번 기능이 들어갈 메서드
startRace() {
for (let i = 0; i < this.attempts; i++) {
this.playRound();
this.printRoundResult();
}
}
// 라운드 처리 로직 분리 (인덴트 깊이 2를 넘지 않도록)
playRound() {
this.cars.forEach(car => car.move());
}

// 10, 11번 기능 구현: 라운드별 결과 출력
printRoundResult() {
this.cars.forEach(car => {
// car.getDisplay()는 Car.js에 구현되어 있습니다.
Console.print(car.getDisplay());
});
Console.print(""); // 11번: 차수별 실행 사이에 빈 줄 출력
}

// 12번 ~ 15번 기능 구현: 우승자 결정 및 반환
getWinners() {
// 12. 경주 게임 완료 후 가장 많이 전진한 거리를 계산한다.
const maxPosition = this.cars.reduce((max, car) => {
// car.position은 Car 클래스에 저장된 전진 거리
return Math.max(max, car.position);
}, 0); // 초기 최대 거리는 0

// 13. 최대 전진 거리를 가진 자동차들을 우승자로 선정한다.
const winners = this.cars.filter(car => car.position === maxPosition);

// 14. 15. 우승자 이름만 추출 (한 명이든 여러 명이든 쉼표로 구분할 이름 리스트 준비)
return winners.map(car => car.name);
}
}

export default RacingGame;