-
JavaScript 입문 : 카드맞추기 게임 - 카드게임 수량 유저 선택하기, 총 걸린시간 계산하기컴퓨터 알아가기/JavaScript 2022. 10. 13. 19:30728x90반응형
이 글은 제로초 TV 자바스크립트 강좌를 기본으로 공부하고 있습니다.
현재까지 카드맞추기 게임을 만들면서 어느정도 버그가 수정이 되었다고 판단되어 조금 더 업그레이드를 해보고자 합니다. 첫번째는 카드의 수량을 최대치로 정해놓고 시작시 유저가 원하는 카드갯수를 입력하여 게임을 시작하고 최종적으로는 게임완료 시간을 계산하도록 하겠습니다.
1. 카드수량 정하기
게임 시작시 카드 수량을 입력하도록 만들겠습니다. 최대 20개까지 카드의 숫자를 만들도록 하고 이는 alert 메시지를 통하거나 버튼클릭으로 만들 수 있습니다.
주의할 점은 카드 2개가 같은 색이어야 하고 유저가 몇장을 선택할지 모르기 때문에 최대 20장의 반인 10장의 색상을 slice( ) 메소드로 나누어준 값을 concat( ) 메소드로 복사합니다.
20을 입력하면 다음과 같이 브라우저에 20개의 카드가 만들어집니다.
2. 게임시간 재기
카드맞추기 게임을 완성할때까지 시간을 체크하도록 하겠습니다. 게임시간 체크는 시작과 끝에 new Date( ) 메소드를 활용합니다.
시작점은 shuffle이 완료되고 다시 카드앞면으로 복귀했을때 클릭하는 순간부터 이고 끝나는 점은 'Mission Clear' 메시지가 뜨기전까지입니다.
먼저 변수 선언을 상단에 하고 시작과 끝에 변수를 만듭니다. 다음과 같습니다.
시작변수 만들기 시작점 만들기 끝점 만들기 상기 코드의결과를 보면 다음과 같이 반영됩니다. 편의상 4개로 해보았습니다.
3. resetGame( ) 수정
확인을 누르면 TypeError가 뜹니다. 이는 게임을 다시 시작하는 resetGame( )에서 알맞게 내용을 변경해줘야 합니다.
여기서 고려할 점은 게임을 다시 시작할 때 몇장의 카드로 할 건지 메시지를 나오게 하면서 겟수가 변하는 만큼 게임을 하도록 설정합니다.
주의할 점은 최초 total과 colors를 const로 변수를 만들었지만 이곳에서 다시 사용하기 위해 let로 변수를 만들고 resetGame( ) 함수 내역을 다음과 같이 만들어 줍니다.
이제 어느정도 카드맞추기 게임에 대한 코드를 완성하였습니다.
최종 완성된 코드는 다음을 참조 바랍니다.
4. 짝수만 입력하기
다 만들었다고 생각했는데 prompt 메시지에 짝수만 입력하라고 수정을 했지만 분명히 홀수를 입력하는 사람도 있을겁니다. 이럴경우를 대비하여 홀수 입력시 경고창과 다시 게임을 시작하도록 해 보겠습니다.
(초보라서 생각과 시간이 많이 걸리네요....)
이제 resetGame( )도 수정해 줍니다. 그럼 어느정도 완성이 된 것 같습니다. 향후 연습하면서 에러가 발견되면 계속 수정을 하는수 밖에 없네요.
전체코드를 공유합니다.
<!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>Card Flip Paring Game</title> <style> .container { display: inline-block; width: 80px; height: 100px; perspective: 150px; margin-right: 20px; margin-bottom: 20px; } .card { position: relative; width: 100%; height: 100%; transition: 0.8s; transform-style: preserve-3d; } .card-front { background-color: navy; } .card-back { transform: rotateY(180deg); } .card-front, .card-back { position: absolute; width: 100%; height: 100%; border: 1px solid black; backface-visibility: hidden; } .container.flipped .card { transform: rotateY(180deg); } </style> </head> <body> <div id="frame"></div> <script> const $frame = document.querySelector('#frame'); // 1. 카드 구성요소 // (self.1) alert 이용 갯수입력 let total = parseInt(prompt('최대 20개까지 카드갯수를 짝수만 입력')); if (total % 2 !== 0) { alert(`${total}은 홀수입니다.`); total = parseInt(prompt('최대 20개까지 카드갯수를 짝수만 입력')); } // (self.2) 10개 color 만들기 let colors = [ 'red', 'orange', 'yellow', 'green', 'pink', 'purple', 'teal', 'grey', 'maroon', 'indigo', ]; let colorSlice = colors.slice(0, total/2); let colorCopy = colorSlice.concat(colorSlice); // (self.3) 최대 20개라는 것은 10개도 고를수 있으니 slice로 나누어 줌 let clicked = []; // 2장 확인용 변수 let completed = []; // 완성카드 보관용 변수 // (버그수정1) 플래그 변수(O, X 변수) 사용 let clickable = false; // 1.1 기본값 클릭금지로 시작 // 2. 카드셔플 (Fisher-Yates Shuffle) let shuffled = []; // (self.4) 시간재기 변수선언 let startTime; function shuffle() { for (let i = 0; colorCopy.length > 0; i++) { const random = Math.floor(Math.random() * colorCopy.length); const spliceArray = colorCopy.splice(random, 1); shuffled.push(spliceArray[0]); // shuffled = shuffled.concat(colorCopy.splice(random, 1)); } } // 3. CSS 연계 카드 태그 만들기 function createCard(i) { const container = document.createElement('div'); container.className = 'container'; const card = document.createElement('div'); card.className = 'card'; const cardFront = document.createElement('div'); cardFront.className = 'card-front'; const cardBack = document.createElement('div'); cardBack.className = 'card-back'; cardBack.style.backgroundColor = shuffled[i]; card.append(cardFront); card.append(cardBack); container.append(card); return container; } // 7. onclickCard( ) 함수 기본형 function onclickCard() { // (버그수정 1.1.3) 1.1.2가 true로 지정했기에 클릭시 false로 if (clickable === false) return; // 클릭이 되지 않으면 return // (버그수정 2) 카드가 완성이 되면 return if (completed.includes(this)) { return; } // (버그수정 3) 동일한 카드 연달아 클릭방지 if (clicked[0] === this) { return } console.log(this); this.classList.toggle('flipped'); clicked.push(this); // 카드가 2장인가? if (clicked.length !== 2) { return; } // 색이 같은가? const firstColor = clicked[0].querySelector('.card-back').style.backgroundColor; const secondColor = clicked[1].querySelector('.card-back').style.backgroundColor; if (firstColor === secondColor) { // 완료 배열에 넣기 completed.push(clicked[0]); completed.push(clicked[1]); clicked = []; if (completed.length !== total) { // completed에 꽉 차는가 return; } // 완료되면 clear meassage // (self 4.2) const endTime = new Date(); setTimeout(() => { alert(`Mission clear!! ${(endTime - startTime) / 1000}초 걸림`); resetGame(); }, 1000); return; } // 색이 다르면 원상복귀 // (버그수정 4) 2장이 활성화되기까지 클릭을 막고 초기화되면 클릭가능 clickable = false; setTimeout(() => { clicked[0].classList.remove('flipped'); clicked[1].classList.remove('flipped'); clicked = []; clickable = true; // (버그수정 4.1) }, 500); } // 4. 카드게임 시작 함수 function startGame() { clickable = false; // (버그수정 1.1.1) shuffle되는 동안 클릭 금지 shuffle(); for (let i = 0; i < total; i++) { const container = createCard(i) container.addEventListener('click', onclickCard); // 7. $frame.append(container); } // 5. 1초후 0.1초 간격으로 card 뒤집기 (back보여주기) document.querySelectorAll('.container').forEach((container, index) => { setTimeout(() => { container.classList.add('flipped'); }, 1000 + 100 * index); }); // 6. 다 뒤집힌 후 2.8초 후 원상태로 돌아가기 (총 5초) document.querySelectorAll('.container').forEach((container, index) => { setTimeout(() => { container.classList.remove('flipped'); // (버그수정 1.1.2) 카드앞면으로 돌아가면 클릭가능 clickable = true; startTime = new Date(); // (self 4.1) }, 5000); }); } startGame(); // resetGame(), 전부 초기화 function resetGame() { $frame.innerHTML = ''; shuffled = []; completed = []; total = parseInt(prompt('최대 20개까지 카드갯수를 짝수만 입력')); if (total % 2 !== 0) { alert(`${total}은 홀수입니다.`); total = parseInt(prompt('최대 20개까지 카드갯수를 짝수만 입력')); } colors = [ 'red', 'orange', 'yellow', 'green', 'pink', 'purple', 'teal', 'grey', 'maroon', 'indigo', ]; colorSlice = colors.slice(0, total/2); colorCopy = colorSlice.concat(colorSlice); startGame(); } </script> </body> </html>
반응형'컴퓨터 알아가기 > JavaScript' 카테고리의 다른 글
JavaScript 입문 : 지뢰찾기 게임 - 기본적 HTML / CSS 만들기, 지뢰를 심기위한 랜덤숫자 뽑기 (0) 2022.10.25 JavaScript 입문 : 지뢰찾기 게임 - 순서도 (0) 2022.10.21 JavaScript 입문 : 카드맞추기 게임 - 이벤트루프를 통한 버그 수정 (동시 3번이상 클릭했을 경우 버그) (0) 2022.10.12 JavaScript 입문 : 이벤트루프 (Event Loop) 이해하기 2 - 3개요소(호출스택, 백그라운드, 태스크큐)를 이용한 테이블 이용하기 (2) 2022.10.11 JavaScript 입문 : 이벤트루프 (Event Loop) 이해하기 1 - 이론적 접근 (호출스택, 백그라운드, 태스크큐) (0) 2022.10.10