Я делаю простую игру с перевернутыми карточками, которая блокирует карты в перевернутом положении, если две карты совпадают, и переключает их обратно в исходное положение, если они не совпадают. Когда первая пара карт переворачивается независимо от того, совпадают они или нет, игра работает правильно. Проблема в том, что при нажатии на третью карточку консоль возвращает ошибку:

«Uncaught TypeError: Невозможно прочитать свойство 'dataset', равное null, при checkForMatch в HTMLDivElement.flipCard»

Как я мог решить эту проблему?

// * Declaring Varaibles
// Get cards on the board
const cards = document.querySelectorAll(".card");
let isCardFlipped = false;
let lockBoard = false;
let firstCard, secondCard;

// * Functions
// Flips cards over
function flipCard() {
  if (lockBoard) return;
  if (this === firstCard) return;

  // Adding class name "flip" to all HTML elments with the class name "card"
  this.style.transform = "rotateY(180deg)";

  if (!isCardFlipped) {
    isCardFlipped = true;
    firstCard = this;

    return;
  }

  secondCard = this;
  checkForMatch();
}

// Checks to see if the cards match
function checkForMatch() {
  let isMatch = firstCard.dataset.monke === secondCard.dataset.monke;

  // isMatch ? disableCards() : unflipCards();

  if (isMatch) {
    disableCards();
  }
  else {
    unflipCards();
  }
}

// Locks the cards in place if they match
function disableCards() {
  firstCard.removeEventListener("click", flipCard);
  secondCard.removeEventListener("click", flipCard);

  resetBoard();
}

// Flips the cards back over if they don't match
function unflipCards() {
  lockBoard = true;

  setTimeout(() => {
    firstCard.style.transform = "";
    secondCard.style.transform = "";

    resetBoard();
  }, 1000);

}

// Resets the board
function resetBoard() {
  [hasFlippedCard, lockBoard] = [false, false];
  [firstCard, secondCard] = [null, null];
}

// * Event Listeners
// Event listener for all the cards
cards.forEach((item) => {
  item.addEventListener("click", flipCard);
});
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: "Londrina Solid", cursive;
}

body {
    background: linear-gradient(180deg, rgb(34, 179, 34), rgb(163, 126, 57));
    height: 100vh;
}

.container {
    padding: 1rem;
    width: 100%;
    height: 100%;
}

h1 {
    text-align: center;
    margin-bottom: 2rem;
    font-size: 3rem;
    color: #000;
}

.row {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    margin: 2rem;
    padding-top: 1rem;
}

.card-container {
    position: relative;
    margin: auto;
    width: 150px;
    height: 200px;
}

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

.front-face {
    position: absolute;
    backface-visibility: hidden;
    height: 100%;
    width: 100%;
    background: rgb(244, 238, 86);
    border-radius: 10px;
}

.back-face {
    position: absolute;
    backface-visibility: hidden;
    transform: rotateY(180deg);
}

.pic-container {
    height: 200px;
    width: 150px;
}

img {
    height: 100%;
    width: 100%;
    border-radius: 10px;
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="preconnect" href="https://fonts.gstatic.com">
  <link href="https://fonts.googleapis.com/css2?family=Londrina+Solid&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="style.css">
  <title>Matching Game</title>
</head>
<body>
  <div class="container">
    <h1>Monke Matching Game</h1>
    <div class="row">
      <div class="card-container">
        <div class="card" data-monke="gorilla">
          <div class="front-face">
            <img src="img/Banna-cartoon.png" alt="">
          </div>
          <div class="back-face">
            <div class="pic-container">
              <img src="img/monke1.jpg" alt="">
            </div>
          </div>
        </div>
      </div>
      <div class="card-container">
        <div class="card" data-monke="gorilla">
          <div class="front-face">
            <img src="img/Banna-cartoon.png" alt="">
          </div>
          <div class="back-face">
            <div class="pic-container">
              <img src="img/monke1.jpg" alt="">
            </div>
          </div>
        </div>
      </div>
      <div class="card-container">
        <div class="card" data-monke="chimp">
          <div class="front-face">
            <img src="img/Banna-cartoon.png" alt="">
          </div>
          <div class="back-face">
            <div class="pic-container">
              <img src="img/monke2.jpg" alt="">
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="card-container">
        <div class="card" data-monke="chimp">
          <div class="front-face">
            <img src="img/Banna-cartoon.png" alt="">
          </div>
          <div class="back-face">
            <div class="pic-container">
              <img src="img/monke2.jpg" alt="">
            </div>
          </div>
        </div>
      </div>
      <div class="card-container">
        <div class="card" data-monke="baby">
          <div class="front-face">
            <img src="img/Banna-cartoon.png" alt="">
          </div>
          <div class="back-face">
            <div class="pic-container">
              <img src="img/monke3.jpg" alt="">
            </div>
          </div>
        </div>
      </div>
      <div class="card-container">
        <div class="card" data-monke="baby">
          <div class="front-face">
            <img src="img/Banna-cartoon.png" alt="">
          </div>
          <div class="back-face">
            <div class="pic-container">
              <img src="img/monke3.jpg" alt="">
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>


  <script src="app.js"></script>
</body>
</html>
2
Zanto 25 Фев 2021 в 02:54

2 ответа

Лучший ответ

Вы забываете установить isCardFlipped в значение false после того, как карты переворачиваются или отключаются.

// * Declaring Varaibles
// Get cards on the board
const cards = document.querySelectorAll(".card");
let isCardFlipped = false;
let lockBoard = false;
let firstCard, secondCard;

// * Functions
// Flips cards over
function flipCard() {
  if (lockBoard) return;
  if (this === firstCard) return;

  // Adding class name "flip" to all HTML elments with the class name "card"
  this.style.transform = "rotateY(180deg)";

  if (!isCardFlipped) {
    isCardFlipped = true;
    firstCard = this;

    return;
  }

  secondCard = this;
  checkForMatch();
}

// Checks to see if the cards match
function checkForMatch() {
  let isMatch = firstCard.dataset.monke === secondCard.dataset.monke;
  // isMatch ? disableCards() : unflipCards();

  if (isMatch) {
    disableCards();
  }
  else {
    unflipCards();
  }
}

// Locks the cards in place if they match
function disableCards() {
  firstCard.removeEventListener("click", flipCard);
  secondCard.removeEventListener("click", flipCard);
  isCardFlipped = false;
  resetBoard();
}

// Flips the cards back over if they don't match
function unflipCards() {
  lockBoard = true;
  isCardFlipped = false;
  setTimeout(() => {
    firstCard.style.transform = "";
    secondCard.style.transform = "";

    resetBoard();
  }, 1000);

}

// Resets the board
function resetBoard() {
  [hasFlippedCard, lockBoard] = [false, false];
  [firstCard, secondCard] = [null, null];
}

// * Event Listeners
// Event listener for all the cards
cards.forEach((item) => {
  item.addEventListener("click", flipCard);
});
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: "Londrina Solid", cursive;
}

body {
    background: linear-gradient(180deg, rgb(34, 179, 34), rgb(163, 126, 57));
    height: 100vh;
}

.container {
    padding: 1rem;
    width: 100%;
    height: 100%;
}

h1 {
    text-align: center;
    margin-bottom: 2rem;
    font-size: 3rem;
    color: #000;
}

.row {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    margin: 2rem;
    padding-top: 1rem;
}

.card-container {
    position: relative;
    margin: auto;
    width: 150px;
    height: 200px;
}

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

.front-face {
    position: absolute;
    backface-visibility: hidden;
    height: 100%;
    width: 100%;
    background: rgb(244, 238, 86);
    border-radius: 10px;
}

.back-face {
    position: absolute;
    backface-visibility: hidden;
    transform: rotateY(180deg);
}

.pic-container {
    height: 200px;
    width: 150px;
}

img {
    height: 100%;
    width: 100%;
    border-radius: 10px;
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="preconnect" href="https://fonts.gstatic.com">
  <link href="https://fonts.googleapis.com/css2?family=Londrina+Solid&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="style.css">
  <title>Matching Game</title>
</head>
<body>
  <div class="container">
    <h1>Monke Matching Game</h1>
    <div class="row">
      <div class="card-container">
        <div class="card" data-monke="gorilla">
          <div class="front-face">
            <img src="img/Banna-cartoon.png" alt="">
          </div>
          <div class="back-face">
            <div class="pic-container">
              <img src="img/monke1.jpg" alt="">
            </div>
          </div>
        </div>
      </div>
      <div class="card-container">
        <div class="card" data-monke="gorilla">
          <div class="front-face">
            <img src="img/Banna-cartoon.png" alt="">
          </div>
          <div class="back-face">
            <div class="pic-container">
              <img src="img/monke1.jpg" alt="">
            </div>
          </div>
        </div>
      </div>
      <div class="card-container">
        <div class="card" data-monke="chimp">
          <div class="front-face">
            <img src="img/Banna-cartoon.png" alt="">
          </div>
          <div class="back-face">
            <div class="pic-container">
              <img src="img/monke2.jpg" alt="">
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="card-container">
        <div class="card" data-monke="chimp">
          <div class="front-face">
            <img src="img/Banna-cartoon.png" alt="">
          </div>
          <div class="back-face">
            <div class="pic-container">
              <img src="img/monke2.jpg" alt="">
            </div>
          </div>
        </div>
      </div>
      <div class="card-container">
        <div class="card" data-monke="baby">
          <div class="front-face">
            <img src="img/Banna-cartoon.png" alt="">
          </div>
          <div class="back-face">
            <div class="pic-container">
              <img src="img/monke3.jpg" alt="">
            </div>
          </div>
        </div>
      </div>
      <div class="card-container">
        <div class="card" data-monke="baby">
          <div class="front-face">
            <img src="img/Banna-cartoon.png" alt="">
          </div>
          <div class="back-face">
            <div class="pic-container">
              <img src="img/monke3.jpg" alt="">
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>


  <script src="app.js"></script>
</body>
</html>
2
maziyank 25 Фев 2021 в 00:19

Настольная игра сбрасывается после события onclick, она вызывает эту функцию resetBoard() и устанавливает переменные firstCard в null. Во время следующего события переменная будет null.

Удалить эту строку

// Resets the board
function resetBoard() {
  [hasFlippedCard, lockBoard] = [false, false];
  //[firstCard, secondCard] = [null, null];
}
2
jTorleon 25 Фев 2021 в 00:42