새소식

알고리즘 테스트 ⏲/JavaScript

[JavaScript] 카드 맞추기 프로그램 구현

  • -
카드 맞추기 구현 문제

처음 12장의 카드를 잠깐 기억했다가 뒤집은 후 색상이 같은 2장의 카드를 짝지어 모든 카드를 맞추는 프로그램이다. 클릭했을 때 클릭한 카드의 패밀리 노드 중 특정한 클래스를 가진 노드들을 가져와 해당 노드의 색상을 비교해 맞추어가는 방식으로 동작한다. 구현에 어려움은 없었는데 parent와 child 노드를 왔다갔다 하는 부분들이 많다. 이 부분에 더 좋은 구현 방법이 있을 것 같은데.

개인풀이

다이어그램

알고리즘

const $cards = document.querySelectorAll(".card");
const $cardsFront = document.querySelectorAll(".card__face--front");
const colorPack = [
  "orange",
  "orange",
  "red",
  "red",
  "yellow",
  "yellow",
  "green",
  "green",
  "gray",
  "gray",
  "purple",
  "purple",
];
let startTime, endTime;
const shuffle = [];
while (colorPack.length > 0) {
  const random = Math.floor(Math.random() * colorPack.length);
  const spliceArray = colorPack.splice(random, 1);
  shuffle.push(spliceArray[0]);
}
for (let i = 0; i < shuffle.length; i++) {
  $cardsFront[i].style.backgroundColor = shuffle[i];
}
let cardClickFlag = false;
let clickedCards = [];
let matchedCard = 0;
const notMatchedCardFlip = (card1, card2) => {
  cardClickFlag = false;
  setTimeout(() => {
    card1.classList.toggle("is-flipped");
    card2.classList.toggle("is-flipped");
    cardClickFlag = true;
  }, 1000);
};
const handleCardClick = (e) => {
  if (!cardClickFlag) return;
  e.target.parentNode.classList.toggle("is-flipped");
  clickedCards.push(e.currentTarget.childNodes[3]); // .card__face--front
  clickedCards.forEach(
    (card) => card.parentNode.removeEventListener("click", handleCardClick) // .card
  );
  // 열린 2장의 카드 비교
  if (
    clickedCards.length === 2 &&
    clickedCards[0].style.backgroundColor ===
      clickedCards[1].style.backgroundColor
  ) {
    console.log("일치");
    clickedCards[0].parentNode.removeEventListener("click", handleCardClick);
    clickedCards[1].parentNode.removeEventListener("click", handleCardClick);
    matchedCard += 2;
    clickedCards = [];
    cardClickFlag = false;
    setTimeout(() => {
      cardClickFlag = true;
    }, 1000);
  } else if (clickedCards.length === 2) {
    console.log("불일치");

    notMatchedCardFlip(clickedCards[0].parentNode, clickedCards[1].parentNode);
    clickedCards.forEach((card) =>
      card.parentNode.addEventListener("click", handleCardClick)
    );
    clickedCards = [];
  }
  if (matchedCard === 12) {
    endTime = new Date().getTime() / 1000;
    let timeDiff =
      Math.round((endTime - startTime + Number.EPSILON) * 10000) / 10000;
    const $span = document.createElement("span");
    $span.textContent = `성공! ${timeDiff}초 만에 맞추었습니다.`;
    document.body.appendChild($span);
  }
};

const handleAllCardFlip = () => {
  for (let i = 0; i < shuffle.length; i++) {
    setTimeout(() => {
      $cards[i].classList.toggle("is-flipped");
    }, 100 * i);
  }
};
handleAllCardFlip();
const init = () => {
  setTimeout(() => {
    handleAllCardFlip();
  }, 3000);
  setTimeout(() => {
    cardClickFlag = true;
    startTime = new Date().getTime() / 1000;
  }, 3000);
};
$cards.forEach((card) => card.addEventListener("click", handleCardClick));
init();
<!DOCTYPE html>
<html lang="en">
  <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>Document</title>
    <style>
      main {
        display: grid;
        grid-template-columns: 80px 80px 80px 80px;
        grid-template-rows: 100px 100px 100px;
      }
      span {
        font-weight: bold;
      }
      .scene {
        float: left;
        margin: 3px 5px;
        perspective: 600px;
        box-sizing: border-box;
      }

      .card {
        width: 100%;
        height: 100%;
        transition: transform 1s;
        transform-style: preserve-3d;
        cursor: pointer;
        position: relative;
      }

      .card.is-flipped {
        transform: rotateY(180deg);
      }

      .card__face {
        border-radius: 8px;
        position: absolute;
        width: 100%;
        height: 100%;
        color: white;
        -webkit-backface-visibility: hidden;
        backface-visibility: hidden;
      }

      .card__face--back {
        background-color: rgb(37, 37, 37);
      }

      .card__face--front {
        background-color: none;
        transform: rotateY(180deg);
      }
    </style>
  </head>
  <body>
    <main src="gameTable">
      <div class="scene">
        <div class="card">
          <div class="card__face card__face--back"></div>
          <div class="card__face card__face--front"></div>
        </div>
      </div>
      <div class="scene">
        <div class="card">
          <div class="card__face card__face--back"></div>
          <div class="card__face card__face--front"></div>
        </div>
      </div>
      <div class="scene">
        <div class="card">
          <div class="card__face card__face--back"></div>
          <div class="card__face card__face--front"></div>
        </div>
      </div>
      <div class="scene">
        <div class="card">
          <div class="card__face card__face--back"></div>
          <div class="card__face card__face--front"></div>
        </div>
      </div>

      <div class="scene">
        <div class="card">
          <div class="card__face card__face--back"></div>
          <div class="card__face card__face--front"></div>
        </div>
      </div>
      <div class="scene">
        <div class="card">
          <div class="card__face card__face--back"></div>
          <div class="card__face card__face--front"></div>
        </div>
      </div>
      <div class="scene">
        <div class="card">
          <div class="card__face card__face--back"></div>
          <div class="card__face card__face--front"></div>
        </div>
      </div>
      <div class="scene">
        <div class="card">
          <div class="card__face card__face--back"></div>
          <div class="card__face card__face--front"></div>
        </div>
      </div>

      <div class="scene">
        <div class="card">
          <div class="card__face card__face--back"></div>
          <div class="card__face card__face--front"></div>
        </div>
      </div>
      <div class="scene">
        <div class="card">
          <div class="card__face card__face--back"></div>
          <div class="card__face card__face--front"></div>
        </div>
      </div>
      <div class="scene">
        <div class="card">
          <div class="card__face card__face--back"></div>
          <div class="card__face card__face--front"></div>
        </div>
      </div>
      <div class="scene">
        <div class="card">
          <div class="card__face card__face--back"></div>
          <div class="card__face card__face--front"></div>
        </div>
      </div>
    </main>
    <script src="index.js"></script>
  </body>
</html>
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.