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

[자동차 경주] 이진희 미션 제출합니다. #740

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
23 changes: 23 additions & 0 deletions __tests__/RacingCarGameTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import App from '../src/App.js';

const app = new App();

describe('자동차 게임 입력값 유효성 검사 테스트', () => {
test('경주할 자동차 이름을 하나만 입력했을 때 false를 반환하는지 테스트', () => {
const carNameInput = ['pobi'];
const result = app.isValidCarNamesInput(carNameInput);
expect(result).toEqual(false);
});

test('게임 시도 횟수를 0으로 입력했을 때 false를 반환하는지 테스트', () => {
const gameCountInput = 0;
const result = app.isValidGameCountInput(gameCountInput);
expect(result).toEqual(false);
});

test('게임 시도 횟수를 1보다 큰 숫자로 입력했을 때 true를 반환하는지 테스트', () => {
const gameCountInput = 3;
const result = app.isValidGameCountInput(gameCountInput);
expect(result).toEqual(true);
});
});
37 changes: 37 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## 🖥️ 기능 구현 목록

### 자동차 이름 입력

- 게임 시작 메시지를 출력한다.
- "경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)" 메시지 출력
- 경주할 자동차 이름을 입력받는다.
- 이름은 쉼표(,) 기준으로 구분
- 이름은 5자 이하만 가능
- 잘못된 형식의 입력인 경우 에러 처리
- throw문을 사용해 "[ERROR]"로 시작하는 메시지를 가지는 예외를 발생시킨 후, 애플리케이션은 종료되어야 한다.

### 게임 시도 횟수 입력

- 시도할 횟수를 묻는 메시지를 출력한다.
- "시도할 횟수는 몇 회인가요?" 메시지 출력
- 시도할 횟수를 입력받는다.
- 0보다 큰 숫자
- 숫자가 아닌 경우 에러 처리

### 자동차 게임 실행

- 자동차마다 0에서 9 사이에서 무작위 값을 구한다.
- 무작위 값이 4이상일 경우에만, 전진 ⭕️
- 게임 시도 횟수만큼 이 같은 과정을 반복한다.

### 각 차수별 실행 결과

- 각 차수별 실행 결과를 출력한다.
- 자동차 이름도 같이 출력
- 예를 들어, jinhee : -----

### 최종 우승자 출력

- 자동차 경주 게임을 완료한 후 누가 우승했는지 알려준다.
- 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분
- 최종 우승자를 출력한 후, 게임을 종료한다.
108 changes: 107 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,111 @@
import { Console, Random } from '@woowacourse/mission-utils';

class App {
async play() {}
async play() {
this.askCarNames();
const racingCarsMap = await this.inputCarNames();

this.askGameCount();
const gameCount = await this.inputGameCount();

this.startRacingCarGame(racingCarsMap, gameCount);
}

askCarNames() {
Console.print(
'경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)'
);
}

async inputCarNames() {
const carNames = await Console.readLineAsync('');
const carNameList = carNames.split(',').map((carName) => carName.trim());

if (!this.isValidCarNamesInput(carNameList)) {
throw new Error('[ERROR] 잘못된 입력값입니다.');
}

const racingCarsMap = new Map();
carNameList.forEach((racingCar) => {
racingCarsMap.set(racingCar, '');
});

return racingCarsMap;
}

askGameCount() {
Console.print('시도할 횟수는 몇 회인가요?');
}

async inputGameCount() {
const gameCount = await Console.readLineAsync('');
const trimmedGameCount = gameCount.trim();

if (!this.isValidGameCountInput(trimmedGameCount)) {
throw new Error('[ERROR] 숫자가 잘못된 형식입니다.');
}

return parseInt(trimmedGameCount);
}

async startRacingCarGame(racingCarsMap, gameCount) {
Console.print('\n실행 결과');

for (let i = 0; i < gameCount; i++) {
await this.moveRacingCarRandomDistance(racingCarsMap);
await this.printRacingCarGameResult(racingCarsMap, gameCount);
}
const racingCarWinner = this.getRacingCarWinner(racingCarsMap);

Console.print(`최종 우승자 : ${racingCarWinner}`);
}

async moveRacingCarRandomDistance(racingCarsMap) {
[...racingCarsMap.keys()].forEach((racingCar) => {
const randomDistance = Random.pickNumberInRange(0, 9);
if (randomDistance >= 4) {
racingCarsMap.set(racingCar, racingCarsMap.get(racingCar) + '-');
}
});
}

async printRacingCarGameResult(racingCarsMap) {
for (const [racingCar, distance] of racingCarsMap.entries()) {
await Console.print(`${racingCar} : ${distance}`);
}
Console.print('');
}

getRacingCarWinner(racingCarsMap) {
const longestDistance = [...racingCarsMap.values()].reduce(
(longestDistance, currentDistance) =>
longestDistance.length > currentDistance.length
? longestDistance
: currentDistance
);

const racingCarWinner = [...racingCarsMap.keys()].filter(
(car) => racingCarsMap.get(car) === longestDistance
);

return racingCarWinner.join(',');
}

isValidCarNamesInput(carNameList) {
if (carNameList.length === 1) return false;

for (let carName of carNameList) {
if (carName.length === 0 || carName.length > 5) return false;
}

return true;
}

isValidGameCountInput(gameCount) {
if (isNaN(gameCount) || gameCount <= 0) return false;

return true;
}
}

export default App;