One of the most impressive skills that I like to train is doing math in my head. It’s so good don’t be addicted to that devil’s creation called calculator!
But what is even better is having some fun while practicing it. So you have to challenge yourself, see your improvements, and learn things. The most you train yourself, the most you’ll want to train.
This is why I like Kumon method. It’s used as a math and reading educational method, which is based on moving on to the next level when you have achieved mastery of the previous level. And mastery is defined as speed (using a standard completion time) and accuracy.
What we’ll be doing today is an amazing game to simulate this method so you’ll get a few operations to do, and have limited time to complete them. And the best thing is that it all will be done with jQuery!
So, let’s rock.
Demo & Download
Ok, why don’t you try to play a little bit and see how you go with it? Just give our live demo a try! Oh, and you can download it as well, if you want.
Basic Structure.. Guess what?
Yeah, we’ll use bootstrap again because it’s so amazing! We’ll change it a little bit since we’ll have dark background, but it’s a incredibly simple thing to do.
We’ll add a dark background from subtlepatterns and will change a base text color to #ccc.
Let’s take a look at our basic HTML:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <title>JKumon - Kumon-like Game for Practicing Math & jQuery Skills</title> <meta name="author" content="Rochester Oliveira - RockingCode.com" /> <link rel="shortcut icon" type="image/x-icon" href="favicon.ico"> <!-- CSS: implied media="all" --> <link rel="stylesheet" href="css/style.css?v=2" /> <link rel="stylesheet" href="css/bootstrap.min.css" /> <link type="text/plain" rel="author" href="humans.txt" /> </head> <body> <div id="container" class="content"> <h1><img src="img/jkumon.png" alt="JKumon" />JKumon</h1> <p>Your task is to do a little math above. You'll get 1 minute to solve all those operations. Try increasing the number of operations as you get better on it</p> <br clear="all" /> <p> <label><strong>Total operations:</strong> <input type="text" name="numOP" id="numOP" value="10" /></label><br /> <strong>Best Score:</strong> <span id="bestScore">0</span> </p> <h1 id="count">60</h1> <div id="game"></div> <p><a href="#" class="btn primary start" id="start">Let's play! <img src="img/start.png" alt="start" /></a></p> </div> <!--! end of #container --> <!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if necessary --> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js"></script> <script>window.jQuery || document.write("<script src='js/libs/jquery-1.7.1.min.js'>\x3C/script>")</script> </body> </html>
Our CSS rules are really easy to understand also:
body {
background: url("../img/bg.png") repeat;
}
#container {
position: relative;
width: 700px;
margin: 15px auto 0;
color: #ccc;
}
#container h1 {
font-family: "Lucida Console";
color: #29884f;
}
#container h1 img {
float: left;
margin: 0 25px 10px 0;
}
#start {
text-transform: uppercase;
font-weight: bold;
}
#start img {
margin: 0 0 -5px 5px;
width: 20px;
}
#container #count {
float: right;
color: #e6e824;
}
#game label {
border-bottom: 1px solid #454545;
display: block;
font-size: 15px;
font-weight: bold;
margin-bottom: 5px;
overflow: hidden;
padding-bottom: 10px;
width: 185px;
font-family: "Lucida Console";
}
#game label input {
margin-left: 10px;
}
Let’s go to the funny part, then, the game itself!
Game Logic
Before just coding I like to take a look at the whole picture and see which is the best approach for what we’re trying to do.
So, without any code we can list a few functionalities (that after will turn into functions) that is required to our little game:
- Counter – Since this game has limited time we’ll need it!
- Generate X math operations and store their answer – that’s they funny part anyway
- Check user input and give results
- Store best results
So far, so good. Now you may even write pseudo-code, but since I know that this game won’t be too big (spoiler, you can do it with 150 lines or less) we’ll just go ahead and write some JavaScript.
Game Implementation
Variables & Functions Scope
Here we’ll need to take a special care with where we declare variables and functions. The main concern is that several variables need to be shared between functions (like counter), so we need to declare them in our very first line of code, this way:
var $start = $("#start"), $bestScore = $("#bestScore"), $numOp = $("#numOP"), $game = $("#game"), count = 0, $count = $("#count"), html = "";
You may notice that a few of them have a $ prefix. It’s because they’re jQuery objects, so it’s good to differentiate them of “regular” variables. Of and caching elements is really good for code performance, so if you’ll can an element twice, cache it!
jQuery binding
Instead of mess your code with “click” attribute, you can use jQuery to easily bind clicks. This is what we’ll be doing:
$(function(){ // document ready!
$start.click(function(){
start($numOp.attr("value"));
});
init();
});
Cool, now when “#start” element is clicked it’ll start the game. But we have also this init function. We need it because our best score uses localStorage, so we need to update best score HTML when page is loaded:
function init() {
if (localStorage["best"]) {
$bestScore.text(localStorage["best"]);
}
$count.text("");
}
Starting a new game
Start function is quite easy to understand. Actually it just set up things to the others:
function start(i) {
$start.fadeOut(); //we've started already so let's hide "start" button
//delete anything that may be inside $game
$game.empty();
//generate hidden inputs with operations
operations(i);
//show them and start counter
html = "<a href='#' class='btn success' onclick='stop()'>Done!</a>";
$game.append(html);
count = 60; //if you want to increase maximum time, change here
$count.text(count);
clock = setInterval("counter()",1000);
}
Before going to magic operations function, let’s dig into our counter a little bit!
Counter
SetInterval calls a function at determined intervals. So what we’re saying in our last line of start() is that counter function will run every second AND that the identifier for this interval will be clock variable. So when we want to stop it we’ll just need to destroy clock.
The counter itself is quite simple:
function counter() {
if (count > 0) {
count--;
$count.text(count);
} else {
stop();
}
}
Dynamically generated operations!
Operations function will generate 3 random numbers. 2 operands and 1 for operation itself. This way we’ll generate a random operation and will store its result with localStorage. Then it’s just add its HTML to our game screen!
// generate random operations
function operations(i) {
var a, b, c, r;
for (z=0;z<=i;z++) {
//we'll generate 3 random numbers, 1 for operation and 2 for operands
a = Math.floor(Math.random() * 50) + 1; //let's keep it under 50, change it to the highest number you want to see, +1 removes zero from possibilities
b = Math.floor(Math.random() * 50) + 1;
c = Math.floor(Math.random() * 4); // 0 = +, 1 = -, 2 = *, 3 = /
r = resultNumber(a,b,c);
c = operator(c);
localStorage["result-" + z] = r;
html = "<label>" + a + " " + c + " " + b + " <input type='text' id='op-" + z + "' name='op-" + z + "' value=''></label>";
$game.append(html);
}
}
function resultNumber(a, b, c) {
var result = 0;
switch(c) {
case 0:
result = a + b;
break;
case 1:
result = a - b;
break;
case 2:
result = a * b;
break;
case 3:
result = a / b;
break;
default:
result = "error";
break;
}
return result;
}
function operator(c) {
var result = "";
switch(c) {
case 0:
result = "+";
break;
case 1:
result = "-";
break;
case 2:
result = "*";
break;
case 3:
result = "/";
break;
default:
result = "error";
break;
}
return result;
}
And your final score is…
Now our very last function is “stop” which is called when clock ends.
What it’ll do is to check for every user input which was the right result, and then show final score. It’ll save high scores also, of course
// stop clock!
function stop() {
var i = localStorage["i"], r = 0, sel = "", right = 0;
// stop and clear clock
clearTimeout(clock);
$count.text("");
//count results
for (z=0;z<=i;z++) {
sel = "#op-" + z;
r = $(sel).attr("value");
if ( r == localStorage["result-" + z]){
right++;
}
}
html = "<p class='alert-message'><strong>Awesome!</strong></p><p>Your score was <strong>" + right + "</strong>, which means " + Math.round((right / i)*100) + "% of total questions. Great job!</p><br />";
// show results
$game.empty().append(html);
// save best result if it is
if (right > localStorage["best"]) {
localStorage["best"] = right;
$bestScore.text(right);
html = "<p class='alert-message success'><strong>A-M-A-Z-I-N-G!!!</strong></p><p>New High Score! Yeah, baby, yeah!</p><br />";
$game.append(html);
}
//show again button to start game
$start.fadeIn();
}
What do you think?
Don’t be shy and share you thoughts with us! Oh, and don’t forget to post your best score


No doubt.