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
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,32 @@
# javascript-racingcar-precourse
# 🚗

## 자동차 경주 기능 구현 목록

### 1. 기본 입출력
- 자동차 이름 입력용 안내문 출력
- 자동차 이름 입력 받기
- 시도 횟수 입력용 안내문 출력
- 시도할 횟수 입력 받기

### 2. 데이터 처리 및 validation
- 자동차 이름 분리(,) / 배열 생성
- 자동차 이름 validation (5자 이하)
- 시도 횟수 validation (NaN)

### 3. 수행 로직
- 자동차 객체 생성 (이름, 포지션)
- 라운드 진행 로직 구현 (시도 횟수 만큼 반복)
- 전진/멈춤 로직 구현
- mission-utils 활용 무작위 값 생성
- 4 이상일 경우 전진

### 4. 출력
- Console.print 사용하여 라운드별 실행 결과 출력
- 자동차 객체 중 가장 높은 전진 횟수를 가진 객체 선정 (공동 우승 가능)
- 우승자 출력

### 5. 실행
- Jest 활용 테스트 코드 진행
- 예외 처리
- 오류 문제 해결

2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

111 changes: 110 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,114 @@
import * as MissionUtils from '@woowacourse/mission-utils';
import Car from './Car.js';


class App {
async run() {}
async run() {

const carNamesInput = await this.getCarNames();
const carNames = this.parseAndValidateCarNames(carNamesInput)

const tryCountInput = await this.getTryCount();
const tryCount = this.parseAndValidateTryCount(tryCountInput);

const cars = carNames.map((name) => new Car(name));

this.#runRace(cars, tryCount);

const winnerNames = this.#findWinners(cars);
this.#printWinners(winnerNames);

}

async getCarNames() {
const input = await MissionUtils.Console.readLineAsync(
"경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"
);
return input;
}

async getTryCount() {
const input = await MissionUtils.Console.readLineAsync(
"시도할 회수는 몇회인가요?"
);
return input;
}

parseAndValidateCarNames(input) {

const names = input.split(",").map((name) => name.trim());


if (names.some((name) => name.length > 5)) {
throw new Error("[ERROR] 자동차 이름은 5자 이하만 가능합니다.");
}


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


const uniqueNames = new Set(names);
if (uniqueNames.size !== names.length) {
throw new Error("[ERROR] 자동차 이름은 중복될 수 없습니다.");
}

return names;
}

parseAndValidateTryCount(input) {
const count = Number(input);

if (isNaN(count)) {
throw new Error("[ERROR] 시도 횟수는 숫자여야 합니다.");
}

return count;

}

#runRace(cars, tryCount) {
MissionUtils.Console.print("\n실행 결과");

for (let i = 0; i < tryCount; i++) {

for (const car of cars) {
car.move();
}


this.#printRoundResult(cars);

MissionUtils.Console.print("");
}
}

#printRoundResult(cars) {
cars.forEach((car) => {
const positionsString = '-'.repeat(car.getPosition());

MissionUtils.Console.print(
`${car.getName()} : ${positionsString}`
);
});
};

#findWinners(cars) {
const positions = cars.map((car) => car.getPosition());
const maxPosition = Math.max(...positions);
const winners = cars.filter(
(car) => car.getPosition() === maxPosition
);
return winners.map((winner) => winner.getName());
}

#printWinners(winnerNames) {
const nameString = winnerNames.join(', ');
MissionUtils.Console.print(
`최종 우승자 : ${nameString}`
);
}
}

export default App;
32 changes: 32 additions & 0 deletions src/Car.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//constructor(#name)으로 이름을 받고 position = 0 으로 초기화
//App에서 car.move로 명령 받으면 Car에서 스스로 랜덤 값 뽑아서 position 증가

import { MissionUtils } from "@woowacourse/mission-utils";

class Car {
#name;
#position;

constructor(name) {
this.#name = name;
this.#position = 0;
}

move() {
const randomNumber = MissionUtils.Random.pickNumberInRange(0,9);

if (randomNumber >= 4) {
this.#position += 1;
}
}

getName() {
return this.#name;
}

getPosition() {
return this.#position;
}
}

export default Car;
14 changes: 12 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
import { MissionUtils } from "@woowacourse/mission-utils";
import App from "./App.js";

const app = new App();
await app.run();
class Main {
async run() {
const app = new App();
await app.run();
} catch (error) {
MissionUtils.Console.print(error.message);
}
}

const main = new Main();
main.run();