Memory Game
Quick JS test of the classic matching memory game.
by Jonathan Lam
HTML
<div id="settings">
<input type="number" id="numRows" value="4" placeholder="4" max="10" min="2" /> × <span id="boardSize"></span> BOARD
</div>
<div id="gameboard"></div>
<div id="cite">A memory game by Jonathan Lam for <a href="http://www.thehomeworklife.co.nf">The Homework Life</a>.<br />See the code at <a href="https://jsfiddle.net/jlam55555/2x0ufnpz/50/embedded/result/">JSFiddle.net</a>.</div>
CSS
@import url(https://fonts.googleapis.com/css?family=Lora:700);
@import url(https://fonts.googleapis.com/css?family=Merriweather);
* {
border-radius: 5px;
box-sizing: border-box;
}
html, body {
height: 100%;
width: 100%;
min-height: 500px;
min-width: 500px;
margin: 0;
padding: 0;
font-size: 16px;
}
div#settings {
text-align: center;
margin-top: 20px;
font-family: merriweather;
}
span#boardSize {
padding: 0 10px;
}
input#numRows {
background-color: transparent;
border: none;
display: inline-block;
width: 50px;
outline: none;
text-align: right;
font-family: inherit;
font-size: inherit;
}
div#cite {
font-family: merriweather;
text-align: center;
}
div#cite > a {
color: black;
border-bottom: 1px dotted black;
text-decoration: none;
border-radius: 0;
}
div#gameboard {
background-color: #2c5986;
height: 500px;
width: 500px;
margin: 20px auto;
}
div.card:hover {
background-color: rgba(200, 200, 255, 0.75);
}
div.card:active {
background-color: rgba(200, 255, 200, 0.75);
}
div.card {
background-color: rgba(255, 255, 255, 0.75);
display: inline-flex;
align-items: center;
cursor: pointer;
float: left;
color: transparent;
transition: all .2s;
}
@keyframes spinIn {
0% { transform: rotateY(0deg); }
50% { color: transparent; }
51% { color: black; }
100% { transform: rotateY(180deg); color: black; }
}
@keyframes spinOut {
0% { transform: rotateY(180deg); }
50% { color: black; }
51% { color: transparent; }
100% { transform: rotateY(0deg); color: transparent; }
}
@keyframes shake {
0% { transform: rotate(0deg); }
20% { transform: rotate(10deg); }
50% { transform: rotate(0deg); background-color: rgba(255, 200, 200, 0.75); }
80% { transform: rotate(-10deg); }
100% { transform: rotate(0deg); backgound-color: rgba(255, 255, 255, 0.75) }
}
@keyframes disappear {
from { opacity: 1; }
to { opacity: 0; }
}
div.card span {
flex-grow: 1;
text-align: center;
font-family: Lora;
font-weight: bold;
font-size: 30px;
color:...
JavaScript
var numOpen = 0;
var numMoves = 0;
var draw = function() {
numMoves = 0;
numOpen = 0;
var gameboard = $("div#gameboard");
var numRows = parseInt($("input#numRows").val());
$("span#boardSize").text(numRows);
if(numRows % 2 != 0) {
$("input#numRows").val(4);
$("span#boardSize").text(4);
draw();
return;
}
var allNums = [];
for(var i = 1; i <= numRows*numRows/2; i++) {
allNums.push(i, i);
}
// The following shuffle uses the "Fisher-Yates" shuffle algorithm
// See http://bost.ocks.org/mike/shuffle/
var index, left = allNums.length;
while(left) {
index = Math.floor(Math.random() * left--);
var tmp = allNums[left];
allNums[left] = allNums[index];
allNums[index] = tmp;
}
var margin = -(5/2)*numRows + 30;
gameboard.css({
"padding": margin/2 + "px"
});
gameboard.empty();
for(var i = 0; i < numRows*numRows; i++) {
var newSquare = $("<div>");
newSquare.append("<span>" + allNums[i] + "</span>");
newSquare.addClass("card");
newSquare.css({
"width": "calc(100% / " + numRows + " - " + margin + "px)",
"height": "calc(100% / " + numRows + " - " + margin + "px)",
"margin": margin/2 + "px"
});
gameboard.append(newSquare);
}
$("div.card").click(function() {
if(!$(this).hasClass("active")) {
if(numOpen == 2) {
$(this).addClass("nope");
setTimeout(function() {
$("div.card.nope").removeClass("nope");
}, 200);
return;
}
numOpen++;
$(this).removeClass("inactive").addClass("active");
if(numOpen == 2) {
setTimeout(function() {
numOpen = 0;
numMoves++;
if($("div.card.active:first > span").text() == $("div.card.active:last > span").text()) {
$("div.card.active").removeClass().addClass("card").addClass("gone");
if($("div.gone").length == numRows*numRows) {
if(confirm("You finished in " + numMoves + " moves!\nTry again?"))
draw();
}
} else {
$("div.card.active").removeClass("active").addClass("inactive");
}
}, 500);
}
}...