Skip to content
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
6 changes: 4 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ <h1>⚾ 숫자 야구 게임</h1>
올바른 예) 139 <br />
틀린 예) 122
</p>
<input type="text" id="user-input" />
<button id="submit">확인</button>
<form>
<input type="text" id="user-input" />
<button id="submit">확인</button>
</form>
Comment on lines +16 to +19
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 👍 👍

<h3>📄 결과</h3>
<div id="result"></div>
</div>
Expand Down
78 changes: 78 additions & 0 deletions src/BaseballGame.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Controller
export default class BaseballGame {
#DIGIT_LENGTH = 3;
#referee;

constructor(referee) {
this.#referee = referee;
}

play(computerInputNumbers, userInputNumbers) {
const isValidInput =
this.#validateInputNumbers(computerInputNumbers) &&
this.#validateInputNumbers(userInputNumbers);
if (!isValidInput) return "";

const judgement = this.#judge(computerInputNumbers, userInputNumbers);
const result = this.#formatResult(judgement);

return result;
}

// TODO: 널 오브젝트 패턴?? Judgeable을 validate하는 서비스로 추출
#validateInputNumbers(inputNumbers) {
const inputStr = String(inputNumbers);
if (!this.#validateCorrectLength(inputStr)) return false;
if (!this.#validateAllDigit(inputStr)) return false;
if (!this.#validateDuplication(inputStr)) return false;

return true;
}

#validateCorrectLength(input) {
return input.length === this.#DIGIT_LENGTH;
}

#validateAllDigit(input) {
return /^\d+$/.test(input);
}

#validateDuplication(input) {
return new Set(input).size === inputStr.length;
}

// TODO: Judgeable 객체를 두 개를 비즈니스 로직에 따라 처리하는 Referee 서비스로 추출
#judge(computerInputNumbers, userInputNumbers) {
const set = new Set();
let strike = 0;
let ball = 0;
const computerInputDigits = Array.from(
String(computerInputNumbers),
Number
);
const userInputDigits = Array.from(String(userInputNumbers), Number);

for (let i = 0; i < computerInputDigits.length; i++) {
if (computerInputDigits[i] === userInputDigits[i]) {
strike += 1;
continue;
}
set.add(computerInputDigits[i]);
}

for (const userInputDigit of userInputDigits) {
if (set.has(userInputDigit)) ball += 1;
}

return { strike, ball };
}

// TODO: VO 객체(Judge) 내의 로직으로 분리
#formatResult({ strike, ball }) {
if (strike === 0 && ball === 0) return "낫싱";
if (strike === this.#DIGIT_LENGTH) return "정답을 맞추셨습니다!";
if (strike === 0) return `${ball}볼`;
if (ball === 0) return `${strike}스트라이크`;
return `${ball}볼 ${strike}스트라이크`;
}
}
89 changes: 76 additions & 13 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,76 @@
export default function BaseballGame() {
this.play = function (computerInputNumbers, userInputNumbers) {
return "결과 값 String";
};
}

// export default class BaseballGame {
// play(computerInputNumbers, userInputNumbers) {
// return "결과 값 String";
// }
// }

new BaseballGame();
import BaseballGame from "/src/BaseballGame.js";
import {
convertDigitArrayToInt,
generateNonDuplicateRandomIntArray,
} from "/src/utils.js";

const generateComputerInputNumbers = () =>
convertDigitArrayToInt(
generateNonDuplicateRandomIntArray({
arraylength: 3,
digitCount: 1,
})
);

const userInputEl = document.querySelector("#user-input");
const submitBtnEl = document.querySelector("#submit");
const resultEl = document.querySelector("#result");

const baseballGame = new BaseballGame();
let computerInputNumbers = generateComputerInputNumbers();

const resetUserInput = () => {
userInputEl.disabled = false;
userInputEl.value = null;
userInputEl.focus();
};

const resetResultEl = () => {
resultEl.innerHTML = "";
};

const showWinningResult = () => {
const strongEl = document.createElement("strong");
strongEl.textContent = result;
resultEl.textContent = "";
resultEl.appendChild(strongEl);

const restartMention = document.createElement("span");
restartMention.textContent = "게임을 새로 시작하시겠습니까?";

const restartButtonEl = document.createElement("button");
restartButtonEl.textContent = "게임 재시작";
restartButtonEl.addEventListener("click", handleRestart);

const restartWrapper = document.createElement("div");
restartWrapper.appendChild(restartMention);
restartWrapper.appendChild(restartButtonEl);

resultEl.appendChild(restartWrapper);
};

const handleRestart = (e) => {
resetUserInput();
resetResultEl();
computerInputNumbers = generateComputerInputNumbers();
};

const handleSubmit = (e) => {
const userInputNumbers = Number(userInputEl?.value);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

submit event를 사용하면 다시 DOM에 접근해서 값을 가져오는게 아니라 전달 받은 Event 객체에서 값을 가져올 수 있을거 같네요 ㅎㅎ

const result = baseballGame.play(computerInputNumbers, userInputNumbers);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

result를 텍스트로 받아오고 있는데요. result에서 ball과 strike 개수를 받아서 처리해도 좋을거 같네요


if (!result) {
alert("유효하지 않은 입력입니다.");
userInputEl.focus();
return;
}
if (result === "정답을 맞추셨습니다!") {
userInputEl.disabled = true;
showWinningResult();
return;
}

resultEl.textContent = result;
};

submitBtnEl.addEventListener("click", handleSubmit);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

form을 사용하도록 변경해서 여기도 submit 이벤트를 활용해보시면 좋을거 같네요!

27 changes: 27 additions & 0 deletions src/utils.js
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

깔끔하네요 👍 👍

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export const convertDigitArrayToInt = (digitArr) => parseInt(digitArr.join(""));

export const generateRandomInt = (length = 1) => {
const min = 10 ** (length - 1);
const max = 10 ** length;

return Math.floor(Math.random() * (max - min)) + min;
};

export const generateFixedSizeSet = (generateValue, { size = 1 }) => {
const set = new Set();
while (set.size < size) {
const value = generateValue();
set.add(value);
}
return set;
};

export const generateNonDuplicateRandomIntArray = ({
arraylength,
digitCount = 1,
}) =>
Array.from(
generateFixedSizeSet(() => generateRandomInt(digitCount), {
size: arraylength,
})
);