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 |1 Answer
Reset to default 1This 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.
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<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