diff --git a/README.md b/README.md index 8b2833c..0d22415 100644 --- a/README.md +++ b/README.md @@ -1 +1,7 @@ -# javascript-baseball-precourse \ No newline at end of file +# javascript-baseball-precourse + +기능 요구 사항 +1. 랜덤 수 생성 : 1부터 9까지 서로 다른 임의의 3자리 수를 생성한다. +2. 사용자 입력 받기: 입력된 수가 3자리이고 각 자리가 중복되지 않는지 확인한다. +3. 게임 진행 : 정답과 입력된 숫자를 비교하여 스트라이크와 볼을 판단하고 결과를 표시한다. +4. 게임 종료 : 결과가 3 스트라이크인 경우 게임이 종료되고 재시작 버튼을 표시한다. \ No newline at end of file diff --git a/css/main.css b/css/main.css new file mode 100644 index 0000000..3018f53 --- /dev/null +++ b/css/main.css @@ -0,0 +1,105 @@ +body { + font-family: "Nanum Gothic", sans-serif; + font-size: 16px; + line-height: 1.4; + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + margin: 0; + background-color: #f2f2f2; +} + +strong { + font-weight: bold; +} + +button { + cursor: pointer; + border: none; + background-color: #6b9fff; + color: white; + border-radius: 50px; + padding: 10px 20px; + font-size: 16px; +} + +button:hover { + background-color: #588bf7; +} + +.container { + background: white; + width: 360px; + height: 330px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + padding: 20px; + border-radius: 10px; +} + +.container h1 { + font-size: 30px; + font-weight: bold; + margin-bottom: 20px; + color: #333333; + text-align: center; +} + +.container .description { + font-size: 17px; + margin: 10px 0; + color: #666666; +} + +.container .answer { + display: flex; + gap: 25px; + width: 100%; +} + +.container .answer input { + width: 220px; + padding: 10px 20px; + border-radius: 5px; + border: 1px solid #dddddd; + font-size: 16px; +} + +.container .answer button{ + width: 75px; +} + +.error-text { + color: red; + font-size: 17px; +} + +.result { + margin-top: 20px; + display: flex; + flex-direction: column; + align-items: center; + width: 100%; +} + +.result h2 { + font-size: 20px; + font-weight: bold; + margin-bottom: 10px; + color: #333333; + width: 100%; + text-align: left; +} + +.result .result-text { + font-size: 18px; + font-weight: bold; + margin-bottom: 10px; + height: 30px; + color: #333333; +} + +.result button { + width: 150px; + margin: 0 auto; +} diff --git a/index.html b/index.html index b021b5c..678e5f2 100644 --- a/index.html +++ b/index.html @@ -1,12 +1,52 @@ - + - + 숫자 야구 게임 + + + + -
- +
+ +
+

⚾ 숫자 야구 게임

+
+ +
+

+ 1~9까지의 수를 중복없이 + 3개 입력해주세요 +

+

올바른 예) 139

+

틀린 예) 122

+
+ +
+ + +
+ +

+ +
+

📋 결과

+

+ +
+
+ diff --git a/src/checkNumber.js b/src/checkNumber.js new file mode 100644 index 0000000..3d491d5 --- /dev/null +++ b/src/checkNumber.js @@ -0,0 +1,24 @@ +export default function checkNumber(userInput) { + const errorMessageElement = document.getElementById("error-message"); + + errorMessageElement.textContent = ""; + + // 입력이 3자리 숫자인지 확인 + if (!/^\d{3}$/.test(userInput)) { + showError("3자리 수로 입력해주세요"); + return false; + } + + // 입력에 중복된 숫자가 있는지 확인 + if (new Set(userInput).size !== 3) { + showError("중복 없이 입력해주세요"); + return false; + } + + return true; +} + +function showError(message) { + const errorMessageElement = document.getElementById("error-message"); + errorMessageElement.textContent = message; +} \ No newline at end of file diff --git a/src/main.js b/src/main.js index e69de29..3f177aa 100644 --- a/src/main.js +++ b/src/main.js @@ -0,0 +1,24 @@ +import generateRandomNumber from './randNumber.js'; +import checkNumber from './checkNumber.js'; +import result from './result.js'; +import restartGame from './restart.js'; + +// 정답 랜덤 수 생성 +let resultNum = generateRandomNumber(false); + +document.getElementById("check-button").addEventListener("click", function () { + // 사용자의 입력을 가져옴 + const userInput = document.getElementById("user-input").value; + if (checkNumber(userInput)) { + // 입력된 수가 조건에 맞으면 결과 출력 + result(userInput, resultNum); + } else { + // 입력된 수가 조건에 맞지 않으면 결과 초기화 + document.getElementById("result-message").textContent = ""; + } +}); + +document.getElementById("restart-button").addEventListener("click", function () { + // 게임 재시작 + resultNum = restartGame(); +}); \ No newline at end of file diff --git a/src/randNumber.js b/src/randNumber.js new file mode 100644 index 0000000..77ea8ff --- /dev/null +++ b/src/randNumber.js @@ -0,0 +1,29 @@ +export default function generateRandomNumber(restart = false) { + // 기존의 resultNum이 localStorage에 있는지 확인 + let resultNum = localStorage.getItem("resultNum"); + + // 게임 재시작이 아닌 경우와 resultNum이 이미 있는 경우 그대로 반환 + if (!restart && resultNum) { + return resultNum; + } + + // 새로운 정답 생성 + resultNum = generateUniqueNumber(); + localStorage.setItem("resultNum", resultNum); + console.log(resultNum); + return resultNum; +} + +function generateUniqueNumber() { + const answerArr = []; + + // 중복되지 않는 3자리 숫자 생성 + while (answerArr.length < 3) { + const num = Math.floor(Math.random() * 9) + 1; + if (!answerArr.includes(num)) { + answerArr.push(num); + } + } + + return answerArr.join(''); +} \ No newline at end of file diff --git a/src/restart.js b/src/restart.js new file mode 100644 index 0000000..80643fc --- /dev/null +++ b/src/restart.js @@ -0,0 +1,21 @@ +import generateRandomNumber from './randNumber.js'; + +export default function restartGame() { + // 게임 재시작을 위해 resultNum 제거 + clearLocalStorage(); + // 입력 및 메시지 초기화 + resetInputs(); + // 새로운 정답 생성 + return generateRandomNumber(true); +} + +function clearLocalStorage() { + localStorage.removeItem("resultNum"); +} + +function resetInputs() { + document.getElementById("user-input").value = ""; + document.getElementById("error-message").textContent = ""; + document.getElementById("result-message").textContent = ""; + document.getElementById("restart-button").style.display = "none"; +} \ No newline at end of file diff --git a/src/result.js b/src/result.js new file mode 100644 index 0000000..bf2ea3f --- /dev/null +++ b/src/result.js @@ -0,0 +1,47 @@ +export default function result(userInput, targetNumber) { + // 결과를 계산 + const { strikes, balls } = calculateScore(userInput, targetNumber); + // 결과를 화면에 표시 + showResult(strikes, balls); +} + +function calculateScore(userInput, targetNumber) { + let strikes = 0; + let balls = 0; + + // 입력된 수와 정답을 비교하여 스트라이크와 볼의 개수를 계산 + for (let i = 0; i < 3; i++) { + if (userInput[i] === targetNumber[i]) { + strikes++; + } else if (targetNumber.includes(userInput[i])) { + balls++; + } + } + + return { strikes, balls }; +} + +function showResult(strikes, balls) { + const resultMessage = document.getElementById("result-message"); + const restartButton = document.getElementById("restart-button"); + restartButton.style.display = "none"; + + if (strikes === 3) { + // 스트라이크가 3개인 경우 정답 메시지를 표시 + resultMessage.textContent = "🎉 축하합니다! 정답을 맞추셨습니다! 🎉"; + restartButton.style.display = "inline-block"; + } else if (strikes > 0 || balls > 0) { + // 스트라이크나 볼이 있는 경우 해당 개수를 표시 + let message = ""; + if (balls > 0) { + message += ` ${balls} 볼`; + } + if (strikes > 0) { + message += `${strikes} 스트라이크`; + } + resultMessage.textContent = message; + } else { + // 스트라이크와 볼이 모두 없는 경우 낫싱 메시지를 표시 + resultMessage.textContent = "낫싱"; + } +} \ No newline at end of file