<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="style.css" />
    <title>Project #17 - Memory Card Game</title>
  </head>
  <body>
    <section class="memory-game">
      <!-- 1st Card -->
      <div class="memory-card" data-name="baby-bear">
        <img src="https://cdn.pixabay.com/photo/2014/01/22/19/44/flower-field-250016_960_720.jpg" alt="animal" class="front-face" />
        <img src="https://cdn.pixabay.com/photo/2019/09/29/22/06/light-bulb-4514505_960_720.jpg" alt="?" class="back-face" />
      </div>

      <!-- 2nd Card -->
      <div class="memory-card" data-name="baby-bear">
        <img src="https://cdn.pixabay.com/photo/2014/01/22/19/44/flower-field-250016_960_720.jpg" alt="animal" class="front-face" />
        <img src="https://cdn.pixabay.com/photo/2019/09/29/22/06/light-bulb-4514505_960_720.jpg" alt="?" class="back-face" />
      </div>

      <!-- 3rd Card -->
      <div class="memory-card" data-name="bird">
        <img src="https://cdn.pixabay.com/photo/2013/08/22/19/18/flowers-174817_960_720.jpg" alt="animal" class="front-face" />
        <img src="https://cdn.pixabay.com/photo/2019/09/29/22/06/light-bulb-4514505_960_720.jpg" alt="?" class="back-face" />
      </div>

      <!-- 4th Card -->
      <div class="memory-card" data-name="bird">
        <img src="https://cdn.pixabay.com/photo/2013/08/22/19/18/flowers-174817_960_720.jpg" alt="animal" class="front-face" />
        <img src="https://cdn.pixabay.com/photo/2019/09/29/22/06/light-bulb-4514505_960_720.jpg" alt="?" class="back-face" />
      </div>

      <!-- 5th Card -->
      <div class="memory-card" data-name="cat">
        <img src="https://cdn.pixabay.com/photo/2013/07/21/13/00/rose-165819_960_720.jpg" alt="animal" class="front-face" />
        <img src="https://cdn.pixabay.com/photo/2019/09/29/22/06/light-bulb-4514505_960_720.jpg" alt="?" class="back-face" />
      </div>

      <!-- 6th Card -->
      <div class="memory-card" data-name="cat">
        <img src="https://cdn.pixabay.com/photo/2013/07/21/13/00/rose-165819_960_720.jpg" alt="animal" class="front-face" />
        <img src="https://cdn.pixabay.com/photo/2019/09/29/22/06/light-bulb-4514505_960_720.jpg" alt="?" class="back-face" />
      </div>

      <!-- 7th Card -->
      <div class="memory-card" data-name="curious-cat">
        <img src="https://cdn.pixabay.com/photo/2016/11/29/01/10/kitten-1866475_960_720.jpg" alt="animal" class="front-face" />
        <img src="https://cdn.pixabay.com/photo/2019/09/29/22/06/light-bulb-4514505_960_720.jpg" alt="?" class="back-face" />
      </div>

      <!-- 8th Card -->
      <div class="memory-card" data-name="curious-cat">
        <img src="https://cdn.pixabay.com/photo/2016/11/29/01/10/kitten-1866475_960_720.jpg" alt="animal" class="front-face" />
        <img src="https://cdn.pixabay.com/photo/2019/09/29/22/06/light-bulb-4514505_960_720.jpg" alt="?" class="back-face" />
      </div>

      <!-- 9th Card -->
      <div class="memory-card" data-name="dog">
        <img src="https://cdn.pixabay.com/photo/2021/10/19/10/56/cat-6723256_960_720.jpg" alt="animal" class="front-face" />
        <img src="https://cdn.pixabay.com/photo/2019/09/29/22/06/light-bulb-4514505_960_720.jpg" alt="?" class="back-face" />
      </div>

      <!-- 10th Card -->
      <div class="memory-card" data-name="dog">
        <img src="https://cdn.pixabay.com/photo/2021/10/19/10/56/cat-6723256_960_720.jpg" alt="animal" class="front-face" />
        <img src="https://cdn.pixabay.com/photo/2019/09/29/22/06/light-bulb-4514505_960_720.jpg" alt="?" class="back-face" />
      </div>

      <!-- 11th Card -->
      <div class="memory-card" data-name="hamster">
        <img src="https://cdn.pixabay.com/photo/2016/03/28/10/05/kitten-1285341_960_720.jpg" alt="animal" class="front-face" />
        <img src="https://cdn.pixabay.com/photo/2019/09/29/22/06/light-bulb-4514505_960_720.jpg" alt="?" class="back-face" />
      </div>

      <!-- 12th Card -->
      <div class="memory-card" data-name="hamster">
        <img src="https://cdn.pixabay.com/photo/2016/03/28/10/05/kitten-1285341_960_720.jpg" alt="animal" class="front-face" />
        <img src="https://cdn.pixabay.com/photo/2019/09/29/22/06/light-bulb-4514505_960_720.jpg" alt="?" class="back-face" />
      </div>
    </section>

    <!-- -------------------------------- -->
    <!-- JS File -->
    <script src="app.js"></script>
  </body>
</html>
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

body {
  min-height: 100vh;

  display: flex;
  align-items: center;
  justify-content: center;
}

.memory-game {
  height: 650px;
  width: 1200px;

  display: flex;
  flex-wrap: wrap;
}

.memory-card {
  width: calc(25% - 10px);
  height: calc(33.3333% - 10px);
  margin: 5px;
  position: relative;
  transform: scale(1);
  transform-style: preserve-3d;
  transition: transform 0.3s ease-out;
}

.front-face,
.back-face {
  height: 100%;
  width: 100%;
  position: absolute;
  object-fit: cover;
  /* 뒤집혔을때 앞뒷면이 서로 겹치지 않도록 한 면은 숨겨놓는다. */
  backface-visibility: hidden;
}

.memory-card:active {
  /* 카드를 누르면 크기가 조금 작아지며 눌리는 효과냄. */
  transform: scale(0.97);
  transition: transform 0.15s ease-out;
}

/* 카드를 180도 회전 turn은 단위. */
.front-face {
  transform: rotateY(0.5turn);
}

/* Dynamic Class */
.memory-card.flip {
  /* perspective 값이 작을수록화면과 가까이 있다는 뜻. 즉 변화가 커진다.*/
  transform: rotateY(180deg) perspective(1000px);
}
const cards = document.querySelectorAll(".memory-card");

let cardIsFlipped = false;
//카드 두개를 확인하는 동안에는 다른 카드들을 열수 없도록 화면 잠그기.
let lockBoard = false;
let firstCard, secondCard;

function flipCard() {
  //세번째 카드를 열수 없도록 함.
  if (lockBoard) return;
  //처음 누른 카드를 또 누르면 아무 작용도 없이 리턴.
  //이렇게 안하면 더블 클릭으로 같은 카드를 누르면 그 이름이 같으므로 카드가 일치하게 되어 화면에 남게 된다. 
  if (this === firstCard) return;

  // this.classList.toggle("flip");
  this.classList.add("flip");

  if (!cardIsFlipped) {
    //카드가 눌린 적 없는 첫번째 클릭. 첫 카드
    cardIsFlipped = true;
    firstCard = this;
    return;
  }
  // 두번째 클릭 , 두번째 카드.
  secondCard = this;

  checkForMatch();
}

//카드가 맞는지 확인.
function checkForMatch() {
  let isMatched = firstCard.dataset.name === secondCard.dataset.name;
  isMatched ? disableCards() : unFlipCards();
}

//카드가 서로 맞으면. 카드 비활성화 (더이상 클릭 이벤트가 없도록.)
function disableCards() {
  firstCard.removeEventListener("click", flipCard);
  secondCard.removeEventListener("click", flipCard);

  resetBoard();
}

//카드가 틀리면 , 일정 시간이 지난 후에 뒤집힌 상태가 없어져서 다시 뒷면으로 뒤집히게 된다. 
function unFlipCards() {
  lockBoard = true;

  setTimeout(() => {
    firstCard.classList.remove("flip");
    secondCard.classList.remove("flip");
    resetBoard();
  }, 1500);
}

function resetBoard() {
  //구조 분해 할당으로 리셋
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
  [cardIsFlipped, lockBoard] = [false, false];
  [firstCard, secondCard] = [null, null];
}

// IIFE -> Immediately Invoked Function Expression => 즉시 실행 함수 => 함수가 정의된 바로 직후에 실행.
//화면을 새로고침만해도, 즉시 셔플이 실행됨.
(function shuffle() {
  cards.forEach(function (card) {
    let randomPositions = Math.floor(Math.random() * 12);
    card.style.order = randomPositions;
  });
})();

cards.forEach(function (card) {
  card.addEventListener("click", flipCard);
});
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.