- Published on
Memory Game using JavaScript
- Authors
- Name
- Andrew Nicholas
Table of Contents
- Introduction
- Project Structure
- HTML Structure
- CSS Styling
- JavaScript Logic
- Images
- Running the Game
- Conclusion
Introduction
This project is a simple Memory Game created using HTML, CSS, and JavaScript with jQuery. The game involves flipping cards to find matching pairs.
Technologies used include:
- HTML
- CSS
- JavaScript
- jQuery
Project Structure
Create the Project Structure
- Create the project directory and navigate to it:
mkdir memorygame
cd memorygame
- Create the following files and directories:
touch index.html main.js memory.css
mkdir images
- Download jQuery and jQuery UI:
- Download the minified versions of jQuery and jQuery UI from their official websites or use the following commands:
curl -o jquery-ui.min.css https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.min.css
curl -o jquery-ui.min.js https://code.jquery.com/ui/1.12.1/jquery-ui.min.js
- Add images:
- Add the card images and 'back.png', 'blank.png' to the 'images' directory.
The project structure should now look like this:
memorygame/
index.html
jquery-ui.min.css
jquery-ui.min.js
main.js
memory.css
images/
back.png
blank.png
card_1.png
card_2.png
...
card_24.png
HTML Structure
Create the 'index.html' file with the following content:
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Memory Game</title>
<link type="text/css" rel="stylesheet" href="jquery-ui.min.css" />
<link type="text/css" rel="stylesheet" href="memory.css" />
</head>
<body>
<header>
<h1>Memory Game</h1>
<p id="new_game"><a href="index.html">New Game</a></p>
<p id="player"> </p>
<p id="high_score"> </p>
<p id="correct"> </p>
<div class="clear"></div>
</header>
<main>
<div id="tabs">
<ul>
<li><a href="#tabs-1">Play Game</a></li>
<li><a href="#tabs-2">View Rules</a></li>
<li><a href="#tabs-3">Settings</a></li>
</ul>
<div id="tabs-1">
<div id="cards"></div>
</div>
<div id="tabs-2">
<fieldset>
<legend>How to play the Memory game</legend>
<ul>
<li>The cards are placed face down. Each card has a matching card.</li>
<li>For each turn, the player selects two cards.</li>
<li>If the cards match, they are removed from the board.</li>
<li>If the cards don't match, they are turned face down again.</li>
<li>
At the end of the game, the player receives a score based on the number of correct
selections that were made.
</li>
</ul>
</fieldset>
</div>
<div id="tabs-3">
<label for="player_name">Player name:</label>
<input type="text" id="player_name" /><br />
<label for="num_cards">Number of cards:</label>
<select id="num_cards">
<option>48</option>
<option>40</option>
<option>32</option>
<option>24</option>
<option>16</option>
<option>8</option></select
><br />
<input type="button" id="save_settings" value="Save Settings" />
</div>
</div>
</main>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="jquery-ui.min.js"></script>
<script src="main.js"></script>
</body>
</html>
Explanation:
- The HTML structure includes a header with the game title and new game link.
- A main section with tabs for playing the game, viewing rules, and changing settings.
- A script section to include jQuery and custom JavaScript.
CSS Styling
Create the 'memory.css' file with the following content:
body {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 100%;
background-color: white;
width: 750px;
margin: 0 auto;
border: 3px solid blue;
padding: 0 2em 1em;
}
h1 {
font-size: 150%;
color: blue;
margin-bottom: 0.5em;
}
label {
float: left;
width: 8em;
}
input,
select {
width: 10em;
margin-right: 1em;
margin-bottom: 1em;
}
input[type='checkbox'] {
width: 2em;
}
header p {
margin: 0 2em 1em 0;
}
#new_game,
#player,
#high_score,
#correct {
float: left;
}
#cards img {
height: 100px;
width: 80px;
padding-right: 5px;
padding-bottom: 3px;
float: left;
}
.clear {
clear: both;
}
main {
border: solid 1px #999;
}
#blocks {
display: flex;
background-color: #ddd;
padding: 10px 0 0 10px;
margin: 0;
border-bottom: solid 1px #999;
}
#blocks li {
display: block;
list-style: none;
margin-right: 10px;
padding: 5px;
border-top: solid 1px #999;
border-left: solid 1px #999;
border-right: solid 1px #999;
border-radius: 5px 5px 0px 0px;
}
#blocks li a {
text-decoration: none;
color: #555;
}
#blocks li a:active {
text-decoration: none;
color: antiquewhite;
}
#tabs-1,
#tabs-2,
#tabs-3 {
padding: 10px;
margin: 10px;
}
#tabs-1 {
min-height: 40em;
}
.hidden {
display: none;
}
.active {
background-color: #5c5cec;
color: antiquewhite;
}
#row1,
#row2,
#row3,
#row4,
#row5,
#row6 {
min-height: 100px;
}
#cards img {
height: 100px;
width: 80px;
padding-right: 5px;
padding-bottom: 3px;
float: left;
}
.match {
pointer-events: none;
}
.flipped1 {
pointer-events: none;
}
.flipped2 {
pointer-events: none;
}
.clear {
clear: both;
}
Explanation:
- The CSS file defines the styles for the game including the layout, card styles, and responsive design elements.
JavaScript Logic:
Create the 'main.js' file with the following content:
'use strict'
let player_name = ''
let num_cards = 48
let cards
let cards_array = new Array(24)
let matches = 0
let matches_array = new Array()
let num_turns = 0
let highscore = 0
for (let i = 0; i < cards_array.length; i++) {
cards_array[i] = new Image()
const card_num = i + 1
cards_array[i].src = 'images/card_' + card_num.toString() + '.png'
}
const Gameboard = () => {
num_cards = parseInt(sessionStorage.num_cards)
if (isNaN(num_cards) || num_cards <= 0) {
num_cards = 48 // Default value if sessionStorage is not set or invalid
}
const num_rows = Math.floor(num_cards / 8)
let row_string = ''
let cards = new Array(num_cards)
for (let num = 0; num < cards.length; num += 2) {
const card = Math.floor(Math.random() * 24) + 1
cards[num] = cards_array[card]
cards[num + 1] = cards_array[card]
}
cards.sort(() => Math.random() - 0.5)
if (num_rows > 0) {
for (let i = 0; i < num_rows; i++) {
const x = i + 1
row_string += `<div id="row` + x.toString() + `"></div>`
}
$('#cards').html(row_string)
let count = 0
for (let row = 0; row < num_rows; row++) {
let rows = row + 1
let card_string = ''
for (let img = count; img < count + 8; img++) {
card_string += `<img src="images/back.png" alt=${cards[img].src}>`
}
count += 8
$(`#row${rows}`).html(card_string)
}
}
} // End of Gameboard function
$(document).ready(() => {
$('#tabs').tabs()
$('#player_name').val(sessionStorage.player_name)
$('#num_cards').val(sessionStorage.num_cards)
$('#player').text(sessionStorage.player_name)
$('#high_score').text(sessionStorage.highscore)
$('#save_settings').click(() => {
let isValid = true
const player_name = $('#player_name').val()
const num_cards = $('#num_cards').val()
const highscore = $('#high_score').text()
if (player_name === '') {
isValid = false
alert('Please enter a name.')
}
if (isValid) {
sessionStorage.player_name = player_name
sessionStorage.num_cards = num_cards
sessionStorage.highscore = highscore
location.reload()
}
})
Gameboard()
let num_flips = 1
const Flipcard = (card_img) => {
let game_flip = card_img.attr('alt')
card_img.attr('class', `flipped${num_flips}`)
card_img.attr('alt', card_img.attr('src'))
card_img.attr('src', game_flip)
matches_array.push(game_flip)
num_flips += 1
}
const Unflipcard = (card_img) => {
let game_flip = card_img.attr('alt')
card_img.attr('class', '')
card_img.attr('alt', card_img.attr('src'))
card_img.attr('src', game_flip)
}
$('img').on('click', function (evt) {
const delay = 1000
let card_img = $(this)
Flipcard(card_img)
console.log(matches_array)
if (matches_array.length > 1) {
if (matches_array[0] === matches_array[1]) {
console.log('Match!')
$('.flipped1').attr('class', 'match')
$('.flipped2').attr('class', 'match')
$('.match').attr('src', 'images/blank.png')
num_flips = 1
matches_array.pop()
matches_array.pop()
matches += 1
num_turns += 1
let correct = (matches / (num_cards / 2)) * 100
$('#correct').text(correct)
if (matches === num_cards / 2) {
if (num_turns < highscore || highscore === 0) {
sessionStorage.highscore = num_turns
console.log(sessionStorage.highscore)
$('img').css({
'pointer-events': 'auto',
})
$('#high_score').text(sessionStorage.highscore)
}
}
} else {
console.log('Not a match!')
$('img').css({
'pointer-events': 'none',
})
setTimeout(function () {
Unflipcard($('.flipped1'))
Unflipcard($('.flipped2'))
$('img').css({
'pointer-events': 'auto',
})
}, delay)
num_flips = 1
num_turns += 1
matches_array.pop()
matches_array.pop()
}
}
console.log('Turns', num_turns)
})
})
Explanation:
- The JavaScript file contains the logic for the memory game.
- It initializes the game board, handles card flips, checks for matches, and manages game settings.
Adding jQuery
To include jQuery in your project, you can either download the jQuery files or use a CDN (Content Delivery Network).
- Using CDN: Add the following script tags in your index.html file inside the head or before the closing body tag:
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="jquery-ui.min.js"></script>
<script src="main.js"></script>
- Downloading jQuery: You can download the minified version of jQuery and jQuery UI from the official websites:
Images
Add the following images to the images directory:
- 'back.png'
- 'blank.png'
- 'card_1.png to card_24.png'
The images should be used as card faces for the memory game.
Running the Game
To run the game:
- Open the index.html file in a web browser.
- Start playing by clicking on the "Play Game" tab.
- Set your preferences in the "Settings" tab and save them.
- View the rules in the "View Rules" tab.
Conclusion
This Memory Game project demonstrates how to use HTML, CSS, and JavaScript to create an interactive web application. By following this guide, you can recreate the Memory Game and customize it further to add more features or improve its design.