ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JavaScript 입문 : 카드맞추기 게임 - 카드뒤집기(setTimeout( )이용), 클릭이벤트 (onclickCard 함수) 만들기 (2)
    컴퓨터 알아가기/JavaScript 2022. 10. 6. 19:30
    728x90
    반응형

    지난시간 이어서 카드 짝 맞추기에 대한 본격적인 코드를 공부해 보도록 하겠습니다. 

     

    참고로 본 글은 제로초 TV 자바스크립트 강좌를 참고로 하고 있습니다. 

     

    다시 순서도를 보겠습니다. 순서도 상 다음 주황색 영역을 만들어 보고자 합니다. 

     

     

     

    1. 카드 짝 맞추기 

     

    이제부터는 본격적으로 뒤집힌 카드가 2장인지 여부와 2장이 색이 다르면 다시 카드앞면으로 돌아가고 같은 색이면 완료배열에 넣고 return하는 프로그램을 만들도록 하겠습니다. 아래 코드는 onclickCard(  ) 함수내에서 이루어지는 코드입니다. 

     

    ① 카드가 2장인가

     

    보통 코드의 기본을 만들때 반대로 하더군요. 즉, 카드가 2장인가의 코드는 카드가 2장이 아니면으로 하는게 풀어가는게 쉽습니다. 

     

     

    ② 같은색인가

     

    clicked에 넣은 색상이 첫번째 카드와 두번째 카드가 같으완료배열에 넣고 12개가 다차면 return합니다. 여기서 포인트는 완료배열에 2장씩 들어가는데 이때마다 2장씩 비교하는 clicked배열은 초기화 시킵니다. 

     

     

    ③ 다른색이면 카드앞면으로 복귀

     

    다음과 같이 코드를 만들 수 있습니다.

     

     

    그런데 문제점이 발생이 되었네요. 첫번째 카드를 클릭하고 두번째 카드를 클릭하고자 했을때 첫번째 카드가 바로 원상복귀됩니다. 이는 색이 다른경우 clicked[0]과 clicked[1]이 동시에 일어나는 현상인데요. 이를 해결하기 위해서 약간의 시간을 둬야 합니다. setTimeout(  ) 메소드를 이용합니다. 

     

     

    약 0.5초의 시간차이를 두었습니다. 

     

    이제 작동이 잘 됩니다. 

     

    ④ MIssion Clear

     

    카드 12개가 색이 다 맞으면 completed 배열이 꽉 차게 되면서 게임이 끝나게 됩니다. alert 메시지로 Mission Clear라는 메시지를 나타내도록 하겠습니다. 

     

     

    브라우저에서 작동이 잘 됩니다. 

     

     

    여기까지 onclickCard(  ) 함수의 코드는 아래를 참조하세요.

     

    // 7. onclickCard( ) 함수 기본형
          function onclickCard() {
            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                
              alert('Mission clear!!');    
              resetGame();          
              return;          
            } 
            // 색이 다르면 원상복귀   
            setTimeout(() => {
              clicked[0].classList.remove('flipped');
              clicked[1].classList.remove('flipped');
              clicked = [];
            }, 500);
          }

     

    카드맞추기 게임에 대한 전체코드는 다음과 같습니다. 

     

    <!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. 카드 구성요소
        const total = 12;
        const colors = ['red', 'orange', 'yellow', 'green', 'pink', 'purple'];
        let colorCopy = colors.concat(colors); // 복사를 통하여 12개 만들기
    
        let clicked = []; // 2장 확인용 변수
        let completed = []; // 완성카드 보관용 변수
    
        // 2. 카드셔플 (Fisher-Yates Shuffle)
        let shuffled = [];
    
        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() {
            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                
              alert('Mission clear!!');    
              resetGame();          
              return;          
            } 
            // 색이 다르면 원상복귀   
            setTimeout(() => {
              clicked[0].classList.remove('flipped');
              clicked[1].classList.remove('flipped');
              clicked = [];
            }, 500);
          }
    
        // 4. 카드게임 시작 함수
        function startGame() {
          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');        
            }, 5000);
          });
        }
    
        startGame();
    
      </script>
      
    </body>
    </html>

     

    지금까지 일반적인 카드맞추기 게임을 완성 시켰는데요. 다음 시간부터는 각종 버그를 수정할 차례입니다. 게임이라는 것은 정상적인 클릭방법이 있겠지만 다양한 케이스를 고민해서 가능한 완벽하게 프로그램을 만드는 과정에 있습니다. 이러한 버그를 수정해 나가면서 자바스크립트에서 가장 중요한 이론 중 하나인 이벤트 루프(Event Loop)에 대한 부분도 이해를 해 보고자 합니다. 

    반응형

    댓글

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
Designed by Tistory.