Guessing Game
Combine functions, conditionals, arrays, and early loop termination into game logic.
Core concepts
conditionals, arrays, function composition, early return
How the learner should approach this project
Do not paste the complete program immediately. Create the file, type the first step, run vpp check, and then run the program when a complete entry point exists. Read the explanation before looking at the snippet. After each step, predict what the new code should do. This turns the page into a lesson rather than a code dump.
Step 1: Produce a hint
The hint function compares a guess against a secret. It returns one of three strings. Because the equality case is the only case left after the two comparisons, the final return is correct.
After typing the snippet, identify the new names introduced by the step. Ask what each name represents, what type the compiler should infer or check, and what value should exist after the code runs.
fn hint(guess: int, secret: int) -> string {
if guess < secret {
return "too low"
}
if guess > secret {
return "too high"
}
return "correct"
}Step 2: Turn the hint into a round result
play_round delegates the comparison to hint, prints the message, and converts the message into a bool. The bool tells the outer loop whether the game is finished.
Before moving forward, explain how this step connects to the previous one. In particular, identify which values cross a function boundary, which values change, and which values are guaranteed by the type system.
fn play_round(secret: int, guess: int) -> bool {
let message = hint(guess, secret)
print(message)
return message == "correct"
}Step 3: Try guesses until correct
The guesses array acts as predetermined input for this lesson. Each guess is printed and passed to play_round.
When the function returns true, main prints the win message and returns immediately.
Before moving forward, explain how this step connects to the previous one. In particular, identify which values cross a function boundary, which values change, and which values are guaranteed by the type system.
fn main() -> int {
let secret = 42
let guesses = [10, 30, 50, 42]
for g in guesses {
print(g)
if play_round(secret, g) {
print("you win")
return 0
}
}
return 0
}Complete source
fn hint(guess: int, secret: int) -> string {
if guess < secret {
return "too low"
}
if guess > secret {
return "too high"
}
return "correct"
}
fn play_round(secret: int, guess: int) -> bool {
let message = hint(guess, secret)
print(message)
return message == "correct"
}
fn main() -> int {
let secret = 42
let guesses = [10, 30, 50, 42]
for g in guesses {
print(g)
if play_round(secret, g) {
print("you win")
return 0
}
}
return 0
}Expected behavior
The complete program should produce the following output when run with the command shown below. Exact formatting should follow the current V++ runtime.
10 too low 30 too low 50 too high 42 correct you win
Run the project
vpp run projects/17-guessing-game/main.vppWhat the learner should understand after this project
Small games are good for learning control flow because they turn simple comparisons into a stateful sequence of decisions.
Common mistakes to teach
- Reversing the low and high messages
- Never stopping after the correct guess
- Changing the secret without updating the test guesses
Practice extension
Change the secret and guesses. Then add an attempt counter using let mut.
A strong learner should be able to explain the program without looking at the code, rebuild the core idea from memory, and make the practice change without copying a solution.
Full program
fn hint(guess: int, secret: int) -> string {
if guess < secret {
return "too low"
}
if guess > secret {
return "too high"
}
return "correct"
}
fn play_round(secret: int, guess: int) -> bool {
let message = hint(guess, secret)
print(message)
return message == "correct"
}
fn main() -> int {
let secret = 42
let guesses = [10, 30, 50, 42]
for g in guesses {
print(g)
if play_round(secret, g) {
print("you win")
return 0
}
}
return 0
}