Programming Foundations
Beginner

Mini Project: A Number Guessing Game

Put everything together. Plan, build and improve a complete number guessing game using variables, conditions, loops and functions, all running in your browser.

Mini Project: A Number Guessing Game

What you will build

A game where the computer picks a secret number between 1 and 100, and the player tries to guess it. After each guess, the game says "Too high" or "Too low", until the player gets it right. At the end it shows how many tries it took.

Animation: a number line from 1 to 100 narrows as the player guesses 50 (too high), 25 (too low), then 37 (correct) in three tries
Every hint cuts the range. That's the whole game.

It runs entirely in your browser. No installs.

Along the way you'll use every idea from this course:

Lesson Where it shows up
2. Breaking problems into steps Planning the game before coding
3. Variables and data types The secret number, the guess, the number of tries
4. Conditions Too high, too low, or correct?
5. Loops Keep asking until the player wins
6. Functions Organising the game into clear pieces
7. Debugging Fixing the bugs we'll meet on the way

Step 1: Plan before you code

Let's use the four questions from lesson 2.

  1. What do I have? A secret random number, and guesses typed by the player.
  2. What do I want? Tell the player if each guess is too high, too low or correct, then show the number of tries.
  3. What are the steps?
  4. What could go wrong? The player types letters, a number out of range, or presses Cancel.

The steps, as pseudocode:

pick a secret number from 1 to 100
set tries to 0

repeat:
    ask the player for a guess
    add 1 to tries
    if guess is too high → say "Too high"
    if guess is too low  → say "Too low"
    if guess is correct  → say "You win in X tries!" and stop

That's the whole game. Now we translate, one small piece at a time.

Step 2: Two new tools

We need two built-in functions we haven't used yet.

Math.random() gives a random decimal number between 0 and 1 (like 0.7382...). To turn it into a whole number from 1 to 100:

const secret = Math.floor(Math.random() * 100) + 1;

Read it from the inside out:

Piece Result (example)
Math.random() 0.7382
* 100 73.82
Math.floor(...) rounds down 73
+ 1 (so we get 1–100, not 0–99) 74

prompt() shows a pop-up box where the player can type, and returns what they typed as a string (remember lesson 3!), or null if they press Cancel.

const answer = prompt("What's your name?");
console.log(answer);

Try both in the console before moving on.

Step 3: The first working version

Open a new browser tab, open the console (F12), and type this in:

const secret = Math.floor(Math.random() * 100) + 1;
let tries = 0;

while (true) {
  const guess = prompt("Guess a number from 1 to 100:");
  tries++;

  if (guess > secret) {
    alert("Too high!");
  } else if (guess < secret) {
    alert("Too low!");
  } else {
    alert(`You got it! The number was ${secret}. Tries: ${tries}`);
    break;
  }
}

Two new words:

  • while (true) means "loop forever"... until something stops it.
  • break stops the loop immediately. We only reach it when the guess is correct, so the loop always has a way out. (Lesson 5: every loop needs something that moves it toward stopping.)

Play a round. It works! But it has hidden bugs. Let's find them.

Step 4: Debug it

Try these while playing, and watch what happens:

Bug 1: typing letters. Type hello. The game says... "You got it!" 😱

Why? Use the lesson 7 method. "hello" > 74 is false. "hello" < 74 is also false, because text can't be compared with a number. Neither condition matched, so we fell into else: the "correct" branch. Our else assumed that anything not too high or too low must be right. That's a logic error.

The player types hello: hello > 74 is false, hello < 74 is false, so the code falls into else and says You got it; the fix checks the input with Number.isInteger first
The else assumed too much. Check the input before you compare it.

Bug 2: pressing Cancel. prompt returns null, and the loop keeps asking forever. There's no way to quit.

Hidden bug: strings vs numbers. guess is a string like "50". The comparison "50" > 74 happens to work because JavaScript quietly converts it, but relying on that is risky. We should convert it ourselves with Number().

Step 5: Fix the bugs

The fix is to check the input first, and only then compare it:

const secret = Math.floor(Math.random() * 100) + 1;
let tries = 0;

while (true) {
  const answer = prompt("Guess a number from 1 to 100:");

  // Cancel pressed: stop the game
  if (answer === null) {
    alert(`Game over. The number was ${secret}.`);
    break;
  }

  const guess = Number(answer);

  // Not a whole number from 1 to 100: ask again, don't count it
  if (!Number.isInteger(guess) || guess < 1 || guess > 100) {
    alert("Please type a whole number from 1 to 100.");
    continue;
  }

  tries++;

  if (guess > secret) {
    alert("Too high!");
  } else if (guess < secret) {
    alert("Too low!");
  } else {
    alert(`You got it! The number was ${secret}. Tries: ${tries}`);
    break;
  }
}

What changed:

  • Cancel now ends the game properly.
  • Number(answer) turns the text into a real number. Number("hello") gives NaN.
  • Number.isInteger(guess) is false for NaN and for decimals like 4.5, so bad input is caught.
  • continue skips the rest of this round and goes straight back to the top of the loop, without counting a try.
  • The final else is now safe: by the time we reach it, guess is definitely a number from 1 to 100 that's neither too high nor too low.

Play again and try to break it. That's what testers do.

Step 6: Organise it with functions

The game works, but everything is in one big block. Let's split it into functions that each do one job (lesson 6):

function pickSecret(max) {
  return Math.floor(Math.random() * max) + 1;
}

function isValidGuess(guess, max) {
  return Number.isInteger(guess) && guess >= 1 && guess <= max;
}

function getHint(guess, secret) {
  if (guess > secret) return "Too high!";
  if (guess < secret) return "Too low!";
  return "Correct!";
}

function playGame(max) {
  const secret = pickSecret(max);
  let tries = 0;

  while (true) {
    const answer = prompt(`Guess a number from 1 to ${max}:`);

    if (answer === null) {
      alert(`Game over. The number was ${secret}.`);
      return;
    }

    const guess = Number(answer);

    if (!isValidGuess(guess, max)) {
      alert(`Please type a whole number from 1 to ${max}.`);
      continue;
    }

    tries++;
    const hint = getHint(guess, secret);

    if (hint === "Correct!") {
      alert(`You got it in ${tries} tries! The number was ${secret}.`);
      return;
    }

    alert(hint);
  }
}

playGame(100);
playGame at the top, built from pickSecret, isValidGuess, and getHint; getHint(50, 74) returns Too low!
Each helper does one job and can be tested on its own.

It does exactly the same thing, but now:

  • playGame reads like the pseudocode from Step 1.
  • Each helper can be tested on its own, for example console.log(getHint(50, 74)) should print Too low!.
  • Changing the game is easy: playGame(1000) makes it harder, with no other edits.

Notice return inside playGame. It ends the whole function, which also ends the loop. It does the job break did before.

Step 7: Make it yours

Your game works. Now improve it. Pick at least two:

  1. Limit the tries. The player loses after 7 wrong guesses. (Hint: add a condition on tries.)
  2. Difficulty levels. Ask "easy, medium or hard?" first, and use 1–10, 1–100 or 1–1000.
  3. Warmer / colder. If the guess is within 5 of the secret, say "Very close!" as well.
  4. Play again. After winning, use confirm("Play again?") (it returns true or false) to start a new round.
  5. Best score. Keep track of the fewest tries across rounds in a variable.

Plan each change with pseudocode first, then code it, then test it. That's the whole cycle, and it's exactly how professionals work, just on bigger problems.


You finished Programming Foundations 🎉

Look at what you can do now:

  • Break a vague problem into clear steps and pseudocode
  • Store information in variables and pick the right data types
  • Make decisions with conditions
  • Repeat work with loops
  • Organise code into functions
  • Debug calmly, and use AI as a tutor instead of a crutch

These ideas are the same in every programming language. When you learn Python, Swift or Dart later, you'll recognise them all; only the spelling changes.

Where to go next: the Web Development course, where you'll use these same skills to build real websites with HTML, CSS and JavaScript.