Skip to content
47 changes: 47 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
## 구현할 기능 목록
#### 1. 컴퓨터가 랜덤으로 1에서 9까지 서로 다른 임의의 수 3개를 선택한다.
- @woowacourse/mission-utils의 Random 및 Console API를 사용하여 구현해야 한다.
- Random 값 추출은 Random.pickNumberInRange()를 활용한다.

#### 2. 게임이 시작되어 '숫자 야구 게임을 시작합니다.' 를 출력한다.

#### 3. 게임 플레이어로부터 서로 다른 3자리의 수를 입력받는다.
- 입력을 받을 때 '숫자를 입력해주세요 : '를 출력한다.
- 사용자의 값을 입력 받고 출력하기 위해서는 Console.readLineAsync, Console.print를 활용한다.

#### 4. 컴퓨터는 사용자의 입력과 자신이 선택한 숫자를 비교 후 결과 값을 다음의 규칙에 따라 출력한다.

[규칙]
1) 같은 수가 자리에 있으면 **스트라이크**
2) 같은 수가 다른 자리에 있으면 **볼**
3) 같은 수가 전혀 없으면 **낫싱**

[출력]
1) 스트라이크, 볼의 경우가 하나도 없을 때 : **낫싱**

2) 스트라이크는 없으나 볼의 경우가 존재할 때 : **x볼**
- x는 (1~3)의 범위 내에 존재한다.

3) 볼은 없으나 스트라이크의 경우만 존재할 때 : **y스트라이크**
- y는 (1~3)의 범위 내에 존재한다.
- 3스트라이크가 된다면 답을 맞춘 것이다.

4) 스트라이크와 볼의 경우가 모두 존재할 때 : **x볼 y스트라이크**
- x는 (1~2)의 범위 내에 존재하며 y는 1만 가능하다.
- 1볼 2스트라이크는 존재할 수 없는 경우의 수이다.

#### 5. 정답을 맞출때까지 3번~4번의 과정을 반복한다.
- 스트라이크가 3이 되면 컴퓨터가 랜덤으로 선택한 숫자를 맞췄으므로 게임을 종료한다.
- 정답을 맞추면 '3개의 숫자를 모두 맞히셨습니다! 게임 종료', '게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.' 를 출력한다.

#### 6. 사용자로부터 1 또는 2의 입력을 받는다.
- 1을 입력받으면 1번의 과정으로 돌아가 게임을 새롭게 시작한다.
- 2를 입력받으면 게임을 완전히 종료한다. 프로그램 종료 시 process.exit()를 호출하지 않는다.

#### 7. 예외처리
- 사용자가 잘못된 값을 입력한 경우 throw문을 사용해 예외를 발생시킨후 애플리케이션은 종료되어야 한다.
- 3번의 입력에서 사용자가 서로 다른 3자리의 수를 입력하지 않은 경우
- 6번의 입력에서 사용자가 1 또는 2가 아닌 다른 것을 입력한 경우


#### 8. 프로그램 구현이 완료되면 ApplicationTest의 모든 테스트가 성공해야 한다.
115 changes: 114 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,118 @@
import { MissionUtils } from "@woowacourse/mission-utils";

class App {
async play() {}
constructor() {
this.continue = true
}

async play() {
MissionUtils.Console.print("숫자 야구 게임을 시작합니다.");
this.computerNum = this.setNum();
while(this.continue) {
const userNum = await MissionUtils.Console.readLineAsync("숫자를 입력해주세요 : ");
this.vaildation(userNum)
let [ball, strike] = this.result(this.computerNum, userNum)
this.printresult(ball, strike)
if (strike === 3) {
const userReturn = await MissionUtils.Console.readLineAsync("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
this.restart(userReturn)
}
}
}

restart(userReturn) {
if (userReturn !== "1" && userReturn !== "2") {
throw new Error("1과 2중에 하나만 입력해주세요.")
}

if (userReturn === "1") {
this.computerNum = this.setNum();
}

if (userReturn === "2") {
this.continue = false;
}

}

// 랜덤값과 입력값을 비교
result(computerNum, userNum) {
const checkNum = Array.from(userNum, Number)
let strike = 0
let ball = 0

for (let i = 0; i < 3; i++) {
if (computerNum.includes(Number(checkNum[i]))) {
if (computerNum[i] === checkNum[i]) {
strike += 1;
}
else{
ball += 1;
}
}
}
return [ball, strike]
}

//비교값 출력
printresult(ball, strike) {
if (ball === 0 && strike === 0) {
MissionUtils.Console.print("낫싱")
}

else if(ball > 0) {
if (strike > 0) {
MissionUtils.Console.print(`${ball}볼 ${strike}스트라이크`)
}
else {
MissionUtils.Console.print(`${ball}볼`)
}
}

else if (strike > 0) {
MissionUtils.Console.print(`${strike}스트라이크`)
if (strike === 3) {
MissionUtils.Console.print("3개의 숫자를 모두 맞히셨습니다! 게임 종료")
}
}

}


//예외처리
vaildation(userNum) {

if(userNum.length === 0) {
throw new Error("[ERROR] 숫자가 입력되지 않았습니다.")
}

if (userNum.length !== 3) {
throw new Error("[ERROR] 3자리의 수를 입력해주세요.")
}

if(userNum.length !== new Set(Array.from(String(userNum))).size) {
throw new Error("[ERROR] 중복된 숫자가 입력되었습니다.")
}

return true

}


//랜덤으로 3자리의 수 선택
setNum() {
const computer = [];
while (computer.length < 3) {
const number = MissionUtils.Random.pickNumberInRange(1, 9);
if (!computer.includes(number)) {
computer.push(number);
}
}
return computer;
}
}

const app = new App();
app.play();

export default App;