whatisthis?
project. (js) 숫자야구게임 - 웹 ver (수정) 본문
지난 포스팅에서 숫자야구 게임을
html요소와 eventListener을 이용하여 플레이할 수 있도록 수정했었다.
Guess 버튼을 눌렀을 때를 기준으로 해보았는데,
1 / count가 누적이 안됨
2 / 랜덤 숫자가 연동이 안됨
3 / UI 디자인이 너무 안이쁨
과 같은 문제가 있었다.
큰 틀은 유지하되, 폰트나 기본 디자인 요소를 바꿔보았고,
index.html
<!-- reference : www.zerocho.com -->
<!-- JS Array / Math객체 / String / Loop practice용 -->
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>숫자야구</title>
<link rel="stylesheet" href="style.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@700&display=swap" rel="stylesheet">
</head>
<body>
<div id="input-form">
<input required type="text" placeholder="Guess the number" maxlength="4" />
<button>Guess</button>
</div>
<div id="container">
<div id="log"></div>
</div>
<script src="app.js"></script>
</body>
</html>
- #log를 감싸는 div를 추가해 디자인적으로 다 감싸는 역할
( 백그라운드 효과를 줄 예정 )
- web font를 사용하기 위해 link태그 3줄이 추가되었음.
style.css
* {
margin: 0;
box-sizing : border-box;
}
html {
font-family: 'Poppins', sans-serif;
font-size: 16px;
line-height: 2;
color: #1f2d3d;
}
body {
text-align: center;
width: 100%;
height: 100vh;
background-color: #f7efde;
}
body::after {
content: "Bulls and Cows";
display: block;
margin-top: 50px;
color: #736a59;
font-size: 12px;
font-weight: 600;
}
#container {
background-color: #f1e6cd;
}
- 웹 폰트 적용은 font-family로
app.js
// reference : www.zerocho.com
// JS Array / Math객체 / String / Loop practice용
// 로그 출력
function logMessage(msg, color) {
if(!color) {color = '#444444';}
const div = document.createElement('div');
div.innerHTML = msg;
div.style.color = color;
if(color === '#370089') {div.style.fontWeight = 'bold';
div.style.fontSize = '20px';}
document.getElementById('log').appendChild(div);
}
// input과 button
const input = document.querySelector('#input-form input');
const button = document.querySelector('#input-form button');
//
function getNumber() {
let list = [0,1,2,3,4,5,6,7,8,9];
let answer = [];
for (let i=0; i<4; i++) {
let select = Math.floor(Math.random() * list.length);
// answer[i] = list.splice(select, 1)[0];
answer.push(list.splice(select, 1)[0]);
}
localStorage.setItem('answer', answer.join('')); // answer = 2458
}
let count = 1;
function guessNumber() {
let strike = 0;
let ball = 0;
while(count <= 10) {
let num = input.value;
let numArr = num.split('');
strike = 0;
ball = 0;
let answerArr = localStorage.getItem('answer').split('');
for(let j=0; j<4; j++) {
for (let k=0; k<4; k++) {
if (answerArr[j] == numArr[k]) {
if (j == k) {
strike++;
} else {
ball++;
}
break;
}
}
}
if (strike === 4) {
logMessage('정답입니다!' + count + '회만에 맞춤', '#370089');
break;
} else if (count > 10) {
logMessage('시도 횟수를 초과하셨습니다.\n게임을 다시 하려면 F5를 누르세요.', '#780000');
} else {
logMessage(numArr.join('') + ': ' + strike + '스트라이크 ' + ball + '볼');
count++;
break;
}
}
}
getNumber(); // 숫자 뽑기
button.addEventListener('click', guessNumber); // eventListener - 버튼 클릭시
- 지난번에 작성했던 코드와 비교해보면
// 로그 출력
function logMessage(msg, color) {
if(!color) {color = 'black';}
const div = document.createElement('div');
div.innerHTML = msg;
div.style.color = color;
document.getElementById('log').appendChild(div);
}
// input과 button
const input = document.querySelector('#input-form input');
const button = document.querySelector('#input-form button');
//
function guessNumber() {
let list = [0,1,2,3,4,5,6,7,8,9];
let answer = [];
for (let i=1; i<4; i++) {
let select = Math.floor(Math.random() * list.length);
answer[i] = list.splice(select, 1)[0];
}
let count = 1;
let strike = 0;
let ball = 0;
while(count <= 10) {
let num = input.value;
let numArr = num.split('');
strike = 0;
ball = 0;
count++;
for(let j=0; j<4; j++) {
for (let k = 0; k < 4; k++) {
if ([j] == numArr[k]) {
if (j === k) {
strike++;
} else {
ball++;
}
break;
}
}
}
if (strike === 4) {
logMessage('정답입니다!');
break;
} else if (count > 10) {
logMessage('시도 횟수를 초과하셨습니다.\n게임을 다시 하려면 F5를 누르세요.', 'red');
} else {
logMessage(numArr.join('') + ': ' + strike + '스트라이크 ' + ball + '볼', 'blue');
break;
}
}
}
// eventListener - 버튼 클릭시
button.addEventListener('click', guessNumber);
function logMessage
- 색상이름 (예> black, blue)에서 HEX 코드값으로 변경함.
- 정답일 때에는 bold와 font-size 를 크게.
지난번에는 eventListener가 버튼을 클릭할 떄 마다
guessNumber함수가 실행되도록 했다.
(form을 제출할 때를 기준으로도 만들 수 있다.
굳이 버튼 안누르고 enter키로도 가능하니까)
>> 이것은 지난번 크롬 클론코딩에서 했었다!
그러나, 한번 클릭할 때마다
정답인 수(answer)를 매번 다시 뽑으므로
이번에는 getNumber 함수를 추가해서
정답인 수는 한번만 뽑고,
guess는 10번까지 할 수 있도록 하였다. (while count <= 10)
___
또, count가 올라가지 않는 문제가 있었는데
이는 count = 1 이 guessNumber안에 있기 떄문에
이벤트리스너에 의해 매번 count=1로 초기화되기
때문이다.
따라서, count는 함수 밖으로 뺴서
default = 1로 하고,
(적어도 한번은 시도하고 맞춰야하니까)
>>> 이부분은 나중에 do~while문으로도 고칠 수 있을듯?
마지막 if-elseif-else문에서
정답이면 > count = 1에서 끝냄 (break)
정답 아니면 > count++ 하고나서 break. (다시 버튼 누르면 실행)
count 변수는 함수 밖에 있으므로 count가 계속 누적해서
올라갈 수 있다.
__
여기까지 해결하고 나니, 이제는 getNumber()에서
랜덤하게 뽑은 4자리수 (사실은 4개의 아이템을 가지는 배열)
, 즉 정답인 수를
guessNumber에 사용하지 못하게 되었다.
왜냐면 answer 변수는 getNumber 함수의 '지역객체' 이니까.
>> 나는 이 해결방법을 생각해보다가
localStorage를 일단 이용하였다.
지금도 이 방법을 잘 쓸지는 모르겠다만
다른 방법들도 있겠지만 우선 이걸 활용해보았다.
localStorage.setItem('key값', value);로 저장한 후에
나중에 불러올 떄에는
localStorge.getItem('key값'); 으로 하면 된다.
__
나머지는 이전과 동일하다.
아래 실행부에
getNumber();로 함수를 호출해 먼저 정답인 수를 뽑고
button.addEventListener('click', guessNumber);
로 버튼을 클릭할 때 마다 함수를 호출한다.
플레이 화면
** reference : www.zerocho.com
사담 👻
역시 프로젝트를 해봐야 실력이 늘 수 있구나 ㅡ 싶었다.
'PRACTICE > SELF' 카테고리의 다른 글
javaScript. 턴제 게임 - 텍스트 기반 RPG (上) (0) | 2022.01.30 |
---|---|
project. (js) 자동 텍스트 RPG 게임 - (수정) (0) | 2022.01.29 |
javaScript. 숫자야구게임 - 웹 ver. (1) | 2022.01.27 |
javaScript. 자동 텍스트 RPG 게임 (0) | 2022.01.27 |
javaScript. 숫자야구게임 - (2) (0) | 2022.01.19 |