<div class="container">
  <h1 class="text-center mt-5 mb-4">JavaScript Memory Game</h1>
  <h3 class="text-center mb-4" id="timer">Time left: 1:00</h3>
  <p class="text-center mt-4">
    Click on the cards to reveal their numbers and find matching pairs. If
    you find a match, the cards stay open; otherwise, they will be hidden
    again. The game ends when all pairs are matched. Watch the timer to
    track your time. Good luck!
  </p>

  <div class="wrapper" id="wrapper">
    <div class="card">
      <div class="card-front"></div>
      <div class="card-back"></div>
    </div>
    <div class="card">
      <div class="card-front"></div>
      <div class="card-back"></div>
    </div>
    <div class="card">
      <div class="card-front"></div>
      <div class="card-back"></div>
    </div>
    <div class="card">
      <div class="card-front"></div>
      <div class="card-back"></div>
    </div>
    <div class="card">
      <div class="card-front"></div>
      <div class="card-back"></div>
    </div>
    <div class="card">
      <div class="card-front"></div>
      <div class="card-back"></div>
    </div>
    <div class="card">
      <div class="card-front"></div>
      <div class="card-back"></div>
    </div>
    <div class="card">
      <div class="card-front"></div>
      <div class="card-back"></div>
    </div>
    <div class="card">
      <div class="card-front"></div>
      <div class="card-back"></div>
    </div>
    <div class="card">
      <div class="card-front"></div>
      <div class="card-back"></div>
    </div>
    <div class="card">
      <div class="card-front"></div>
      <div class="card-back"></div>
    </div>
    <div class="card">
      <div class="card-front"></div>
      <div class="card-back"></div>
    </div>
    <div class="card">
      <div class="card-front"></div>
      <div class="card-back"></div>
    </div>
    <div class="card">
      <div class="card-front"></div>
      <div class="card-back"></div>
    </div>
    <div class="card">
      <div class="card-front"></div>
      <div class="card-back"></div>
    </div>
    <div class="card">
      <div class="card-front"></div>
      <div class="card-back"></div>
    </div>

  </div>

  <div class="d-flex flex-column justify-content-center align-items-center position-absolute w-100 h-100" id="gameOverContainer">
    <h2 class="gameOver"></h2>
    <button class="btn btn-primary mt-4" id="restart">Play Again</button>
  </div>
</div>
@import url("https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap");
body {
  background-color: rgb(247, 248, 249);
  font-family: "DM Mono", monospace;
}
.wrapper {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  max-width: 400px;
  margin: 50px auto;
}
.card {
  width: 100px;
  height: 100px;
  perspective: 1000px;
  cursor: pointer;
  position: relative;
  transform-style: preserve-3d;
  transition: transform 0.6s;
}
.card.flipped {
  transform: rotateY(180deg);
}
.card-front,
.card-back {
  position: absolute;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid #000;
  font-size: 3rem;
  font-weight: 800;
}
.card-front {
  background-color: #fff;
  transform: rotateY(180deg);
}
.card-back {
  background-color: #3498db;
}

#gameOverContainer {
  visibility: hidden;
  opacity: 0;
  background-color: rgba(0, 0, 0, 0.5);
  top: 0;
  left: 0;
}
#gameOverContainer.show {
  visibility: visible;
  opacity: 1;
  transition: opacity 0.7s linear;
}
h2 {
  font-size: 3rem;
}
document.addEventListener("DOMContentLoaded", (event) => {
  const restart = document.getElementById("restart");
  const timerElement = document.getElementById("timer");
  const gameOverContainer = document.getElementById("gameOverContainer");
  const gameOverMessage = document.querySelector(".gameOver");

  let timerStarted = false;
  let clickedCards = [];
  let matchedCards = 0;
  
  const numbers = [...Array(2)].flatMap(() => [1, 2, 3, 4, 5, 6, 7, 8]);

  const cards = document.querySelectorAll(".card");

  let timer;
  let timeLeft = 60;

  restart.addEventListener("click", restartGame);

  function startTimer() {
    timer = setInterval(() => {
      timeLeft--;
      const minutes = Math.floor(timeLeft / 60);
      const seconds = timeLeft % 60;
      timerElement.textContent = `Time left: ${minutes}:${
        seconds < 10 ? "0" : ""
      }${seconds}`;

      if (timeLeft <= 0) {
        clearInterval(timer);
        endGame(false);
      }
    }, 1000);
  }

  function restartGame() {
    gameOverContainer.classList.remove("show");

    timeLeft = 60;
    timerElement.textContent = "Time left: 1:00";
    clearInterval(timer);
    timerStarted = false;
cards.forEach((card, index) => {
          card.querySelector(".card-front").textContent =
            shuffledNumbers[index];
          card.classList.remove("flipped");
        });
    

    clickedCards = [];
    matchedCards = 0;
  }

  function endGame(isWin) {
    console.log("endGame called with isWin:", isWin);
    gameOverMessage.textContent = isWin
      ? "Congratulations! You won!"
      : "You have failed!";
    gameOverMessage.style.color = isWin ? "#FFD700" : "red";
    gameOverContainer.classList.add("show");
  }

  const shuffledNumbers = [...numbers].sort(() => 0.5 - Math.random());
  cards.forEach((card, index) => {
    card.querySelector(".card-front").textContent = shuffledNumbers[index];
  });

  cards.forEach((card) => {
    card.addEventListener("click", () => {
      if (!timerStarted) {
        startTimer();
        timerStarted = true;
      }

      card.classList.add("flipped");
      clickedCards.push(card);

      if (clickedCards.length === 2) {
        if (
          clickedCards[0].querySelector(".card-front").textContent ===
          clickedCards[1].querySelector(".card-front").textContent
        ) {
          clickedCards = [];
          matchedCards += 2;
          if (matchedCards === cards.length) {
            clearInterval(timer);
            endGame(true);
          }
        } else {
          setTimeout(() => {
            clickedCards.forEach((card) => card.classList.remove("flipped"));
            clickedCards = [];
          }, 1000);
        }
      }
    });
  });
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.