Skip to content

Instantly share code, notes, and snippets.

@JonCooperWorks
Last active December 14, 2015 14:29
A rewrite of memory.js to be actually readable.
/*
A rewrite of memory.js to be actually readable.
Written by Jonathan Cooper.
*/
//Array of cards to display in the game
var cards = ["0", "A", "2", "3", "4", "5", "6", "7", "8", "9", "J", "Q", "K", "♥", "♠", "♦", "♣"];
//Max of 24 attempts (48 clicks)
var tries = 48;
//Attempt counter
var attempts = 0;
var pairsLeft = 8;
var section = document.getElementsByTagName('section')[0];
var canvas = document.getElementsByTagName('canvas')[0];
document.body.clientWidth; // fix bug in webkit: http://qfox.nl/weblog/218
//Need to detect if the browser supports local storage, since this entire game depends on it.
function supportsLocalStorage() {
try {
return 'localStorage' in window && window['localStorage'] != null;
} catch(e) {
return false;
}
}
window.onload = function() {
if(!supportsLocalStorage()) {
alert("Your browser is too old, bro. Get Chrome.");
}
else{
var player = new Player("Cooper");
player.loadGame();
var divs = document.getElementsByClassName("c");
for(i=0; i<divs.length; i++) {
divs[i].onclick = audio('http://rpg.hamsterrepublic.com/wiki-images/d/db/Crush8-Bit.ogg ');
}
}
}
//Sets a CSS class on an element
function setClass(element, className) {
element.className = 'w '+ className
}
//Adds vendor prefixes to a style rule
function prefix(style) {
return ";-webkit-"+ style +";-moz-"+ style +";-o-"+ style;
}
//Retrieve a random element from an array
function randomElement(array) {
return array.splice(0 | array.length*Math.random(),1)[0]
}
//Play a sound. Make it return a function for easy listener creation.
//Yay functional programming.
function audio(source) {
return function() {
var audioElement = document.createElement('audio');
audioElement.setAttribute('src', source);
audioElement.load();
audioElement.play();
}
}
//Flips a card
function flip(card) {
//User still has some attemps left
if(attempts < tries) {
attempts++;
//Update turn counter every 2 clicks
document.querySelector("h1").innerHTML = "Turn: "+ parseInt(attempts/2);
//Get all visible cards
visible = document.querySelectorAll('.v');
first = visible[0];
last = visible[1];
//If 2 cards are showing, both need to be flipped over
if(last) {
setClass(first, "");
setClass(last, "")
}
//If a match is found, flip both cards
if(first && !last && first != card && first.innerHTML == card.innerHTML) {
audio('http://cd.textfiles.com/10000soundssongs/WAV/COWBELL2.WAV ')();
setClass(first, "p");
setClass(card, "p");
pairsLeft--;
}
//Otherwise, just flip the current card
else {
setClass(card, "v");
}
//Check to see if the game is finished
if(pairsLeft == 0) {
audio('http://www.earthstation1.com/SFXs/SFX_Wavs/cheer.wav')()
alert("You won, bro!");
}
}
//Max attempts used
else {
var retry = confirm("Max attempts used! Try again?");
if(retry) {
location.reload();
}
else {
alert("Game over.");
}
}
}
function makeGameArea()
{
var divNode = document.createElement("mdiv");
divNode.innerHTML
="<style>\
/* wrapper for the border of the card */\
.w{"
+"width:99px;height:99px;"
+"border:10px solid #777\
+margin-top:-30px\
;text-align:center\
;margin:5px\
;float:left"
+"\
}\
\
.v .b,.p .b{"
+prefix("transform:scale(0)") +"\
}\
/* card */\
.c{"
+"width:99px;height:99px;"
+"position:absolute;"
+"font-size:80px\
}\
/* ♥♠♦♣ on the card */\
b{"
+"position:absolute;"
+"font-size:24px\
;left:5px\
}\
/* back of the card and ♥♦ are red */\
.b,.r{\
color:red\
}\
/* back of the card */\
.z{\
margin-top:30px\
}\
/* back of the card */\
.b{\
background:url('http://www.bmwblog.com/wp-content/uploads/porsche-cayman-s-03-100x100.jpg')"
+prefix("transition:1s") +"\
;margin-top:-35px\
}\
</style>";
document.body.appendChild(divNode);
cards[0]=10;
//Create pack of cards
pack=[];
for(c=13;c<17;c++) {
for(i=0;i<13;i++) {
pack.push([c%2?' r':'',c,cards[i]]);
}
}
//Place a card on the deck twice to create pairs
deck = []
for(k=0; k<8; k++) {
deck[k] = deck[k+8] = randomElement(pack)
}
// start to draw the screen
var gameArea='<div style="width:450px">';
// we need to create 16 cards
for(i=16;i;i--) {
// take out a random element from the cards on the deck
card = randomElement(deck),
gameArea += '<div id="logo" class="w" onclick="flip(this)"><div class="c f'
+card[0]
+'"><b>'
+cards[card[1]]
+'</b>'
+card[2]
+'</div><div class="c b" ><div class="z"></div></div></div>';
}
//return it for later use
return gameArea + '</div>';
}
//Represents a player of the game
function Player(username) {
//Get game state from local storage, if it exists, or create a new board
this.getGameState = function() {
var player = JSON.parse(localStorage.getItem("player"));
if(player && player._gameState) {
return player.gameState;
}
return makeGameArea();
};
//Save the current board.
this.saveGame = function() {
this._gameState = section.innerHTML;
localStorage.setItem("player", JSON.stringify(this));
};
//Retrieve a board, or create a new game
this.loadGame = function() {
section.innerHTML = this._gameState;
};
this.getHighScore = function() {
var player = JSON.parse(localStorage.getItem("player"));
if(player && player._highscore) {
return player._highscore;
}
return 0;
};
this.setHighScore = function(score) {
if(score < this.getHighScore) {
this._highscore = score;
}
localStorage.setItem("player", JSON.stringify(this));
};
//User object properties.
//Link game state and high score to functions
//to allow for cleaner abstraction of player state.
this.username = username;
//Don't access these two properties directly.
//They are for INTERNAL USE ONLY. If you need
//access to a player's state (save game, etc.),
//use the provided methods.
this._gameState = this.getGameState();
this._highscore = this.getHighScore();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment