diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..78806ebc5 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,32 @@ +## 구현할 기능 정리 +0. 게임 시작 시 출력 문구 + - [숫자 야구 게임을 시작합니다.] 문구 출력 + +1. 랜덤으로 숫자를 생성하는 기능 + - `@woowacourse/mission-utils`의 `Random.pickNumberInRange()`를 활용 + +2. 사용자가 숫자 세자리를 입력하는 기능 + - `@woowacourse/mission-utils`의 `Console.readLineAsync`, `Console.print`를 활용 + - [숫자를 입력해 주세요:] 문구 출력 + - 예외처리는 `throw`문을 사용, 앞에 [ERROR]를 포함하여 경고메시지를 출력하고, 애플리케이션을 종료 + * 예외처리 경우 + (1) 숫자 이외에 다른 문자를 입력한 경우 + (2) 3개의 숫자를 입력하지 않은 경우 + (3) 1~9까지의 정수가 아닌 다른 숫자를 입력한 경우 + (4) 동일한 숫자를 입력한 경우: set().length != 3 + (4) 위의 경우가 모두 아닌 경우 + +3. 생성한 값과 입력한 값을 비교하여 힌트를 출력해주는 기능 + - 스트라이크: 같은 수가 같은 자리에 있는 경우 + - 볼: 다른 자리에 있는 경우 + - 낫싱: 같은 수가 전혀 없는 경우 + - 출력 방식: 입력한 숫자에 대한 결과를 [n볼 n스트라이크] 방식으로 출력 + +4. 게임 종료 시 + - 3개의 숫자를 모두 맞힐 경우 [3개의 숫자를 모두 맞히셨습니다! 게임 종료] 출력 + - 이후 [재시작(1)/종료(2)] 중 하나의 수를 입력받아서 프로그램 재시작/종료여부 결정 + +## 코드 컨벤션(이름 구현 규칙) + - 소스의 변수명, 클래스명 등에는 영문만 사용 + - 클래스, 메서드 등의 이름에는 특수 문자를 사용x + - 상수명은 SNAKE_CASE로 작성(대문자 + _ + 대문자) diff --git a/src/App.js b/src/App.js index c38b30d5b..ccc9646ea 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,49 @@ +import PlayGame from "./PlayGame.js" +import { MissionUtils } from "@woowacourse/mission-utils"; + class App { - async play() {} + constructor() { + this.playgame = new PlayGame(); + this.play(); + this.setRandomNumber(); + this.handleUserInput(); + + } + play() { + MissionUtils.Console.print('숫자 야구 게임을 시작합니다.'); + } + + setRandomNumber() { + this.playgame.setRandomNumber(); + } + + async handleUserInput() { + const randomNumber = this.playgame.getRandomNumber(); + this.playgame.handleInput().then((result) => { + this.playgame.compareNumbers(randomNumber, result).then((strike) => { + if (strike !== 3) { + this.handleUserInput() + } else { + MissionUtils.Console.print('3개의 숫자를 모두 맞히셨습니다! 게임 종료'); + this.askRestart() + } + + }) + }) + } + + askRestart() { + this.playgame.restartInput().then((response) => { + if (['1', '2'].includes(response)) { + if (response === '1') { + this.setRandomNumber(); + this.handleUserInput(); + } + } + }) + } } -export default App; +const app = new App(); + +export default App; \ No newline at end of file diff --git a/src/PlayGame.js b/src/PlayGame.js new file mode 100644 index 000000000..9de91574e --- /dev/null +++ b/src/PlayGame.js @@ -0,0 +1,85 @@ +import { MissionUtils } from "@woowacourse/mission-utils"; +import ReturnError from "./RetrunError.js"; + +class PlayGame { + constructor() { + this.returnError = new ReturnError(); + } + + randomNumber; + strikeCount = 0; + ballCount = 0; + restartUserInput; + + + getStrikeCount() { + return this.strikeCount; + } + + getRandomNumber() { + return this.randomNumber; + } + + setRandomNumber() { + const computer = [] + while (computer.length < 3) { + const randomNum = MissionUtils.Random.pickNumberInRange(1, 9); + if (!computer.includes(randomNum)) { + computer.push(randomNum) + } + } + this.randomNumber = computer; + } + + async handleInput() { + this.strikeCount = 0; + this.ballCount = 0; + try { + const input = await MissionUtils.Console.readLineAsync('숫자를 입력해 주세요:'); + const userInput = input.split('').map(Number); + this.returnError.sayError(userInput); + return userInput; + } catch (ERROR) { + throw new Error(ERROR) + } + } + + async compareNumbers(random, input) { + for (let i = 0; i < random.length; i++) { + if (random.includes(input[i])) { + if (random[i] == input[i]) { + this.strikeCount++; + } else { + this.ballCount++; + } + } + } + this.printResult() + return this.strikeCount; + } + + printResult () { + if (this.strikeCount === 0 && this.ballCount === 0) { + MissionUtils.Console.print('낫싱'); + } else if (this.ballCount === 0) { + MissionUtils.Console.print(this.strikeCount + '스트라이크'); + } else if (this.strikeCount === 0) { + MissionUtils.Console.print(this.ballCount + '볼'); + } else { + MissionUtils.Console.print(this.ballCount + '볼' + ' ' + this.strikeCount + '스트라이크'); + } + } + + + async restartInput() { + try { + const restartUserInput = await MissionUtils.Console.readLineAsync('게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.\n'); + return restartUserInput; + } catch (ERROR) { + throw new Error('[ERROR] 1 또는 2를 입력해야 합니다.'); + } + } + +} + +export default PlayGame; \ No newline at end of file diff --git a/src/retrunError.js b/src/retrunError.js new file mode 100644 index 000000000..714d2720e --- /dev/null +++ b/src/retrunError.js @@ -0,0 +1,15 @@ +class ReturnError { + + sayError(userInput){ + if (isNaN(userInput.join(""))) { + throw new Error('[ERROR] 숫자를 입력해야 합니다.') + } else if (userInput.length != 3) { + throw new Error('[ERROR] 숫자 3개를 입력해야 합니다.') + } else if(Math.min(userInput) < 1 || Math.max(userInput) > 9 ){ + throw new Error('[ERROR] 1부터 9사이의 숫자를 입력해야 합니다.') + } else if (new Set(userInput).size != 3) { + throw new Error('[ERROR] 서로 다른 숫자 세개를 입력해야 합니다.') + } + } +} +export default ReturnError; \ No newline at end of file