Freshman Simon Game tutorial
Learn how to build a Simon Game with JavaScript. Tutorial: https://freshman.tech/simon-game
by vishalvasani
HTML
<main class="game">
<header>
<h1 class="heading js-heading">Simon Game</h1>
</header>
<section class="tile-container js-container unclickable">
<div class="tile tile-red" data-tile="red"></div>
<div class="tile tile-green" data-tile="green"></div>
<div class="tile tile-blue" data-tile="blue"></div>
<div class="tile tile-yellow" data-tile="yellow"></div>
</section>
<footer class="info-section">
<button class="start-button js-start">Start</button>
<span class="info js-info hidden"></span>
</footer>
</main>
<div class="hidden">
<audio
src="https://s3.amazonaws.com/freecodecamp/simonSound1.mp3"
data-sound="red"
></audio>
<audio
src="https://s3.amazonaws.com/freecodecamp/simonSound2.mp3"
data-sound="green"
></audio>
<audio
src="https://s3.amazonaws.com/freecodecamp/simonSound3.mp3"
data-sound="blue"
></audio>
<audio
src="https://s3.amazonaws.com/freecodecamp/simonSound4.mp3"
data-sound="yellow"
></audio>
</div>
CSS
html {
box-sizing: border-box;
}
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: inherit;
}
body {
display: flex;
justify-content: center;
font-family: 'Rubik', sans-serif;
}
.game {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.hidden {
display: none !important;
}
.invisble {
visibility: hidden;
}
header {
text-align: center;
font-size: 18px;
}
.heading {
font-size: 3em;
}
.tile-container {
display: grid;
grid-template-rows: 180px 180px;
grid-template-columns: 180px 180px;
grid-gap: 25px;
position: relative;
margin-top: 30px;
margin-bottom: 40px;
}
.unclickable {
pointer-events: none;
}
.tile-red {
background-color: #f25022;
box-shadow: 0 0 0 1px #f25022 inset, 0 0 0 2px rgba(255, 255, 255, 0.15) inset, 0 8px 0 0 #c93a12, 0 8px 0 1px rgba(0, 0, 0, 0.4), 0 8px 8px 1px rgba(0, 0, 0, 0.5);
transition: 0.15s;
}
.tile-red:hover,
.tile-red:focus {
background-color: #ff451a;
box-shadow: 0 0 0 1px #FF3000 inset, 0 0 0 2px rgba(255, 255, 255, 0.15) inset, 0 10px 0 0 #e62b00, 0 10px 0 1px rgba(0, 0, 0, 0.4), 0 10px 8px 1px rgba(0, 0, 0, 0.6);
}
.tile-red:active,
.tile-red.activated {
box-shadow: 0 0 0 1px #ff5c36 inset, 0 0 0 2px rgba(255, 255, 255, 0.15) inset, 0 0 0 1px rgba(0, 0, 0, 0.4);
background-color: #ff5c36;
transform: translateY(10px);
}
.tile-green {
background-color: #7fba00;
box-shadow: 0 0 0 1px #7fba00 inset, 0 0 0 2px rgba(255, 255, 255, 0.15) inset, 0 8px 0 0 #638f05, 0 8px 0 1px rgba(0, 0, 0, 0.4), 0 8px 8px 1px rgba(0, 0, 0, 0.5);
transition: 0.15s;
}
.tile-green:hover,
.tile-green:focus {
background-color: #8cc218;
box-shadow: 0 0 0 1px #8cc218 inset, 0 0 0 2px rgba(255, 255, 255, 0.15) inset, 0 10px 0 0 #74a802, 0 10px 0 1px rgba(0, 0, 0, 0.4), 0 10px 8px 1px rgba(0, 0, 0, 0.6)
}
.tile-green:active,
.tile-green.activated {
box-shadow: 0 0 0 1px #a0ea00 inset, 0 0 0 2px rgba(255, 255, 255, 0.15) inset, 0 0 0 1px...
JavaScript
let sequence = [];
let humanSequence = [];
let level = 0;
const startButton = document.querySelector('.js-start');
const info = document.querySelector('.js-info');
const heading = document.querySelector('.js-heading');
const tileContainer = document.querySelector('.js-container');
function resetGame(text) {
alert(text);
sequence = [];
humanSequence = [];
level = 0;
startButton.classList.remove('hidden');
heading.textContent = 'Simon Game';
info.classList.add('hidden');
tileContainer.classList.add('unclickable');
}
function humanTurn(level) {
tileContainer.classList.remove('unclickable');
info.textContent = `Your turn: ${level} Tap${level > 1 ? 's' : ''}`;
}
function activateTile(color) {
const tile = document.querySelector(`[data-tile='${color}']`);
const sound = document.querySelector(`[data-sound='${color}']`);
tile.classList.add('activated');
sound.play();
setTimeout(() => {
tile.classList.remove('activated');
}, 300);
}
function playRound(nextSequence) {
nextSequence.forEach((color, index) => {
setTimeout(() => {
activateTile(color);
}, (index + 1) * 600);
});
}
function nextStep() {
const tiles = ['red', 'green', 'blue', 'yellow'];
const random = tiles[Math.floor(Math.random() * tiles.length)];
return random;
}
function nextRound() {
level += 1;
tileContainer.classList.add('unclickable');
info.textContent = 'Wait for the computer';
heading.textContent = `Level ${level} of 20`;
const nextSequence = [...sequence];
nextSequence.push(nextStep());
playRound(nextSequence);
sequence = [...nextSequence];
setTimeout(() => {
humanTurn(level);
}, level * 600 + 1000);
}
function handleClick(tile) {
const index = humanSequence.push(tile) - 1;
const sound = document.querySelector(`[data-sound='${tile}']`);
sound.play();
const remainingTaps = sequence.length - humanSequence.length;
if (humanSequence[index] !== sequence[index]) {
resetGame('Oops! Game over, you...