Computer Science Essentials · Unit 1 Project

Build Your Own Game

You have built an app that draws and an app that moves. Now build a game — your choice of five — with nothing but the blocks you already know, plus two or three new ones you'll meet along the way.

Pick ONE of five5 class days100 pointsPlan before you build

How this works

1
Pick one game from the five below. Two are beginner, two are intermediate, and Tic-Tac-Toe is the logic puzzle in the middle. Pick by how confident you feel, not by which sounds coolest — you can always add stretch goals.
2
Fill out the plan sheet at the bottom of this page and show it to Mr. Babb. No plan, no building. Every game on this page starts with a WHEN / DO table, because every app does.
3
Build the must-haves first, following the step-by-step build guide for your game. A boring game that works beats an amazing game that crashes. Stretch goals come after every must-have is checked off.
4
Test it on the phone, break it on purpose, fix it. Keep a bug log — three bugs you hit and what was actually wrong. That log is part of your grade.
5
Demo it on day 5, export your .aia, and turn in the reflection.

Which one is for me?

Three honest questions. Nobody sees your answers but you.

In Happy Accelerometer, moving the sprite with set Happy.X to (Happy.X + xAccel) was…
An if / else block that compares two numbers…
When my app breaks, I usually…

The five games

Tap a game to see exactly what it needs. Green = blocks you already used. Orange = new to you.

🐹 Mole Mash

Intermediate · Canvas + sprite + Clock
Score: 7   Miss: 2
🐹
RESET

A mole pops up somewhere new on the canvas every second. Tap it: +1. Tap the grass: that's a miss. Reset starts over.

This is Happy Accelerometer's cousin: same Canvas, same ImageSprite, same score variable. The new idea is a Clock that fires on its own instead of waiting for a tilt.

You already know

  • Canvas + ImageSprite (upload a mole image or use an emoji in a Label — sprite is better)
  • initialize global score to 0
  • set global score to (global score + 1) — read → change → write
  • when Mole.Touched — a sprite event, like EdgeReached
  • A procedure you call from more than one place

New to you

  • Clock component (Sensors drawer). Set TimerInterval to 1000 = fires once a second.
  • when Clock1.Timer — an event the phone fires, not the user
  • random integer from 0 to … (Math drawer)
  • call Mole.MoveTo(x, y) — moves a sprite in one block instead of setting X then Y
  • if touchedAnySprite = false inside when Canvas1.Touched — so tapping the mole doesn't ALSO count as a miss

Must-haves (all five to pass)

  • M1Mole moves to a random spot every second and never goes off the canvas. (Hint: random X from 0 to Canvas.Width − Mole.Width.)
  • M2Tapping the mole adds 1 to a score shown in a Label.
  • M3Tapping empty canvas adds 1 to a miss counter — and tapping the mole does NOT.
  • M4A Reset button sets both counters to 0 using a procedure called reset.
  • M5The mole moves through a procedure called moveMole that is called from the Timer and from Touched (so it jumps away when you hit it).

Build order

  1. Designer: Canvas (Width Fill parent, Height 300), ImageSprite inside it, two Labels, one Button, one Clock.
  2. Variables: score, misses, both 0.
  3. Procedure moveMole: MoveTo random X, random Y. Test: tap Timer on, mole should hop.
  4. Mole.Touched: score + 1, update Label, call moveMole.
  5. Canvas.Touched: if not touchedAnySprite → misses + 1.
  6. Procedure reset, wire the Button. Done — now stretch.

When it breaks

  • Mole never moves: Clock's TimerEnabled is unchecked, or the Timer block is empty.
  • Mole hides off the edge: you used Canvas.Width instead of Canvas.Width − Mole.Width.
  • Every hit also counts a miss: the touchedAnySprite check is missing.
  • Score Label never changes: you changed the variable but never set Label.Text.

Stretch goals (after all five)

  • Speed up: every 5 hits, set Clock1.TimerInterval smaller (minimum 300).
  • A Sound component that plays on a hit.
  • A 30-second round: a second Clock that counts down in a Label and stops the game.

🧺 Catch It!

Intermediate · Two sprites + Clock + collisions
Caught: 4   Lost: 1
🎁
🧺

Gifts fall from the top. Slide the basket left and right — by tilting the phone or dragging — to catch them. Miss one and it counts against you.

Pick this if Happy Accelerometer clicked for you. It is the same movement block, plus a second sprite that moves by itself.

You already know

  • Canvas + ImageSprite, the coordinate grid (Y grows down — that is why the gift falls by adding to Y)
  • set Basket.X to (Basket.X + xAccel) — or Canvas.Dragged with currentX if you prefer
  • when Basket.EdgeReached to keep the basket on screen
  • Variables for caught / lost, a reset procedure

New to you

  • Clock at TimerInterval 50 — fires 20× a second, that is the "animation"
  • when Gift.CollidedWith(other) — fires when two sprites overlap
  • if Gift.Y > Canvas1.Height — the gift fell past the bottom
  • random integer for where the next gift starts
  • A speed variable so you can tune difficulty in one place

Must-haves (all five to pass)

  • M1The gift falls on its own (Clock adds speed to Gift.Y every tick).
  • M2The basket moves left/right by tilt or drag, and cannot leave the canvas.
  • M3Basket touches gift → caught + 1, gift respawns at the top at a random X. (Use a procedure called dropNewGift.)
  • M4Gift reaches the bottom → lost + 1, then dropNewGift.
  • M5Both counters show in Labels; a Reset button zeroes them through a reset procedure.

Build order

  1. Designer: Canvas, Basket sprite near the bottom, Gift sprite at the top, two Labels, Button, Clock (interval 50), AccelerometerSensor if tilting.
  2. Get the basket moving first (copy Happy Accelerometer). EdgeReached → stop it.
  3. Procedure dropNewGift: set Gift.Y to 0, Gift.X to random.
  4. Clock.Timer: Gift.Y + speed. If Gift.Y > Canvas.Height → lost + 1, dropNewGift.
  5. Gift.CollidedWith → caught + 1, dropNewGift.
  6. Labels + reset procedure + button.

When it breaks

  • Gift falls up: you subtracted from Y. On a screen, down is bigger.
  • One catch counts 3 or 4 times: CollidedWith keeps firing while they overlap — call dropNewGift immediately so the gift leaves.
  • Basket flies off screen: no EdgeReached handler, or you forgot call Basket.Bounce / MoveTo inside it.
  • Nothing moves at all: Clock.TimerEnabled unchecked, or the sprites are not inside the Canvas.

Stretch goals

  • Add a second falling sprite that you must dodge — catching it costs a point.
  • Speed climbs by 1 every 5 catches.
  • Three lives, then a "Game over" Notifier with the score.

✊ Rock, Paper, Scissors

Beginner · Buttons + random + if/else
You 3 — Phone 2
✋ vs ✌️
Scissors cut paper. Phone wins.
✊
✋
✌️

Three buttons. You pick, the phone picks at random, the app says who won and keeps score. First to 5 wins the match.

No canvas, no sprites. This one is all about decisions: an if / else if / else chain that decides the winner. Pick this if you want to nail 1.1.3 selection logic.

You already know

  • Buttons and when Rock.Click (three of them)
  • Labels and set Label.Text to
  • Variables: you, phone scores; set global you to (global you + 1)
  • A procedure so the three buttons don't repeat the same 15 blocks

New to you

  • random integer from 1 to 3 = the phone's choice (1 rock, 2 paper, 3 scissors)
  • if … else if … else — click the blue gear on the if block to add else-if branches
  • A procedure with a parameter: to play(mine) — each button calls play with 1, 2 or 3
  • join to build the message: join("You picked ", mine, "…")

Must-haves (all five to pass)

  • M1Three buttons, each calls ONE procedure play with a different parameter value.
  • M2The phone's choice is random and shown on screen (text or emoji) every round.
  • M3The app correctly decides win / lose / tie for all 9 combinations (test every one — that's your bug log).
  • M4Scores for you and the phone update in Labels.
  • M5First to 5 shows a match-over message and a New Match button resets both scores through a reset procedure.

Build order

  1. Designer: 3 Buttons in a HorizontalArrangement, 3 Labels (phone pick, result, score), 1 New Match button.
  2. Variables you = 0, phone = 0.
  3. Procedure play(mine): set local phonePick to random 1–3, show it.
  4. Inside play: if mine = phonePick → tie. Else if (mine=1 and phonePick=3) or (mine=2 and phonePick=1) or (mine=3 and phonePick=2) → you win. Else → phone wins.
  5. Update scores + Labels. Then: if you = 5 or phone = 5 → match over.
  6. Wire the three buttons: call play(1), play(2), play(3).

When it breaks

  • Phone always picks the same thing: random is outside the procedure, so it ran once at startup.
  • Paper beats scissors: one of your three win conditions is flipped. Test all nine on paper first.
  • Scores jump by 2: the +1 block is inside two branches.
  • "Ties" never show: the = check is comparing text "1" to number 1 — use the Math = block, not the Text compare.

Stretch goals

  • Images instead of text for both picks.
  • A streak counter: how many wins in a row.
  • Best-of-3 / best-of-5 picker before the match starts.

🔢 Guess My Number

Beginner · TextBox + random + if/else
I'm thinking of 1–100
37
GUESS
Too low! Guess #3

The phone picks a secret number. Type a guess, tap Guess, and it tells you higher or lower until you get it — and counts your tries.

The smallest game here, but it has the most input handling. What if they type nothing? Letters? 500? A good version handles all three.

You already know

  • when Screen1.Initialize — runs once at startup (from Happy Accelerometer)
  • Button.Click, Labels, set Label.Text to
  • Variables: secret, guesses; read → change → write for the counter
  • A newGame procedure

New to you

  • TextBox component — set NumbersOnly on in the Designer; read it with TextBox1.Text
  • random integer from 1 to 100
  • if … else if … else comparing guess to secret with < and >
  • is number? — true if the TextBox holds a real number
  • Notifier component: call Notifier1.ShowAlert for "You got it!"

Must-haves (all five to pass)

  • M1A random secret from 1 to 100 is chosen in Screen1.Initialize — and a different one each time you tap New Game (so: a newGame procedure, called from both).
  • M2Each guess shows "Too high", "Too low" or "You got it" in a Label.
  • M3A guess counter goes up by 1 per guess and shows on screen.
  • M4An empty TextBox or a non-number does NOT count as a guess — it shows "Type a number first."
  • M5On a win, the message says how many guesses it took, and the Guess button is disabled until New Game.

Build order

  1. Designer: Label (title), TextBox (NumbersOnly), Button Guess, Label (feedback), Label (count), Button New Game, Notifier.
  2. Variables secret = 0, guesses = 0.
  3. Procedure newGame: secret = random 1–100, guesses = 0, clear Labels, enable Guess button. Call it from Screen1.Initialize.
  4. Guess.Click: if not is number?(TextBox.Text) → "Type a number first." Stop there (put the rest in the else).
  5. Else: guesses + 1. If guess < secret → too low. Else if > → too high. Else → won: message with guesses, disable button.
  6. Wire New Game → call newGame.

When it breaks

  • Always "Too high": secret is still 0 — newGame never ran. Is it called from Initialize?
  • App crashes on empty box: you compared "" to a number. The is-number check must come first.
  • Counter counts the blank guesses: the +1 is above the if, not inside the else.
  • "Got it" but the number was different: you compared TextBox.Text (text) to secret with the Text compare block. Use Math =.

Stretch goals

  • "Warmer / colder" instead of high / low (compare the new distance to the last one — needs one more variable).
  • A best-score variable: fewest guesses this session.
  • Let the player choose the range (1–10, 1–100, 1–1000) before starting.

❌ Tic-Tac-Toe

Beginner+ · Nine buttons + a procedure that answers a question
O's turn
${'
X
O
X
'}
NEW GAME

Two players, one phone. Tap a square to place X or O, the app takes turns, spots a win on any of the eight lines, calls a draw when the board fills, and keeps score.

No canvas, no sensors. The whole game is one question asked eight times: "are these three squares the same?" You write that question once as a procedure. Pick this if you liked the if/else logic in 1.1.3 and want more of it.

You already know

  • Buttons, when B5.Click, set B5.Text to
  • Labels for status and score
  • Variables: turn ("X" or "O"), moves, two score counters
  • if / else to swap turns and to decide win / draw / keep going
  • Procedures with an input (from Rock Paper Scissors) and reset

New to you

  • TableArrangement (Layout) with 3 columns and 3 rows — the grid the nine buttons sit in
  • A procedure that returns an answer: to three(a, b, c) result — the Procedures drawer has two kinds; this is the one with "result"
  • ≠ (not equal) in the Math compare dropdown, and " " the empty text block
  • set B1.Enabled to false to lock the board after a win

Must-haves (all five to pass)

  • M1Nine buttons in a 3×3 grid. Tapping an empty one writes the current player's letter; tapping a taken one does nothing.
  • M2Turns alternate X → O → X, and a Label always says whose turn it is.
  • M3A procedure three(a, b, c) returns true only when all three match and aren't blank. checkWin uses it for all eight lines (3 rows, 3 columns, 2 diagonals).
  • M4On a win: the Label names the winner, the board locks (no more taps change it), and that player's score goes up. On a full board with no winner: "Draw."
  • M5New Game clears all nine squares, unlocks them, and sets the turn back to X — through a reset procedure. Scores survive New Game.

Build order

  1. Designer: StatusLabel, TableArrangement (3×3), nine Buttons named B1–B9 inside it, ScoreLabel, NewGameButton.
  2. Variables: turn = "X", moves = 0, xWins = 0, oWins = 0.
  3. One button first: B5.Click → if B5.Text = "" then set B5.Text to turn, call afterMove. Test it. Then duplicate for the other eight.
  4. Procedure three(a,b,c) with result. Procedure checkWin with result: eight three calls joined by or.
  5. Procedure afterMove: moves + 1; if checkWin → winner, lock, score; else if moves = 9 → draw; else swap turn.
  6. reset + New Game button.

When it breaks

  • Three blanks count as a win: three is missing the a ≠ "" check.
  • You can overwrite a square: the if B.Text = "" guard is missing on that button.
  • Turn never switches: you set turn to "O" but never to "X" — it needs an if/else, not one set.
  • Draw shows even though someone won: the win check must come before the moves = 9 check.

Stretch goals

  • Color the winning three squares (set their BackgroundColor inside the win branch — you'll need to know which line won).
  • Replace nine Click handlers with one when any Button.Click block (Any component drawer at the bottom of the Blocks list).
  • A one-player mode: the phone picks a random empty square for O.

Five days

Each day has a gate. If you're behind the gate, that's what you do first the next day.

Day 1Pick + plan

Choose your game. Fill the plan sheet below. Components, WHEN/DO table, variables, procedure names.

Gate: plan signed by Mr. Babb
Day 2Designer + first event

Every component placed and named. ONE event handler working on the phone (the mole hops, the gift falls, a button does something).

Gate: something moves or reacts
Day 3Must-haves M1–M3

Core loop works. Score goes up. Procedure exists and is called.

Gate: M1–M3 checked
Day 4M4–M5 + bug log

Reset works. Edge cases handled. Break it on purpose, log three bugs. Stretch goals only after M5.

Gate: all five + 3 bugs logged
Day 5Demo + turn in

60-second demo to the class. Export the .aia. Submit the reflection on Classroom.

Gate: .aia + reflection submitted

Plan sheet

Fill this out, tap Copy my plan, paste it into the Classroom assignment "Day 1 — Game Plan." Then show it to Mr. Babb before you open App Inventor.

Name you'll give itTypeIts job
WHEN (the event)DO (what happens)
Copied. Paste it into the Day 1 assignment on Classroom.
This page does not save what you type. Copy your plan before you close the tab.

How it's graded — 100 points

PartWhat earns full pointsPts
Plan sheet (Day 1)Complete, specific, signed before building. Components named, 3+ WHEN/DO rows, variables and procedures listed, a real risk.15
Must-haves M1–M58 points each. Works on the phone during the demo, not just in your description. A must-have that "mostly works" is 4.40
Code qualityRepeated blocks live in a procedure. Variables and components have real names (score, not global1; Mole, not ImageSprite1). No empty sockets. No dead blocks floating in the workspace.15
Bug logThree bugs: what the app did, what you thought was wrong, what was actually wrong, how you fixed it. Quality of the diagnosis is the grade, not the count.10
Demo + reflection60-second demo: show it working, show one thing that broke. Reflection (3 questions on Classroom) uses specific details from your app.20
Stretch goals are not extra credit. They are what you do when you finish early, and they're how you get the "I built that" story for the demo. Every must-have first.

Turning it in (Day 5)

1
Export your project. In App Inventor: Projects → Export selected project (.aia) to my computer. The file is named YourGame.aia. Attach it to the Classroom assignment.
2
Two screenshots — one of the app running on the phone, one of your Blocks workspace zoomed out enough to see every handler.
3
Bug log + reflection — answer the three questions in the Classroom assignment. Specific details from your app, or it caps at half.
4
Demo. 60 seconds. Play it, show the score change, show one thing that used to break and now doesn't.