最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Memory game code works but only if tiles are clicked slowly, if tiles are clicked too fast game breaks - Stack Over

programmeradmin4浏览0评论

const cards = document.querySelectorAll('.card')
let clickCount = 0
let id = []
let matched = 0

function shuffle() {
  cards.forEach(card => {
    let pos = Math.floor(Math.random() * 12);
    card.style.order = pos
  })
}

shuffle()

function checkMatch() {
  if (id[0] == id[1]) {
    return true
  } else {
    return false
  }
}


cards.forEach(card => {
  card.addEventListener('click', () => {
    card.innerHTML = card.id
    id.push(card.id)
    card.setAttribute('open', 'true')
    clickCount += 1
    console.log(clickCount)
    if (clickCount == 2) {
      let result = checkMatch()
      clickCount = 0
      if (result == false) {
        id = []
        setTimeout(() => {
          document.querySelectorAll('[open="true"]').forEach((card) => {
            card.innerHTML = '';
            card.removeAttribute('open', 'true')
          })
        }, 100)
      } else {
        console.log('matched')
        id = []
        document.querySelectorAll('[open="true"]').forEach((card) => {
          card.removeAttribute('open', 'true');
          card.replaceWith(card.cloneNode(true))
        })
        matched += 2
      }
    }
    if (matched == 16) {
      console.log('You win')
    }
  })
})
<!DOCTYPE html>
<html>

<body style="justify-self:center;">
  <h1 style="justify-self:center">Memory Game</h1>
  <div id="cont" style="width:px">
    <p class="stats" style="justify-self:center ;"></p>
    <div class='cardContainer' style="justify-self:center ;">
      <div class='card' id="1"></div>
      <div class='card' id="1"></div>
      <div class='card' id="2"></div>
      <div class='card' id="2"></div>
      <div class='card' id="3"></div>
      <div class='card' id="3"></div>
      <div class='card' id="4"></div>
      <div class='card' id="4"></div>
      <div class='card' id="5"></div>
      <div class='card' id="5"></div>
      <div class='card' id="6"></div>
      <div class='card' id="6"></div>
      <div class='card' id="7"></div>
      <div class='card' id="7"></div>
      <div class='card' id="8"></div>
      <div class='card' id="8"></div>
    </div>
    <div style="justify-self:center ;"><button id="reset" style="margin-top: 20px; ">Reset Game</button></div>
    <script src="mg.js"></script>
  </div>
</body>


</html>

const cards = document.querySelectorAll('.card')
let clickCount = 0
let id = []
let matched = 0

function shuffle() {
  cards.forEach(card => {
    let pos = Math.floor(Math.random() * 12);
    card.style.order = pos
  })
}

shuffle()

function checkMatch() {
  if (id[0] == id[1]) {
    return true
  } else {
    return false
  }
}


cards.forEach(card => {
  card.addEventListener('click', () => {
    card.innerHTML = card.id
    id.push(card.id)
    card.setAttribute('open', 'true')
    clickCount += 1
    console.log(clickCount)
    if (clickCount == 2) {
      let result = checkMatch()
      clickCount = 0
      if (result == false) {
        id = []
        setTimeout(() => {
          document.querySelectorAll('[open="true"]').forEach((card) => {
            card.innerHTML = '';
            card.removeAttribute('open', 'true')
          })
        }, 100)
      } else {
        console.log('matched')
        id = []
        document.querySelectorAll('[open="true"]').forEach((card) => {
          card.removeAttribute('open', 'true');
          card.replaceWith(card.cloneNode(true))
        })
        matched += 2
      }
    }
    if (matched == 16) {
      console.log('You win')
    }
  })
})
<!DOCTYPE html>
<html>

<body style="justify-self:center;">
  <h1 style="justify-self:center">Memory Game</h1>
  <div id="cont" style="width:px">
    <p class="stats" style="justify-self:center ;"></p>
    <div class='cardContainer' style="justify-self:center ;">
      <div class='card' id="1"></div>
      <div class='card' id="1"></div>
      <div class='card' id="2"></div>
      <div class='card' id="2"></div>
      <div class='card' id="3"></div>
      <div class='card' id="3"></div>
      <div class='card' id="4"></div>
      <div class='card' id="4"></div>
      <div class='card' id="5"></div>
      <div class='card' id="5"></div>
      <div class='card' id="6"></div>
      <div class='card' id="6"></div>
      <div class='card' id="7"></div>
      <div class='card' id="7"></div>
      <div class='card' id="8"></div>
      <div class='card' id="8"></div>
    </div>
    <div style="justify-self:center ;"><button id="reset" style="margin-top: 20px; ">Reset Game</button></div>
    <script src="mg.js"></script>
  </div>
</body>


</html>

If i click the tiles slowly and play the game the game works properly. However if i were to try and randomly click tiles super fast, one of the clicked tiles declare itself as matched and stays open even thought it hasn't matched. How do I fix this.

User will start the game by clicking on one of the tile(card divs). Once the first tile is clicked it will stay open, then user will have to click on a second tile. If the tiles match (id match), they will stay open. If not, the tile that was clicked second will open for 100ms (setTimeout is used for this), then both tiles will close. If the two tiles match, both tiles will stay open and their event listener is removed, +2 will be added to the value of matched variable. Once matched variable hits 16, the game will stop. [1]: https://i.sstatic/65H9nyzB.png

Share Improve this question edited Mar 24 at 18:08 Mark Schultheiss 34.2k12 gold badges72 silver badges113 bronze badges asked Mar 22 at 2:40 thiyaharajan rajkumarthiyaharajan rajkumar 53 bronze badges 5
  • Can you please explain (in the body of your question) what you hope to achieve by using the setTimeout and why it's there? You can edit to provide additional details. You should explain what the expected results are. We don't know what "works properly" is unless you explain the intended behaviour. – Wyck Commented Mar 22 at 3:37
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Bot Commented Mar 22 at 4:14
  • 1 You need to ignore any clicks that occur during a timeout as that is designed to show the user (briefly) what two cards they have clicked, so set a flag just before you set the time out and clear it in the timeout code. – A Haworth Commented Mar 22 at 5:48
  • 2 Just to note that ids ought to be unique. Use e.g. a data-id attribute instead. – A Haworth Commented Mar 22 at 6:10
  • Voting to close this as your HTML is invalid with duplicate ID properties which thus produces that invalid HTML Note when you click the ONLY button here in when this runs this does nothing at present also <script src="mg.js"></script> this we can only assume is the in-line JS you provide and can ignore? – Mark Schultheiss Commented Mar 24 at 18:51
Add a comment  | 

1 Answer 1

Reset to default 1

This snippet tests whether you are already in a timeout and if so it does nothing so as to give time for the previous matching/non-matching to complete.

It does this by setting a flag - inTimeout.

<!DOCTYPE html>
<html>

<head>
  <style>
    .cardContainer {
      display: flex;
      gap: 10px;
      flex-direction: row;
    }

    .card {
      width: 50px;
      height: 100px;
      border: solid 2px blue;
    }
  </style>
</head>

<body>
  <h1>Memory Game</h1>
  <div id="cont">
    <p class="stats"></p>
    <div class='cardContainer'>
      <div class='card' data-id="1"></div>
      <div class='card' data-id="1"></div>
      <div class='card' data-id="2"></div>
      <div class='card' data-id="2"></div>
      <div class='card' data-id="3"></div>
      <div class='card' data-id="3"></div>
      <div class='card' data-id="4"></div>
      <div class='card' data-id="4"></div>
      <div class='card' data-id="5"></div>
      <div class='card' data-id="5"></div>
      <div class='card' data-id="6"></div>
      <div class='card' data-id="6"></div>
      <div class='card' data-id="7"></div>
      <div class='card' data-id="7"></div>
      <div class='card' data-id="8"></div>
      <div class='card' data-id="8"></div>
    </div>

    <div style="justify-self:center ;"><button id="reset" style="margin-top: 20px; ">Reset Game</button></div>
    <script src="mg.js"></script>
  </div>
  <script>
    const cards = document.querySelectorAll('.card')
    let clickCount = 0
    let id = []
    let matched = 0
    let inTimeout = false;

    function shuffle() {
      cards.forEach(card => {
        let pos = Math.floor(Math.random() * 12);
        card.style.order = pos
      })
    }

    shuffle()

    function checkMatch() {
      if (id[0] == id[1]) {
        return true
      } else {
        return false
      }
    }


    cards.forEach(card => {
      card.addEventListener('click', () => {
        card.innerHTML = card.getAttribute('data-id');
        id.push(card.innerHTML)
        card.setAttribute('open', 'true')
        clickCount += 1
        console.log(clickCount)
        if (clickCount == 2) {
          let result = checkMatch()
          clickCount = 0
          if (!inTimeout) {
            if (result == false) {
              inTimeout = true;
              id = []
              setTimeout(() => {
                inTimeout = false;
                document.querySelectorAll('[open="true"]').forEach((card) => {
                  card.innerHTML = '';
                  card.removeAttribute('open', 'true')
                })
              }, 1000)

            } else {
              console.log('matched')
              id = []
              document.querySelectorAll('[open="true"]').forEach((card) => {
                card.removeAttribute('open', 'true');
                card.replaceWith(card.cloneNode(true))
              })
              matched += 2
            }
          }
        }
        if (matched == 16) {
          console.log('You win')
        }
      })
    })
  </script>
</body>


</html>

Note: the timeout has been increased to 1second simply to make it easier to test fast clicking.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论