diff --git a/__tests__/ValidatorTest.js b/__tests__/ValidatorTest.js new file mode 100644 index 000000000..dd03fbe5e --- /dev/null +++ b/__tests__/ValidatorTest.js @@ -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(); + }); +}); diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..c0e568df3 --- /dev/null +++ b/docs/README.md @@ -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] 구현할 기능 목록 정리 diff --git a/src/App.js b/src/App.js index c38b30d5b..3b4364109 100644 --- a/src/App.js +++ b/src/App.js @@ -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; diff --git a/src/message.js b/src/message.js new file mode 100644 index 000000000..f5de2f496 --- /dev/null +++ b/src/message.js @@ -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] 숫자만 입력 가능합니다.", +};