Hi there,
I’ve got a simple Memory Card Game that I’ve created using pure JavaScript (i.e. no jQuery). The problem I’ve got is that the cards are clickable even while they’re being checked which causes problems when you select another card - it counts a click on one of the “checking in progress” cards as a click, and tries to match it with the “third” card you click. This results in a reset and a bit of confusing game mechanic.
Therefore, while the cards are being compared, I have attempted to set Pointer Events to none on the selected cards. (and reset the Pointer Events back to “visible” once the comparison is complete). This works perfectly in all browsers except Internet Explorer 10 (and below), and Safari (both desktop and iOS versions).
Is there an alternative I can use, or is there a better method to what I’m trying to do?
Below in the We Transfer are all of the files (HTML, CSS, JS and all the images used for the tiles). Included below is the raw JS in code tags.
cardMatchGame();
function cardMatchGame() {
this.gameboard = document.getElementById("ws-game-board");
this.gameWidth = 4;
this.gameHeight = 4;
this.firstCard = null;
this.secondCard = null;
this.turn = 0;
this.matches = 0;
this.checkTimeout = null;
this.sec = 0;
function pad(val) {
return val > 9 ? val : "0" + val;
}
this.timer = setInterval(function () {
document.getElementById("minutes").innerText = pad(parseInt(sec / 60, 10));
document.getElementById("seconds").innerText = pad(++sec % 60);
if (document.getElementById("minutes").innerText >= "60") {
document.getElementById("seconds").innerText = "00";
gameEnd();
}
}, 1000);
this.turnUpdate = function () {
turnDisplay = document.getElementsByClassName("ws-turn-display"); // Find the elements
for (var i = 0; i < turnDisplay.length; i++) {
turnDisplay[i].innerText = turn; // Change the content
}
}
this.createGrid = function (h, v) {
var a = [];
// create squares within the grid and push the values into an array
for (var i = 0; i < gameWidth * gameHeight / 2; i++) {
a.push(i);
a.push(i);
}
// create a randomised array of numbers using the contents of the "a" array created above
// remove this value from the "a" array ready for the next number
var s = [];
while (a.length > 0) {
var r = Math.floor(Math.random() * a.length);
s.push(a[r]);
a.splice(r, 1);
}
// create the grid using the "s" array
for (var x = 0; x < h; x++) {
for (var y = 0; y < v; y++) {
createCard(s.pop(), x, y);
}
}
}
this.createCard = function (cardNum, posX, posY) {
var card = document.createElement("img");
card.num = cardNum;
card.src = "images/xmas18_memorygame_tileback.jpg";
card.classList.add("ws-card");
card.onclick = clickCard;
gameboard.appendChild(card);
}
this.clickCard = function (e) {
var card = e.target;
// set card image for each card
card.src = "images/xmas18_memorygame_tile" + card.num + ".jpg";
// if another element is clicked while other cards are being checked
// then clear the timeout and run checkCards again
if (checkTimeout != null) {
clearTimeout(checkTimeout);
checkCards();
}
// check if firstCard or secondCard are set to null
if (firstCard == null) {
firstCard = card;
} else if (firstCard == card) {
firstCard.src = "images/xmas18_memorygame_tileback.jpg";
firstCard = null;
} else if (secondCard == null) {
secondCard = card;
firstCard.style.pointerEvents = "none";
secondCard.style.pointerEvents = "none";
checkTimeout = setTimeout(checkCards, 1000);
}
}
this.checkCards = function () {
// if the num of firstCard and secondCard match then remove from board
if (firstCard.num == secondCard.num) {
firstCard.style.visibility = "hidden";
secondCard.style.visibility = "hidden";
matches++;
// if game complete
if (matches >= gameWidth * gameHeight / 2) {
gameEnd();
}
} else {
// if the cards don't match then set their src back to the original
firstCard.src = "images/xmas18_memorygame_tileback.jpg";
secondCard.src = "images/xmas18_memorygame_tileback.jpg";
}
// add 1 to number of turns
turn++;
turnUpdate();
// reset pointer events back to visible so the cards selected are clickable again
firstCard.style.pointerEvents = "visible";
secondCard.style.pointerEvents = "visible";
// reset variables back to null so the next turn can be taken
firstCard = null;
secondCard = null;
checkTimeout = null;
}
this.gameEnd = function () {
document.getElementById("ws-game-end").style.visibility = "visible";
document.getElementById("ws-game-end").style.display = "flex";
turnUpdate();
clearInterval(timer);
upperPrizeMsg = "Wow, you completed it in " + document.getElementById("minutes").innerText + " minutes " + document.getElementById("seconds").innerText + " seconds! Here's your prize: \n WHITESTUFF15";
lowerPrizeMsg = "Hmm, seems like you need some more practice. \n Here's a small prize to keep you going \n WHITESTUFF5";
outOfTimeMsg = "Oh dear, you ran out of time!";
sorryMsg = "Sorry, you didn't win a discount code this time. Try again!";
if (turn >= 0 && turn < 32 && document.getElementById("minutes").innerText < "05") {
document.getElementById("ws-game-end-message").innerText = upperPrizeMsg;
} else if (turn >= 32) {
document.getElementById("ws-game-end-message").innerText = lowerPrizeMsg;
} else if (document.getElementById("minutes").innerText >= "60") {
document.getElementById("ws-game-end-message").innerText = outOfTimeMsg
} else {
document.getElementById("ws-game-end-message").innerText = sorryMsg;
}
}
turnUpdate();
createGrid(gameWidth, gameHeight);
}
Any thoughts please?
Cheers,
Shoxt3r