Skip to content
Closed
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
40 changes: 40 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
## 구현이 필요한 기능

### 컴퓨터가 생각할 숫자 결정하기
> 1부터 9사이의 세 개의 숫자를 임의로 결정해야한다.
- [MissionUtils 라이브러리](https://github.com/woowacourse-projects/javascript-mission-utils#mission-utils) 의 Random.pickNumberInRange를 사용해 구한다.
```js
Random.pickNumberInRange(1, 10); // 1
```

### 유저가 제시한 숫자를 판정하기
> 입력한 값을 컴퓨터가 생각한 숫자와 비교하여 힌트 또는 정답을 출력한다.
- 입력된 숫자가 형식을 만족하는지 확인하는 `validateNumber` 메서드
- **3개의 숫자** 형식을 만족하는 경우
- 같은 수가 같은 자리에 있으면 `스트라이크`
- 같은 수가 다른 자리에 있으면 `볼`
- 같은 수가 없으면 `낫싱`
- 정확히 일치하는 경우엔 게임을 종료하고 재시작 버튼을 노출시킨다.
- 형식을 만족하지 않는 경우
- `alert`로 에러 메시지를 보여주고, 다시 입력하도록 한다.
- 잘못된 값이 입력되어 있던 폼은 비워준다.

### 현재 상태를 결과 영역에 표시하기
> 현재 상태에 따라 결과 영역에 적절한 값을 출력한다.
- 유저가 **오답**을 입력한 경우
- 스트라이크, 볼, 낫싱의 결과를 결과 영역에 출력한다.
- 유저가 **정답**을 입력한 경우
- 축하 메시지와 함께 게임을 재시작 할 수 있는 버튼을 노출한다.
- 유저가 재시작 버튼을 클릭한 경우
- 결과 영역에 출력된 메시지들을 지운다.

### 게임 재시작하기
> 게임을 재시작 할 수 있도록 현재 상태와 정답을 초기화 시킨다.
- **[컴퓨터가 생각할 숫자 결정하기]** 에서 만든 메서드를 통해 정답을 초기화 한다.
- **[현재 상태를 화면에 표시하기]** 에서 만든 메서드를 통해 결과 영역의 메시지들을 지운다.

### 리팩토링 하기
> MVC 패턴을 기반으로 프로젝트 구조를 변경한다.
- Model 구성하기
- View 구성하기
- Controller 구성하기
4 changes: 2 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ <h1>⚾ 숫자 야구 게임</h1>
올바른 예) 139 <br />
틀린 예) 122
</p>
<form>
<form onSubmit="return false;">
<input type="text" id="user-input" />
<button id="submit">확인</button>
</form>
<h3>📄 결과</h3>
<div id="result">1볼 1스트라이크</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/@woowacourse/[email protected]/dist/mission-utils.min.js"></script>
<script type="module" src="src/index.js"></script>
<script type="module" src="./src/index.js"></script>
</body>
</html>
10 changes: 10 additions & 0 deletions src/constants/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const Messages = {
nothing: "낫싱",
ball: "볼",
strike: "스트라이크",
correct: "🎉 정답을 맞추셨습니다! 🎉"
};

export const HTML = {
result: "<h3>" + Messages.correct + "</h3>" + "게임을 새로 시작하시겠습니까? <button id=\"game-restart-button\">게임 재시작</button>"
};
45 changes: 45 additions & 0 deletions src/game/baseballGame.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import judgeInputNumber from "../utils/judgeInputNumber.js";

function uniqueNumberPush(computerNumber, randomNumber) {
if(!computerNumber.includes(randomNumber)) {
computerNumber.push(randomNumber);
}
}

function generateNumber(computerNumber) {
while(computerNumber.length < 3) {
const randomNumber = MissionUtils.Random.pickNumberInRange(1, 9);
uniqueNumberPush(computerNumber, randomNumber);
}
}

class BaseballGame {
state = {};

constructor() {
this.state.computerNumber = [];
this.state.gameState = true;
}

setComputerNumber() {
generateNumber(this.state.computerNumber);
}

getState() {
return this.state;
}

play(userInputNumber) {
judgeInputNumber(this.state, userInputNumber);
if(this.state.strikes === 3) this.state.gameState = false;
return this.state;
}

replay() {
this.state.gameState = true;
this.state.computerNumber = [];
this.setComputerNumber();
}
}

export default BaseballGame;
46 changes: 46 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import BaseballGame from "./game/baseballGame.js";
import validateInputNumber from "./utils/validateInputNumber.js";
import GameResult from "./view/GameResult.js";

const baseballGame = new BaseballGame();
const gameResult = new GameResult("#result");
const submitButton = document.getElementById("submit");
const userInput = document.getElementById("user-input");

function playGame() {
if(validateInputNumber(userInput.value)) {
baseballGame.play(userInput.value);
gameResult.render(baseballGame.getState());
addReplayEvent(baseballGame.getState().gameState);
}else{
alert("잘못된 값을 입력하였습니다!");
clearUserInput();
}
}

function replayGame() {
const replayButton = document.getElementById("game-restart-button");

replayButton.removeEventListener("click", replayGame);
baseballGame.replay();
gameResult.render("reset");
clearUserInput();
}

function addReplayEvent(state) {
if(!state) {
const replayButton = document.getElementById("game-restart-button");
replayButton.addEventListener("click", replayGame);
}
}

function clearUserInput() {
userInput.value = "";
}

function init() {
baseballGame.setComputerNumber();
submitButton.addEventListener("click", playGame);
}

init();
23 changes: 23 additions & 0 deletions src/utils/judgeInputNumber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
function isStrike(computerInputNumbers, userInputNumbers, index) {
return computerInputNumbers[index] === Number(userInputNumbers.charAt(index));
}

function isBall(computerInputNumbers, userInputNumbers, index) {
return computerInputNumbers.includes(Number(userInputNumbers.charAt(index)));
}

function judgeInputNumber(state, userInputNumbers) {
state.strikes = 0;
state.balls = 0;
console.log(state.computerNumber, userInputNumbers);

for(let i = 0; i < 3; i++) {
if(isStrike(state.computerNumber, userInputNumbers, i)) {
state.strikes++;
}else if(isBall(state.computerNumber, userInputNumbers, i)) {
state.balls++;
}
}
}

export default judgeInputNumber;
18 changes: 18 additions & 0 deletions src/utils/validateInputNumber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
function isThreeDigits(inputNumber) {
return inputNumber.length === 3;
}

function isDuplicate(inputNumber) {
const firstDigit = inputNumber.charAt(0);
const secondDigit = inputNumber.charAt(1);
const thirdDigit = inputNumber.charAt(2);
return firstDigit === secondDigit || secondDigit === thirdDigit || thirdDigit === firstDigit;
}

function validateInputNumber(inputNumbers) {
if(!Number.isInteger(Number(inputNumbers))) return false;
if(!isThreeDigits(inputNumbers)) return false;
return !isDuplicate(inputNumbers);
}

export default validateInputNumber;
37 changes: 37 additions & 0 deletions src/view/GameResult.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Messages, HTML } from "../constants/constants.js";

class gameResult {

constructor(target) {
this.target = document.querySelector(target);
}

template(state) {
let msg = "";

if(state !== "reset") {
if (state.strikes === 0 && state.balls === 0) {
msg = Messages.nothing;
} else if (state.strikes === 3) {
msg = HTML.result;
} else {
if (state.balls > 0) {
msg += state.balls + Messages.ball + " ";
}

if (state.strikes > 0) {
msg += state.strikes + Messages.strike;
}
}
}
console.log(msg);
return `<p>${msg}</p>`;
}

render(state) {
console.log(this.target.innerHTML);
this.target.innerHTML = this.template(state);
}
}

export default gameResult;