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

[자동차 경주] 김민경 미션 제출합니다. #751

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 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
26 changes: 26 additions & 0 deletions __tests__/ValidatorTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import App from "../src/App.js";
import { ERROR } from "../src/message.js";

const mockFn = jest.fn();

mockFn(["woowacourse"]);
mockFn(["FuBao"]);

describe("조건 검증 테스트", () => {
const app = new App();

// test("자동차 이름이 5자를 초과할 경우 에러 발생", () => {
// expect(mockFn.mock.calls[0].length).toBeGreaterThanOrEqual(6);
// });
test("자동차 이름이 5자 이하일 경우 에러 발생하지 않음", () => {
expect(mockFn.mock.calls[1].length).toBeLessThanOrEqual(5);
expect(mockFn.mock.calls.length).toBe(2);
});

test("시도할 횟수가 숫자가 아닐 경우 에러 발생", () => {
expect(() => app.validateNumber(NaN)).toThrow(ERROR.ATTEMPT_COUNT);
});
test("시도할 횟수가 숫자인 경우 에러 발생하지 않음", () => {
expect(() => app.validateNumber(5)).not.toThrow();
});
});
36 changes: 36 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# 미션 - 자동차 경주

## 🕹 기능 요구 사항(구현할 기능 목록)

- [x] 게임에 사용되는 message 작성

### ⌨️ 사용자 입력 받기

- [x] 경주할 자동차 이름 받기(쉼표(,) 기준으로 구분, 5자 이하)
- [x] 시도할 횟수 받기
- [x] 잘못된 값 입력 시 `throw`문을 사용해 "[ERROR]"로 시작하는 메시지를 가지는 예외를 발생 후 앱 종료

### 🚘 게임 판단

- [x] 전진하는 조건: 0~9 사이 무작위 값을 생성 후 무작위 값이 4 이상
- [x] 전진: 자동차 이름과 함께 출력
- [x] 각 차수별 실행 결과 출력

### 🎮 게임 완료

- [x] 우승자 발표
- [x] 우승자가 여러 명일 경우 쉼표(,)로 구분

## 🖥 프로그래밍 요구 사항

- [x] `Node.js` `18.17.1` 버전에서 실행 가능
- [x] `App.js`의 `play` 메서드에서 프로그램 실행
- [x] `ApplicationTest` 의 모든 테스트 성공
- [x] indent(인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현
- [ ] Jest를 이용하여 내가 정리한 기능 목록이 정상 동작함을 테스트 코드로 확인
- [x] `@woowacourse/mission-utils`에서 제공하는 `Random` 및 `Console` API를 사용하여 구현

## 📓 과제 진행 요구 사항

- [x] 저장소를 Fork & Clone
- [x] 구현할 기능 목록 정리
88 changes: 87 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,91 @@
import { Random, Console } from "@woowacourse/mission-utils";
import { GAME, ERROR } from "./message";

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

moveForward = () => {
const randomNumber = Random.pickNumberInRange(0, 9);
if (randomNumber >= 4) {
this.position += 1;
}
};
}

class App {
async play() {}
constructor() {
this.cars = [];
}

validateCarName = (carName) => {
if (carName.length > 5) {
throw new Error(ERROR.CAR_NAME);
}
};
validateNumber = (attemptNumber) => {
if (isNaN(attemptNumber) || attemptNumber <= 0) {
throw new Error(ERROR.ATTEMPT_COUNT);
}
};

getCarsName = async () => {
const carsName = await Console.readLineAsync(GAME.GET_CAR_NAME);
const carsNameArray = carsName.split(",");
carsNameArray.forEach((carName) => {
this.validateCarName(carName);
this.cars.push(new Car(carName));
});
};

getAttemptCount = async () => {
const attemptCount = await Console.readLineAsync(GAME.GET_ATTEMPT_COUNT);
const attemptNumber = Number(attemptCount);
this.validateNumber(attemptNumber);

return attemptNumber;
};

moveAllCars = () => {
Console.print(GAME.PRINT_EXECUTION_RESULT);
this.cars.forEach((car) => {
car.moveForward();
Console.print(`${car.name} : ${"-".repeat(car.position)}`);
});
};

selectWinnerByRace = () => {
const maxCarPosition = Math.max(...this.cars.map((car) => car.position));
const winnerCars = this.cars.filter(
(car) => car.position === maxCarPosition
);
return winnerCars.map((car) => car.name);
};

printWinners = () => {
const winners = this.selectWinnerByRace();
if (winners.length > 1) {
Console.print(`${GAME.WINNER}${winners.join(", ")}`);
} else {
Console.print(`${GAME.WINNER}${winners}`);
}
};

racingGame = (attemptCount) => {
while (attemptCount > 0) {
this.moveAllCars();
attemptCount -= 1;
}
this.printWinners();
};

async play() {
await this.getCarsName();
const attemptCount = await this.getAttemptCount();
this.racingGame(attemptCount);
}
}

export default App;
12 changes: 12 additions & 0 deletions src/message.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const GAME = {
GET_CAR_NAME:
"경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)\n",
GET_ATTEMPT_COUNT: "시도할 횟수는 몇 회인가요?\n",
WINNER: "최종 우승자 : ",
PRINT_EXECUTION_RESULT: "실행 결과",
};

export const ERROR = {
CAR_NAME: "[ERROR] 자동차 이름은 5자 이하로 입력 가능합니다.",
ATTEMPT_COUNT: "[ERROR] 숫자만 입력 가능합니다.",
};