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

[자동차 경주] 박재영 미션 제출합니다. #448

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
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
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,64 @@
# javascript-racingcar-precourse

초간단 자동차 경주 게임

## 기능 요구사항

1. 자동차 경주 게임에 참여할 자동차 이름을 쉼표를 기준으로 구분하여 입력받는다.
- 자동차 이름은 5자 이하만 가능하다.
- 자동차 이름은 공백일 수 없다.
2. 시도할 횟수를 입력받는다.
3. 전진하는 조건은 0에서 9사이에서 random 값을 구한 후 random 값이 4이상일 경우 전진하고, 3이하일 경우 정지한다.
4. 차수별 실행 결과를 출력한다.
5. 가장 멀리 이동한 자동차를 우승자로 출력한다.
- 우승자는 한 명 이상일 수 있다.
- 우승자가 여러명일 경우 쉼표(,)로 구분한다.

<br/>

## 예외처리 요구사항

1. 사용자가 잘못된 값을 입력한 경우 `[ERROR]`로 시작하는 에러 메시지를 출력하고 프로그램을 종료한다.
1.1 공백이 포함된 경우
1.2 자동차 이름이 5자를 초과하는 경우
1.3 자동차 이름이 공백인 경우
1.4 자동차 이름이 중복되는 경우
1.5 자동차가 1대인 경우
1.6 시도 횟수가 숫자가 아닌 경우
1.7 시도 횟수가 0 이하인 경우
1.8 시도 횟수가 정수가 아닌 경우
2. 입력값이 빈 문자열인 경우 `[ERROR]`로 시작하는 에러 메시지를 출력하고 프로그램을 종료한다.

<br/>

## 실행결과 예시

```
경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)
pobi,woni,jun
시도할 횟수는 몇 회인가요?
5

실행 결과
pobi : -
woni :
jun : -

pobi : --
woni : -
jun : --

pobi : ---
woni : --
jun : ---

pobi : ----
woni : ---
jun : ----

pobi : -----
woni : ----
jun : -----

최종 우승자 : pobi, jun
```
50 changes: 49 additions & 1 deletion __tests__/ApplicationTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe("자동차 경주", () => {
});
});

test("예외 테스트", async () => {
test("예외 테스트_자동차_이름 5자 초과", async () => {
// given
const inputs = ["pobi,javaji"];
mockQuestions(inputs);
Expand All @@ -57,4 +57,52 @@ describe("자동차 경주", () => {
// then
await expect(app.run()).rejects.toThrow("[ERROR]");
});

test("예외 테스트_자동차_이름 공백", async () => {
// given
const inputs = ["pobi, "];
mockQuestions(inputs);

// when
const app = new App();

// then
await expect(app.run()).rejects.toThrow("[ERROR]");
});

test("예외 테스트_자동차_2대 미만", async () => {
// given
const inputs = ["pobi"];
mockQuestions(inputs);

// when
const app = new App();

// then
await expect(app.run()).rejects.toThrow("[ERROR]");
});

test("예외 테스트_시도 횟수_0 또는 음수", async () => {
// given
const inputs = ["pobi,woni", "-1"];
mockQuestions(inputs);

// when
const app = new App();

// then
await expect(app.run()).rejects.toThrow("[ERROR]");
});

test("예외 테스트_시도 횟수_문자열", async () => {
// given
const inputs = ["pobi,woni", "a"];
mockQuestions(inputs);

// when
const app = new App();

// then
await expect(app.run()).rejects.toThrow("[ERROR]");
});
});
82 changes: 81 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,85 @@
import { Console, MissionUtils } from "@woowacourse/mission-utils";

class App {
async run() {}
cars = [];
distances = [];
winner = [];

async run() {
const carsInput = await Console.readLineAsync(
"경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)\n"
);
if (carsInput === "") {
throw new Error("[ERROR] 자동차 이름을 입력해주세요.");
}
this.cars = carsInput.split(",");
this.checkCarValidation();

const rounds = await Console.readLineAsync("시도할 회수는 몇 회인가요?\n");
this.checkRoundValidation(rounds);

this.distances = Array(this.cars.length).fill(0);

Console.print("\n실행 결과");
for (let i = 0; i < rounds; i++) {
this.racing();
Console.print("\n");
}

this.findWinner();

Console.print(`최종 우승자 : ${this.winner.join(", ")}`);
}

racing() {
for (let i = 0; i < this.cars.length; i++) {
const distance = MissionUtils.Random.pickNumberInRange(0, 9);
if (distance >= 4) {
this.distances[i]++;
}

Console.print(`${this.cars[i]} : ${"-".repeat(this.distances[i])}`);
}
}

findWinner() {
const maxDistance = Math.max(...this.distances);

for (let car of this.cars) {
if (this.distances[this.cars.indexOf(car)] === maxDistance) {
this.winner.push(car);
}
}
}

checkCarValidation() {
if (this.cars.length < 2) {
throw new Error("[ERROR] 자동차는 2대 이상이어야 합니다.");
} else {
this.cars.forEach((car) => {
if (car.length > 5) {
throw new Error("[ERROR] 자동차 이름은 5자 이하여야 합니다.");
} else if (car.trim() === "") {
throw new Error("[ERROR] 자동차 이름은 공백이 아니어야 합니다.");
}
});

if (new Set(this.cars).size !== this.cars.length) {
throw new Error("[ERROR] 중복된 자동차 이름이 있습니다.");
}
}
}

checkRoundValidation(rounds) {
const roundParse = parseInt(rounds);
if (isNaN(roundParse)) {
throw new Error("[ERROR] 시도 횟수는 숫자여야 합니다.");
} else if (roundParse < 1) {
throw new Error("[ERROR] 시도 횟수는 1 이상이어야 합니다.");
} else if (roundParse % 1 !== 0) {
throw new Error("[ERROR] 시도 횟수는 정수여야 합니다.");
}
}
}

export default App;