Course 08 · Blazor · Your first app

Build the Guess the Number Game

In one sitting you'll build a complete little app — a number-guessing game — that picks a secret number, takes your guess, and tells you if you're too high, too low or spot on. Everything you've learned so far, working together.

Follow along in Visual Studio. Each step shows exactly which file to create or open and what to type — use the Copy button if you get stuck. Tip: click the button to go full screen and show just the current step. The build steps end with the real, playable game running live in the page.
Step 1 of 13

Today's goal

Build the Guess the Number Game

Build a working game: the app secretly picks a number from 1 to 10, you type a guess and press a button, and it tells you too high, too low, or correct — counting how many guesses it took.

By the end you'll be able to:

  • Generate a random number in C# with Random.
  • Read what the user typed using two-way binding (@bind).
  • Make decisions with if / else if / else and the ==, < and > operators.
  • Wire it all to your <MyButton> from last lesson into one small, finished app.

Recap

Fast-fire: what do we remember?

Shout out the answers — quick questions on things we've already covered.

  • What does two-way binding (@bind) do?
  • What's the difference between = and == in C#?
  • What does an if / else if / else chain let our code do?
  • What is an EventCallback, and where did we use one?
  • What does count++ do?

Fast-fire · together

What does it do? #1

Read the code and predict the answer before we reveal it.

What does it do?

What numbers can secret end up being?

GuessTheNumber.razor
@code {
    int secret = new Random().Next(1, 11);
}
Reveal the answer

A whole number from 1 to 10not 1 to 11. Next(min, max) includes the lower bound but excludes the upper one, so Next(1, 11) means “1 up to but not including 11”. A classic off-by-one trap.

Fast-fire · together

Spot the error #1

This snippet is from the game we're about to build. Shout out everything that's wrong.

Spot the error
GuessTheNumber.razor
<input @bind="guess" />
<MyButton OnClick="CheckGuess">Guess</MyButton>
<p>@message</p>

@code {
    int secret = 7;
    int guess;
    string message = "";

    void Check()
    {
        if (guess = secret)
            message = "Correct!";
        else if (guess < secret)
            message = "Too low"
        else
            message = "Too high";
    }
}
Reveal the answer
  1. OnClick="CheckGuess" calls a method that doesn't exist — the method below is named Check. The names must match exactly.
  2. if (guess = secret) uses a single = (assignment) instead of == (comparison). A condition must be true/false, and guess = secret isn't — it won't compile.
  3. message = "Too low" is missing its semicolon — every statement ends with ;.

Fast-fire · together

Spot the error #2

A different snippet — shout out anything that looks wrong.

Spot the error
GuessTheNumber.razor
<input @bind="guess" />
<MyButton OnClick="NewGame">New game</MyButton>
<p>@message</p>

@code {
    int secret;
    string guess;
    string message = "";

    void NewGame()
    {
        secret = new Random().Next(1, 10);
        message = "I'm thinking of a number from 1 to 10...";
    }
}
Reveal the answer
  1. string guess; is the wrong type — to compare a guess against secret (an int), guess must be an int too. A string would never compare numerically.
  2. Next(1, 10) is an off-by-one logic bug: it only ever produces 1–9, so the secret can never be 10 even though the message promises “1 to 10”. It should be Next(1, 11).

Fast-fire · together

What does it do? #2

One more prediction before we build.

What does it do?

After pressing the button three times, what does the paragraph show?

GuessTheNumber.razor
<p>@message</p>

@code {
    int tries = 0;
    string message = "";

    void Check()
    {
        tries++;
        message = "Guess number " + tries;
    }
}
Reveal the answer

“Guess number 3”. tries++ adds one each press (0 → 1 → 2 → 3), and "Guess number " + tries glues the text to the number, so the value climbs with every click.

Build · The secret number

Start the page and pick a secret

A game is just a page that holds some state in @code and reacts to the user. Let's start with the one thing every guessing game needs: a secret number the computer chooses.

Do this: In Visual Studio, right-click the Pages folder → Add → Razor Component, name it GuessTheNumber.razor, and replace its contents with the code below.
GuessTheNumber.razor — create this file
@page "/guess"

<h1>Guess the Number</h1>
<p>I'm thinking of a number from 1 to 10.</p>

@code {
    int secret = new Random().Next(1, 11);
}

The @page "/guess" line gives the page its own address. new Random().Next(1, 11) picks the secret — remember, that's 1 to 10, not 11.

Notice: the secret exists, but nothing shows it and there's no way to guess yet. Next we add the input and the button.

Build · Make it reachable

Add a link to your new page

Your page now lives at the address /guess — but nothing points to it, so the only way to reach it is to type the address into the browser by hand. Real apps give every page a link in the menu. In a Blazor project that menu lives in one shared file, NavMenu.razor, and each page you want in the sidebar gets its own <NavLink>.

Do this: open Shared/NavMenu.razor and add the block below next to the menu items already there (Home, Counter, Weather).
Shared/NavMenu.razor — add a menu item
<div class="nav-item px-3">
    <NavLink class="nav-link" href="guess">
        Guess the Number
    </NavLink>
</div>

The href="guess" here matches the @page "/guess" on your page — that's exactly how Blazor connects a menu link to a page: by its route. (The menu drops the leading slash; same address.)

Notice: run the app (F5) — your new Guess the Number link now appears in the sidebar, and clicking it opens the page. Two separate files, the page and the menu, working together.

Build · Take a guess

Add the input and the button

We need somewhere to type a guess, and a button to submit it. The input uses two-way binding (@bind) so whatever the user types lands in a C# variable called guess. The button is your <MyButton> from last lesson — it calls a method when activated by mouse or keyboard.

Do this: update GuessTheNumber.razor so it matches the code below. (If your MyButton lives in a Components folder, Blazor finds it automatically — no extra @using needed.)
GuessTheNumber.razor
@page "/guess"

<h1>Guess the Number</h1>
<p>I'm thinking of a number from 1 to 10.</p>

<input type="number" @bind="guess" />
<MyButton OnClick="Check">Guess</MyButton>

<p>@message</p>

@code {
    int secret = new Random().Next(1, 11);
    int guess;
    string message = "";

    void Check()
    {
        // We'll fill this in next.
    }
}
Notice: pressing the button calls Check(), but it does nothing yet, so message stays empty. Time to make it decide.

Build · Make it decide

Too high, too low, or correct?

This is the heart of the game: compare the guess with the secret and set the message. An if / else if / else chain checks the three possibilities in order — equal first, then lower, otherwise higher.

GuessTheNumber.razor — fill in Check()
void Check()
{
    if (guess == secret)
        message = "Correct! 🎉";
    else if (guess < secret)
        message = "Too low — try higher.";
    else
        message = "Too high — try lower.";
}
Watch out: it's guess == secret with two equals signs — comparison, not assignment. One = would try to change secret and won't even compile.

That's a fully playable game already. Run it (F5), type a number and press Guess. Now let's make it count your tries.

Build · Count the guesses

Add a guess counter

Every guess should bump a counter — exactly the tries++ idea from the fast-fire round. Add a tries field, increase it at the start of Check(), and show it on the page.

GuessTheNumber.razor — finished game
<input type="number" @bind="guess" />
<MyButton OnClick="Check">Guess</MyButton>

<p>@message</p>
<p>Guesses so far: @tries</p>

@code {
    int secret = new Random().Next(1, 11);
    int guess;
    int tries = 0;
    string message = "";

    void Check()
    {
        tries++;

        if (guess == secret)
            message = "Correct! 🎉";
        else if (guess < secret)
            message = "Too low — try higher.";
        else
            message = "Too high — try lower.";
    }
}

Here's the finished game running live — type a guess, or Tab to the button and press Enter:

▶ Live — the finished Guess the Number game
✎ Exercise — can you win in as few guesses as possible?
You built an app. A random secret, user input, a decision, and feedback on screen — that's the shape of countless real programs. Everything from here is making it nicer.

Your turn

Exercises — pick your level

Build on your GuessTheNumber.razor. Start where you're comfortable and climb as far as you can.

  • Easy

    Change the range

    Make the game pick from 1 to 20 instead of 1 to 10 (remember the off-by-one rule), and update the on-screen text to match.

  • Easy

    Friendlier messages

    Reword the too-high / too-low / correct messages in your own style, and show the number of guesses inside the “Correct!” message.

  • Medium

    Play again

    Add a second button that starts a new game — pick a fresh secret, reset tries to 0, and clear the message.

  • Medium

    Colour the feedback

    Show “Correct!” in green, “Too high” in orange and “Too low” in blue, using a CSS class you switch in Check().

  • Hard

    Out-of-range guard

    If the guess is below 1 or above 10, show “Stick to 1–10!” and don't count it as a guess.

  • Hard · Advanced

    One-Question Quiz

    Build a separate Quiz.razor page that asks a single multiple-choice question (e.g. “What does == do in C#?”). The student types or picks an answer, presses your <MyButton>, and an if/else shows “Correct! ✅” or “Not quite — try again.” Same ingredients as the game, but comparing text instead of numbers. Stretch within the stretch: add a second question or keep a score.

Homework

Before next time

Finish these at home — we'll review them at the start of the next lesson.

  • Core

    Play again

    Add the “new game” button so the game can be replayed without restarting the app.

  • Core

    Colour the feedback

    Make the message change colour depending on the result.

  • Stretch

    One-Question Quiz

    Build the advanced quiz page above. Bring it next time to show the group.