I've made a JavaScript, HTML and CSS version of the memory game 'Simon' from the 70s. The design of the board is not too impressive (I wanted to focus first on the JavaScript part) but I also appreciate feedback on it of course. If you want to see the game already in action, it's available here.
var computerMovements = [];
var answers = [];
var rounds = 0;
//strict mode allows one mistake per round. false if 'relaxed' mode
var strict = true;
//in strict mode, there is no last chance
var lastChance = false;
var addColor = function(arr) {
var colorsArray = ["green", "red", "yellow", "blue"];
return arr.push(colorsArray[Math.floor(Math.random() * colorsArray.length)]);
};
var flashLights = function(arr) {
var i = 0;
var interval = setInterval(function() {
$("#" + arr[i]).fadeTo("slow", 0).fadeTo("slow", 1);
$("#sound-" + arr[i])[0].play();
i++;
if (i >= arr.length) {
clearInterval(interval);
}
}, 1500);
};
var resetAnswers = function() {
answers = [];
};
var updateRounds = function() {
rounds++;
$("#show-rounds").html(rounds);
};
var resetGame = function() {
rounds = 0;
computerMovements = [];
if (strict === false) {
lastChance = true;
}
resetAnswers();
};
var playerTurn = function() {
//during the game we don't want the player to switch between strict and relaxed
$("#mode").click(function() {
return false;
});
//winning condition
if (rounds === 20) {
alert("You, you, you're good you!");
resetGame();
}
updateRounds();
addColor(computerMovements);
flashLights(computerMovements);
$(".button").off("click").on("click", function() {
$("#sound-" + $(this).attr("id"))[0].play();
answers.push($(this).attr("id"));
for (var i = 0; i < answers.length; i++) {
//correct answer
if (JSON.stringify(computerMovements) === JSON.stringify(answers)) {
resetAnswers();
playerTurn();
break;
}
//wrong answer
if (answers[i] !== computerMovements[i]) {
if (strict === false && lastChance === true) {
lastChance = false;
alert("You get one more chance...");
resetAnswers();
flashLights(computerMovements);
} else if (
answers[i] !== computerMovements[i] &&
lastChance === false
) {
alert("Epic fail!");
resetGame();
break;
}
}
}
});
};
$("#mode").click(function() {
switch (strict) {
case true:
strict = false;
lastChance = true;
$("#mode").html("Mode: Relaxed");
break;
case false:
strict = true;
lastChance = false;
$("#mode").html("Mode: Strict");
break;
}
});
$("#start").click(function() {
playerTurn();
});
#container {
background-color: gray;
width: 160px;
height: 160px;
margin: 0 auto;
text-align: center;
text-align: justify;
}
#green {
background-color: green;
width: 70px;
height: 70px;
float: left;
}
#red {
background-color: red;
width: 70px;
height: 70px;
display: inline-block;
}
#yellow {
background-color: yellow;
height: 70px;
width: 70px;
clear: left;
float: left;
}
#blue {
background-color: blue;
width: 70px;
height: 70px;
float: left;
}
#green:active {
background-color: lightgreen;
}
#red:active {
background-color: pink;
}
#yellow:active {
background-color: lightyellow;
}
#blue:active {
background-color: lightblue;
}
.box {
margin: 0 auto;
width: 45px;
border: 1px solid black;
text-align: center;
}
#mode:hover {
cursor: pointer;
}
#start:hover {
cursor: pointer;
}
#show-rounds {}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Simon says...</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<audio preload="auto" id="sound-green"> <source src="https://s3.amazonaws.com/freecodecamp/simonSound1.mp3"></source></audio>
<audio preload="auto" id="sound-red"><source src="https://s3.amazonaws.com/freecodecamp/simonSound2.mp3"></source></audio>
<audio preload="auto" id="sound-yellow"><source src="https://s3.amazonaws.com/freecodecamp/simonSound3.mp3"></source></audio>
<audio preload="auto" id="sound-blue"><source src="https://s3.amazonaws.com/freecodecamp/simonSound4.mp3"></source></audio>
<div id='container'>
<div class='button' id='green'> </div>
<div class='button' id='red'> </div>
<div class='button' id='yellow'> </div>
<div class='button' id='blue'> </div>
</div>
<div class='box' id='show-rounds'>0</div>
<div class='box' id='mode'>Mode: Strict</div>
<div class='box' id='start'>Start</div>
</div>
</body>
</html>
1 Answer 1
JavaScript
The code looks nice and short. I like the comments on the strict
and lastChance
variables since they explain the game to readers who are not familiar with the game.
Instead of var name = function(...) {}
, it is more common to write function name(...) {}
.
The function flashLights
is always called with computerMovements
as its argument. Therefore, you can remove the arr
parameter and replace it with computerMovements
.
The code below the //during the game
comment does not do what the comment says; you can still change the mode during a game. To avoid this, you have to call $("#mode").off("click")
.
The code if (strict === false && lastChance === true) {
can be written shorter, as if (!strict && lastChance) {
.
Comparing two arrays by transforming both into JSON format is a nice trick. But that whole if
block should be outside the for
loop.
In the // wrong answer
section, you have some redundant checks:
- when
lastChance
is true,strict
is guaranteed to be false, so you don't need to check this. - the condition before the
Epic fail
alert is completely redundant. The first part is already covered by the outsideif
statement, and the second part is coverted by theif ... then
part.
The code of the function that changes the mode can be written a lot simpler:
$("#mode").click(function() {
strict = !strict;
lastChance = !strict;
$("#mode").html(strict ? "Mode: Strict" : "Mode: Relaxed");
});
CSS
The last rule is empty and therefore can be removed.
HTML
The <!DOCTYPE
declaration has to be at the beginning of the file.
The <script>
element should be near the <link>
element.
-
\$\begingroup\$ "The function flashLights is always called with computerMovements as its argument. Therefore, you can remove the arr parameter and replace it with computerMovements." - Are you suggesting to replace arguments with globals? Wouldn't a more decoupled more local code with less reliance on outside variables be easier to test, reuse and understand? \$\endgroup\$le_m– le_m2017年04月30日 02:41:57 +00:00Commented Apr 30, 2017 at 2:41
-
\$\begingroup\$ @le_m Im general you're right. In this case though, the function has so many other dependencies (window, DOM) that it is already hard to test it automatically. Therefore I thought it wouldn't hurt. \$\endgroup\$Roland Illig– Roland Illig2017年04月30日 06:03:11 +00:00Commented Apr 30, 2017 at 6:03