diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..6c727f39d --- /dev/null +++ b/docs/README.md @@ -0,0 +1,6 @@ +- ✅랜덤 숫자 세자리 지정하기 +- ✅사용자 입력받기 +- ✅컴퓨터 응답 출력하기 +- ✅잘못된 값 입력 시 에러 발생하기 +- ✅랜덤 숫자와 사용자 입력 비교하기 +- ✅게임 종료 시 재시작/종료 입력받기 diff --git a/src/App.js b/src/App.js index c38b30d5b..52d55ef06 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,14 @@ +import Computer from './Computer.js'; +import User from './User.js'; + class App { - async play() {} + constructor() { + this.computer = new Computer(); + this.user = new User(); + } + async play() { + await this.computer.playGame(this.user); + } } export default App; diff --git a/src/Computer.js b/src/Computer.js new file mode 100644 index 000000000..75c629c39 --- /dev/null +++ b/src/Computer.js @@ -0,0 +1,72 @@ +import { MissionUtils } from '@woowacourse/mission-utils'; + +export default class Computer { + static REPLAY_CODE = '1'; + static QUIT_CODE = '2'; + static NUM_SIZE = 3; + static MODE_SIZE = 1; + + constructor() { + this.numbers = []; + } + pickRandomNumbers() { + this.clearNumbers(); + while (this.numbers.length < Computer.NUM_SIZE) { + const number = MissionUtils.Random.pickNumberInRange(1, 9); + if (!this.numbers.includes(number)) { + this.numbers.push(number); + } + } + } + async playGame(user) { + MissionUtils.Console.print('숫자 야구 게임을 시작합니다.'); + while (true) { + this.pickRandomNumbers(); + while (true) { + const input = await user.getUserNumber(); + const result = this.getMessage(input); + MissionUtils.Console.print(result.result); + if (result.success) { + MissionUtils.Console.print( + '3개의 숫자를 모두 맞히셨습니다! 게임 종료' + ); + break; + } + } + const input = await user.getUserReplay(); + if (input === Computer.QUIT_CODE) break; + } + } + getMessage(expectedNumbers) { + const ballStrike = this.calculateBallStrike(expectedNumbers); + const result = this.getResultString(ballStrike); + return { + result, + success: ballStrike.strike === Computer.NUM_SIZE, + }; + } + calculateBallStrike(expectedNumbers) { + return expectedNumbers + .split('') + .map(Number) + .reduce( + (res, cur, idx) => { + const newRes = { ...res }; + if (this.numbers[idx] === cur) newRes.strike += 1; + else if (this.numbers.includes(cur)) newRes.ball += 1; + return newRes; + }, + { ball: 0, strike: 0 } + ); + } + getResultString({ ball, strike }) { + if (ball === 0 && strike === 0) return '낫싱'; + else if (ball === 0) return `${strike}스트라이크`; + else if (strike === 0) return `${ball}볼`; + else return `${ball}볼 ${strike}스트라이크`; + } + + clearNumbers() { + this.numbers = []; + } +} diff --git a/src/User.js b/src/User.js new file mode 100644 index 000000000..1ccb824fd --- /dev/null +++ b/src/User.js @@ -0,0 +1,34 @@ +import { MissionUtils } from '@woowacourse/mission-utils'; +import Computer from './Computer'; +export default class User { + async getUserNumber() { + const input = await MissionUtils.Console.readLineAsync( + '숫자를 입력해주세요 : ' + ); + + if ( + input.length !== Computer.NUM_SIZE || + input.includes('0') || + Number.isNaN(input) + ) { + throw new Error('[ERROR] 숫자가 잘못된 형식입니다.'); + } + + return input; + } + + async getUserReplay() { + const input = await MissionUtils.Console.readLineAsync( + '게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.\n' + ); + if ( + input.length !== Computer.MODE_SIZE || + (input !== Computer.REPLAY_CODE && input !== Computer.QUIT_CODE) || + Number.isNaN(input) + ) { + throw new Error('[ERROR] 숫자가 잘못된 형식입니다.'); + } + + return input; + } +}