Learning Goals 3 min
By the end of this lesson you will be able to:
- Use two variables — score and high-score — and explain which one resets each game and which one survives across games in the same Scratch session.
- Write the one-line update if <(score) > (high-score)> then set [high-score v] to (score) that runs on every game-over and pushes the new best when one happens.
- Maintain a short top-scores list capped at 5 entries using add ... to, length of [top-scores v], and delete (1) of — a tiny leaderboard.
Warm-Up — Devi's amnesia game 7 min
Devi is showing off her catch-the-rambutan game to her cousin. Each round she gets a slightly higher score. After her sixth run, her cousin asks: "Hey, what's your best score so far?" Devi looks at the Stage. Score says 23. But that's only her current game. Her best was 47 two games ago.
when flag clicked
set [score v] to (0)
forever
if <touching [rambutan v] ?> then
change [score v] by (1)
wait (0.3) seconds
end
end
Predict — could Devi add a second variable that remembers her best score across games? What block would she use to update it, and when?
Reveal the answer
Yes — a second variable called high-score. The trick is what you don't do: you don't reset it at flag click. Scratch keeps variable values between flag clicks (as long as the project stays open), so high-score survives. The only place it changes is at game-over — and only if the just-finished score beat it.
The update is one if-then: <(score) > (high-score)>, set high-score to score. That's the whole feature in one block.
Today's lesson is small but powerful — you'll add maybe ten new blocks and Devi's game will gain memory.
New Concept — two variables, one comparison 15 min
The score system has two parts: the score that ticks during play, and the high score that updates rarely but lives forever.
Part 1 — the score variable
You've used this since Level 2. Make a Variable → score → "For all sprites". At flag click, reset to 0. During play, change [score v] by (1) when something good happens.
when flag clicked
set [score v] to (0)
Part 2 — the high-score variable
Make a Variable → high-score → "For all sprites". Do not reset it at flag click. That's the whole secret. Scratch keeps variable values between flag clicks within the same session — so once you set high-score to something, it stays there until you update it again or close the project.
The first time you ever click the flag, high-score is 0 (default for new number variables). After your first game, it gets pushed up. After that, it only changes when you do better.
Part 3 — the update check
When does the high-score change? Exactly one place: at game-over, when you've just finished a run and the score from that run is bigger than the stored high-score. One block does it:
when I receive [game over v]
if <(score) > (high-score)> then
set [high-score v] to (score)
end
If the current score didn't beat the high-score, nothing happens — the high-score keeps its old value. That's correct. Most runs don't break the record.
Part 4 — showing the best on the title screen
The high-score is most useful when the player can see it before starting. Show it on the title screen with a friendly say block. Use join to stitch text and the number together:
when I receive [enter title v]
say (join [Best: ] (high-score)) for (2) seconds
Part 5 — a tiny leaderboard with a list
One high-score is nice. A list of your last five scores is more interesting. Make a List (orange palette, Make a List) named top-scores. At each game-over, add the current score to it. If the list ever has more than 5 entries, delete the oldest (slot 1):
when I receive [game over v]
add (score) to [top-scores v]
if <(length of [top-scores v]) > (5)> then
delete (1) of [top-scores v]
end
Tick the list's checkbox on the Stage. After five games it fills up. After six, the oldest falls off the top. After seven, the second-oldest falls. The list always shows the most recent five runs.
Worked Example — Aisha's rambutan catcher leaderboard 12 min
Aisha is upgrading her rambutan catcher. She wants a score that ticks up, a personal best on the title screen, and a top-5 list. Eight steps.
Step 1 — Three variables, one list
From Variables: Make a Variable → score. Make a Variable → high-score. Make a Variable → state (if you don't have one from L03-27). Make a List → top-scores. Tick the score, high-score, and top-scores checkboxes so all three appear on the Stage.
Step 2 — Reset score at flag click
On the Stage:
when flag clicked
set [score v] to (0)
set [state v] to [title]
broadcast (enter title v)
score resets, high-score does NOT. That's deliberate. The enter title broadcast triggers the title-screen show-best script.Step 3 — Score ticks up during play
On the basket (catcher) sprite:
when flag clicked
forever
if <(state) = [play]> then
if <touching [rambutan v] ?> then
change [score v] by (1)
wait (0.3) seconds
end
end
end
Step 4 — Show the best on the title screen
On the cat (or any sprite, but pick one consistent host for title-screen messages):
when I receive [enter title v]
say (join [Best: ] (high-score)) for (2) seconds
Best: 0. After a game, it shows whatever the best run produced.Step 5 — Update high-score at game-over
On the Stage:
when I receive [game over v]
if <(score) > (high-score)> then
set [high-score v] to (score)
end
Step 6 — Push to the leaderboard list
Still on the Stage, a second receive handler:
when I receive [game over v]
add (score) to [top-scores v]
if <(length of [top-scores v]) > (5)> then
delete (1) of [top-scores v]
end
Step 7 — Test the high-score
Click the flag. Title screen says Best: 0. Play a game, score some points, let it end. The Stage shows high-score: 5 (or whatever you scored). Click flag again. Title screen says Best: 5. Score 3, lose. high-score stays 5 (because 3 is not greater than 5). Score 8, lose. high-score updates to 8. Click flag again — Best: 8. The variable remembers.
Step 8 — Test the leaderboard
Play six games in a row. After game 5, the list shows all five scores. After game 6, the first score (your oldest) is gone — the list shows games 2 through 6. After game 7, games 3 through 7. The list always shows your last five runs.
The full assembled stack
when flag clicked
set [score v] to (0)
set [state v] to [title]
broadcast (enter title v)
when I receive [enter title v]
say (join [Best: ] (high-score)) for (2) seconds
when I receive [game over v]
if <(score) > (high-score)> then
set [high-score v] to (score)
end
when I receive [game over v]
add (score) to [top-scores v]
if <(length of [top-scores v]) > (5)> then
delete (1) of [top-scores v]
end
What you just built: the same score + best + recent-runs pattern that powers every arcade cabinet from Galaga to Geometry Dash. The whole thing is two variables and one list. Real games use saved files or cloud variables to persist the high-score across sessions; Scratch's in-session memory is good enough for class.
Try It Yourself — three score drills 15 min
Goal: One cat, one ball. Each time the cat clicks the ball, score goes up by 1. When the space key is pressed, the cat announces its score and the game stops. No high-score yet — just clean score-counting.
when flag clicked
set [score v] to (0)
when this sprite clicked
change [score v] by (1)
when [space v] key pressed
say (join [You scored: ] (score)) for (2) seconds
stop [all v]
Think: The space key acts like a manual "game over" — without it, the score would tick forever. Real games use lives or timers instead, but the principle is the same: something has to end the game so the score is final.
Goal: Take the Easy ball-clicker. Add a high-score variable. At flag click, score resets to 0 but high-score does NOT. When the space key is pressed, the cat compares score to high-score and updates if better. Then it announces the high-score and stops.
when flag clicked
set [score v] to (0)
when this sprite clicked
change [score v] by (1)
when [space v] key pressed
if <(score) > (high-score)> then
set [high-score v] to (score)
say [New best!] for (1) seconds
end
say (join [Best: ] (high-score)) for (2) seconds
stop [all v]
Think: Why doesn't the high-score reset at flag click? Try resetting it (add set [high-score v] to (0) at flag click) and see — every new game wipes the record. That defeats the entire purpose.
Goal: Add the leaderboard list to the Medium ball-clicker. After each "press space to end" round, the score is added to top-scores. The list is capped at 5. Show the list on the Stage so you can watch it fill up and roll over.
when [space v] key pressed
if <(score) > (high-score)> then
set [high-score v] to (score)
end
add (score) to [top-scores v]
if <(length of [top-scores v]) > (5)> then
delete (1) of [top-scores v]
end
say (join [Best: ] (high-score)) for (2) seconds
stop [all v]
Think: Play seven games — scores like 3, 7, 2, 9, 4, 6, 1. After game 5, the list shows [3, 7, 2, 9, 4]. After game 6, the 3 falls off, list becomes [7, 2, 9, 4, 6]. After game 7, the 7 falls off, list becomes [2, 9, 4, 6, 1]. The list always shows your last 5 runs in the order you played them.
Mini-Challenge — Chong's record-that-wasn't 5 min
"The high-score that resets itself"
Chong built the high-score system. He plays one game, scores 42. The Stage shows high-score: 42. Good. He clicks the flag to play again. The Stage shows high-score: 0. His record is gone. He shows you his startup script:
when flag clicked
set [score v] to (0)
set [high-score v] to (0)
set [state v] to [title]
What's the one line that's wiping Chong's hard-earned record?
Reveal one valid solution
The middle line is the problem. set [high-score v] to (0) runs every single flag click, so the high-score is reset back to zero before the player even starts a new game. Score is supposed to reset; high-score is supposed to persist.
The fix is to delete that one block:
when flag clicked
set [score v] to (0)
set [state v] to [title]
Now score still resets every flag click, but high-score keeps whatever value it had from the previous game. The first time you ever run the project, high-score is 0 anyway (default for new number variables) — so there's no need to set it explicitly. The lesson: ask yourself "should this reset every game?" for every variable. Some say yes, some say no. The "no" ones are what give your game memory.
Recap 3 min
You added persistent memory to your game. score resets each round and ticks up during play. high-score does NOT reset — it survives across games in the same Scratch session. At each game-over, one if-then compares the just-finished score to the stored high-score and updates if better. A top-scores list gives you a rolling leaderboard: every score gets pushed on, and once the list exceeds 5, the oldest falls off the top. The pattern is small — about eighteen blocks for the whole feature — but the player-facing effect is huge: effort now counts for something.
- Score variable
- A counter that resets each game (set [score v] to (0) at flag click) and changes during play (change [score v] by (1)). The number the player is currently chasing.
- High-score variable
- A counter that does NOT reset at flag click — Scratch keeps its value across games in the same session. Only updated at game-over, only if the just-finished score was strictly better.
- Persistence
- The idea that some data survives beyond a single run. In Scratch, variables persist within a session but vanish when the project is closed. Real games use save files or cloud storage.
- Strict greater-than
- The () > () comparison — true only when the left is bigger. Used for high-score updates so exact ties don't trigger a "new record" message.
- Rolling list / FIFO cap
- A list that's allowed to grow to a fixed size, then drops its oldest entry each time a new one is added. Pattern: add + if <(length) > (cap)> then delete (1) of.
- join
- The Operators reporter join () () that stitches two things together as text. Used to make readable messages like
Best: 47from a label and a variable.
Homework 2 min
The Memory-able Maze Runner. Build (or open) a small maze game where a cat moves with arrow keys, collecting yellow dots to score points. Add the full score + high-score + leaderboard system.
- Make three variables: score, high-score, state. Make a list: top-scores. Tick the score, high-score, and top-scores checkboxes.
- At flag click: reset
scoreto 0 (but NOThigh-score), set state totitle, broadcast enter title. - On the title screen handler: say (join [Best: ] (high-score)) for (2) seconds. Then your usual title → press space → start game flow.
- During play: each time the cat touches a yellow dot, hide the dot and change [score v] by (1).
- When the cat touches a wall (or some failure condition), broadcast game over.
- On when I receive [game over v]: the high-score-update if-then, plus the add-and-cap leaderboard pattern.
- Bonus: Add a sprite that shows the top-scores list as a formatted "Recent Runs" label. (Hard mode: stitch the list together using a loop — that's L03-12 territory.)
Save as HW-L3-30-Memory-Maze.sb3. Test: play three rounds with different scores. Each time you return to the title, the "Best:" message should show the highest of the three. After five rounds, the list should be full; after six, the oldest should fall off.
Bring back next class:
- The
.sb3file. - Your answer to: "Close the project and reopen it. What happens to
high-score? Why?" (Hint: Scratch's variable memory only lasts the session — closing the project wipes it. The fix is "cloud variables" for shared Scratch projects, which we won't cover but you can read about.)
Heads up for next class: SCR-L03-31 is the cluster's capstone. You'll combine everything from this whole cluster — title screen, play, pause, lives, score, high-score — into one polished Pause-able Catch Game. No new concepts. Just careful assembly of seven lessons' worth of patterns into one game you'd be proud to show your family.