Warm-up · Activity 1 of 7
// B1.5 · ~35 min · Beginner
Build: a number-guessing game
After this build you can write a game that compares guesses with a secret number, counts the attempts and prints Too low, Too high or Correct, and debug it.
Lesson 5 of 5 in B1 Getting started
You will be able to
- Compare a guess with the secret and print Too low, Too high or Correct, with a first look at if and else
- Keep the secret, the guess and the attempts in const and let
- Debug the game with its error messages and logged values
Predict · Activity 2 of 7
Predict before you read on: what does this print?
const secret = 7; let guess = 4; if (guess < secret) { console.log("Too low"); } else if (guess > secret) { console.log("Too high"); } else { console.log("Correct"); }Practice · Activity 3 of 7
Fill in the comparison so that the program prints Too high for this guess.
const secret = 7; let guess = 9; if (guess ____ secret) { console.log("Too high"); }if (guess secret) {Practice · Activity 4 of 7
Which whole numbers can this expression give? (A preview: modules B2 and B3 come back to Math.)
Math.floor(Math.random() * 10) + 1Practice · Activity 5 of 7
Three rounds each count one attempt. What does the last line print?
let attempts = 0; attempts = attempts + 1; attempts = attempts + 1; attempts = attempts + 1; console.log("Attempts:", attempts);Brain teaser · Activity 6 of 7
Brain teaser. This program stops with an error. What does it print before that?
const secret = 42; const guess = 30; console.log("Guess:", guess); guess = 50; console.log("Guess:", guess);Apply · Activity 7 of 7
Mini-task. Write the whole game for the secret 42 and the guesses 25, 75 and 42. Each round sets guess, adds one to attempts, and prints the guess with Too low, Too high or Correct. At the end print Found 42 in 3 attempts, with both numbers taken from the variables. Then change a guess and run it again.
Check your work against this list
Build it yourself
Read the worked example, then write the exercises. Your code runs in your browser or on your computer and is never uploaded.
Worked example
Three rounds of the game
The secret is fixed at 42 and the three guesses are written into the program, because the editor has no keyboard input. Each round gives guess a new value, counts the attempt and prints one of three messages. Run it, then change a guess, or the secret, and predict the output before you run it again.
main.js
// Number guessing, with the guesses written into the program.
const secret = 42;
let attempts = 0;
let guess = 30;
attempts = attempts + 1;
if (guess < secret) {
console.log(guess, "Too low");
} else if (guess > secret) {
console.log(guess, "Too high");
} else {
console.log(guess, "Correct");
}
guess = 50;
attempts = attempts + 1;
if (guess < secret) {
console.log(guess, "Too low");
} else if (guess > secret) {
console.log(guess, "Too high");
} else {
console.log(guess, "Correct");
}
guess = 42;
attempts = attempts + 1;
if (guess < secret) {
console.log(guess, "Too low");
} else if (guess > secret) {
console.log(guess, "Too high");
} else {
console.log(guess, "Correct");
}
console.log("Attempts:", attempts);
Run it with
node main.jsOutput
30 Too low
50 Too high
42 Correct
Attempts: 3- secret is a const: it never changes. guess and attempts are let: each round changes them.
- In each round exactly one of the three messages is printed.
- guess = 50; has no let in front: the variable exists already, it only gets a new value.
- The same round is written three times. Loops (B3) and functions (B4) will make that one block.
Change it and run it
Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.
The first run downloads the JavaScript runner (up to 0.1 MB) and keeps it cached. Your code runs in your browser’s own engine and stays on your device.
Exercises
Exercise 1 of 3
Step 1: judge three guesses
The secret is 42 and the guesses are 30, 50 and 42. After each guess, print the guess and Too low, Too high or Correct, as in 30 Too low. Use if, else if and else to choose the message, and let JavaScript compare: do not type the answers.
Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.
The first run downloads the JavaScript runner (up to 0.1 MB) and keeps it cached. Your code runs in your browser’s own engine and stays on your device.
Hints
Hint 1
Start with the first guess only: if (guess < secret) { console.log(guess, "Too low"); }.
Hint 2
Add else if (guess > secret) { … } and else { … } for the other two messages.
Hint 3
Copy the whole if … else block after each new guess = line.
Show a solution
One way to solve it. Yours can look different and still pass the checks.
const secret = 42;
let guess = 30;
if (guess < secret) {
console.log(guess, "Too low");
} else if (guess > secret) {
console.log(guess, "Too high");
} else {
console.log(guess, "Correct");
}
guess = 50;
if (guess < secret) {
console.log(guess, "Too low");
} else if (guess > secret) {
console.log(guess, "Too high");
} else {
console.log(guess, "Correct");
}
guess = 42;
if (guess < secret) {
console.log(guess, "Too low");
} else if (guess > secret) {
console.log(guess, "Too high");
} else {
console.log(guess, "Correct");
}
Run it on your computer
Install ECMAScript 2026 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.
main.js
const secret = 42;
let guess = 30;
// Print the guess and "Too low", "Too high" or "Correct".
guess = 50;
// The same check again.
guess = 42;
// And once more.
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {runMain} from './learnrun.js';
const lines = async () => (await runMain()).trimEnd().split('\n');
test('says Too low for 30', async () => {
const got = await lines();
assert.equal(got[0], '30 Too low', `the first line is ${JSON.stringify(got[0])}, expected "30 Too low"`);
});
test('says Too high for 50', async () => {
const got = await lines();
assert.equal(got[1], '50 Too high', `the second line is ${JSON.stringify(got[1])}, expected "50 Too high"`);
});
test('says Correct for 42', async () => {
const got = await lines();
assert.equal(got[2], '42 Correct', `the third line is ${JSON.stringify(got[2])}, expected "42 Correct"`);
});
test('prints exactly one line per guess', async () => {
const got = await lines();
assert.equal(got.length, 3, `the program printed ${got.length} line(s), expected 3`);
});
package.json
{
"type": "module"
}
package.json tells Node.js that the .js files are modules; keep it in the folder.
Run the program:
node main.jsRun the checks (needs learnrun.js in the same folder):
node --testDownload learnrun.jsExercise 2 of 3
Step 2: fix the broken game
This game should print 30 Too low, then 42 Correct, then Attempts: 2. It has two bugs. Run it, read the error message and fix that line. Then compare the output with what it should be: the second bug gives no error at all, only wrong feedback.
Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.
The first run downloads the JavaScript runner (up to 0.1 MB) and keeps it cached. Your code runs in your browser’s own engine and stays on your device.
Hints
Hint 1
The first error is TypeError: Assignment to constant variable. Which variable gets a new value, and how is it declared?
Hint 2
After that fix, 30 is reported as Too high. Log guess and secret, or read each condition aloud: is 30 > 42?
Hint 3
Swap the two comparisons: guess < secret goes with Too low, guess > secret with Too high.
Show a solution
One way to solve it. Yours can look different and still pass the checks.
const secret = 42;
let attempts = 0;
let guess = 30;
attempts = attempts + 1;
if (guess < secret) {
console.log(guess, "Too low");
} else if (guess > secret) {
console.log(guess, "Too high");
} else {
console.log(guess, "Correct");
}
guess = 42;
attempts = attempts + 1;
if (guess < secret) {
console.log(guess, "Too low");
} else if (guess > secret) {
console.log(guess, "Too high");
} else {
console.log(guess, "Correct");
}
console.log("Attempts:", attempts);
Run it on your computer
Install ECMAScript 2026 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.
main.js
const secret = 42;
const attempts = 0;
let guess = 30;
attempts = attempts + 1;
if (guess > secret) {
console.log(guess, "Too low");
} else if (guess < secret) {
console.log(guess, "Too high");
} else {
console.log(guess, "Correct");
}
guess = 42;
attempts = attempts + 1;
if (guess > secret) {
console.log(guess, "Too low");
} else if (guess < secret) {
console.log(guess, "Too high");
} else {
console.log(guess, "Correct");
}
console.log("Attempts:", attempts);
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {runMain} from './learnrun.js';
test('runs without an error', async () => {
await runMain();
});
test('says Too low for 30', async () => {
const got = (await runMain()).trimEnd().split('\n');
assert.equal(got[0], '30 Too low', `the first line is ${JSON.stringify(got[0])}, expected "30 Too low"`);
});
test('prints the whole game', async () => {
const got = (await runMain()).trimEnd().split('\n');
assert.deepEqual(got, ['30 Too low', '42 Correct', 'Attempts: 2'], `the program printed ${JSON.stringify(got)}`);
});
package.json
{
"type": "module"
}
package.json tells Node.js that the .js files are modules; keep it in the folder.
Run the program:
node main.jsRun the checks (needs learnrun.js in the same folder):
node --testDownload learnrun.jsExercise 3 of 3
Step 3: a random secret
Now let the program pick the secret: a whole number from 1 to 10, with Math.floor(Math.random() * 10) + 1. The guess is 5. Print the feedback line as before, then The secret was and the secret, such as The secret was 8. The tests run your program many times: the secret must always be a whole number from 1 to 10, the feedback must fit it, and it must not always be the same.
Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.
The first run downloads the JavaScript runner (up to 0.1 MB) and keeps it cached. Your code runs in your browser’s own engine and stays on your device.
Hints
Hint 1
Run the starter a few times: the secret has decimals, such as 7.3918…, which a player could never guess.
Hint 2
Math.floor(…) rounds down to a whole number, and Math.random() * 10 is below 10, so you get 0 to 9.
Hint 3
Add 1 after rounding: Math.floor(Math.random() * 10) + 1.
Show a solution
One way to solve it. Yours can look different and still pass the checks.
const secret = Math.floor(Math.random() * 10) + 1;
const guess = 5;
if (guess < secret) {
console.log(guess, "Too low");
} else if (guess > secret) {
console.log(guess, "Too high");
} else {
console.log(guess, "Correct");
}
console.log("The secret was", secret);
Run it on your computer
Install ECMAScript 2026 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.
main.js
// Pick a whole number from 1 to 10.
const secret = Math.random() * 10;
const guess = 5;
if (guess < secret) {
console.log(guess, "Too low");
} else if (guess > secret) {
console.log(guess, "Too high");
} else {
console.log(guess, "Correct");
}
console.log("The secret was", secret);
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {runMain} from './learnrun.js';
const RUNS = 6;
const play = async () => {
const [feedback, reveal] = (await runMain()).trimEnd().split('\n');
const found = /^The secret was (\d+)$/.exec(reveal ?? '');
return {feedback, reveal, secret: found ? Number(found[1]) : null};
};
test('the secret is a whole number from 1 to 10', async () => {
for (let run = 0; run < RUNS; run++) {
const {reveal, secret} = await play();
assert.ok(secret !== null && secret >= 1 && secret <= 10, `the last line is ${JSON.stringify(reveal)}, expected The secret was followed by a whole number from 1 to 10`);
}
});
test('the feedback fits the secret', async () => {
for (let run = 0; run < RUNS; run++) {
const {feedback, secret} = await play();
const expected = secret > 5 ? '5 Too low' : secret < 5 ? '5 Too high' : '5 Correct';
assert.equal(feedback, expected, `with the secret ${secret}, the first line is ${JSON.stringify(feedback)}, expected ${JSON.stringify(expected)}`);
}
});
test('the secret changes between runs', async () => {
const seen = new Set();
for (let run = 0; run < 10 && seen.size < 2; run++) seen.add((await play()).secret);
assert.ok(seen.size > 1, `10 runs all gave the secret ${[...seen][0]}`);
});
package.json
{
"type": "module"
}
package.json tells Node.js that the .js files are modules; keep it in the folder.
Run the program:
node main.jsRun the checks (needs learnrun.js in the same folder):
node --testDownload learnrun.jsCommon mistakes
A guess declared with const
const secret = 42;
const guess = 30;
guess = 50;
What Node.js prints
TypeError: Assignment to constant variable.Why, and the fix
A const cannot be given a new value, and the program stops at the line that tries. The guess changes every round, so declare it with let guess = 30; and keep const for the secret. The same happens with a const attempts counter.
A capital F in Math.floor
const secret = Math.Floor(Math.random() * 100) + 1;
What Node.js prints
TypeError: Math.Floor is not a functionWhy, and the fix
Math exists, but it has no Floor with a capital F, so there is nothing to call. Names are case-sensitive: Math starts with a capital M, and its methods, floor and random, are in lower case.
A missing closing brace
const secret = 42;
const guess = 30;
if (guess < secret) {
console.log(guess, "Too low");
} else {
console.log(guess, "Too high or correct");
What Node.js prints
SyntaxError: Unexpected end of inputWhy, and the fix
Every { needs its }. Here the else block is never closed, so JavaScript reaches the end of the file still waiting for it. As with every SyntaxError, no line runs. Match each { with its } and indent the code inside, so a missing one stands out.
JavaScript in the browser: your browser’s own engine, in a sandboxed worker. Syntax errors are located with acorn 8.18.0, MIT. Licence and source
Exit ticket
5 questions, no hints. Score 80% or more to complete the lesson.
Finish every activity above to unlock the exit ticket.