1. Open Day
1.1. guess_the_number_AB
from microbit import *
import random
def get_secret(min_num=1, max_num=9):
return random.randint(min_num, max_num)
def select_number(start_num, min_num=1, max_num=9):
counter = start_num
display.show(counter, delay=200)
# Wait until the logo is pressed to confirm
while pin_logo.is_touched() is False:
# A decreases, stops at 1
if button_a.is_pressed():
if counter > min_num:
counter -= 1
display.show(counter, delay=200)
sleep(200)
# B increases, stops at 9
if button_b.is_pressed():
if counter < max_num:
counter += 1
display.show(counter, delay=200)
sleep(200)
sleep(100)
return counter
def check_guess(secret_num, guess):
if guess == secret_num:
display.show(Image.YES)
sleep(400)
return True
elif guess > secret_num:
display.show(Image.ARROW_S)
sleep(400)
display.show(guess)
return False
else:
display.show(Image.ARROW_N)
sleep(400)
display.show(guess)
return False
secret_num = get_secret()
guess = 5
game_guesses = 0
guessed = False
display.scroll("1-9?")
while True:
guess = select_number(guess, min_num=1, max_num=9)
game_guesses += 1
guessed = check_guess(secret_num, guess)
if guessed:
display.scroll(str(game_guesses) + " GUESSES", delay=80)
# new game
secret_num = get_secret()
guess = 5
game_guesses = 0
guessed = False
1.2. random_pet
# pet store
from microbit import *
import random
# Built-in animals
animal_icons = {
"Cow": Image.COW,
"Duck": Image.DUCK,
"Giraffe": Image.GIRAFFE,
"Rabbit": Image.RABBIT,
"Snake": Image.SNAKE,
}
animals = list(animal_icons.keys())
pet_names = {
"Cow": ["Daisy", "MooMoo",],
"Duck": ["Quacker", "Daffy", "Waddles",],
"Giraffe": ["Stretch", "Lofty"],
"Rabbit": ["Hoppy", "Bunny", "Bugsy"],
"Snake": ["Slither", "Fang", "Slinky"],
}
current_animal = None
while True:
if button_a.was_pressed():
current_animal = random.choice(animals)
display.show(animal_icons[current_animal])
if button_b.was_pressed():
if current_animal:
name = random.choice(pet_names[current_animal])
display.scroll(name + " the " + current_animal)
else:
display.scroll("Pick animal first")
sleep(100)
1.3. maze
from microbit import *
# FINAL MAZES (converted to 0/1)
MAZES = [
# 7x7
[
"1111111",
"0000001",
"1011101",
"1000101",
"1110101",
"1000000",
"1111111"
],
# 9x9
[
"111111111",
"000000001",
"101111101",
"100001001",
"111101101",
"100001001",
"101101101",
"100000000",
"111111111"
],
# 11x11
[
"11111111111",
"00000000001",
"10111111001",
"10100001001",
"10101101001",
"10101001001",
"10101001101",
"10100000001",
"10111111001",
"10000000000",
"11111111111"
]
]
# Start openings (in wall)
START_OPENINGS = [(0,1), (0,1), (0,1)]
# Player starts inside the maze
STARTS = [(1,1), (1,1), (1,1)]
# Exit openings (in wall)
EXIT_OPENINGS = [(6,5), (8,7), (9,9)]
# Exit tiles inside the maze
EXITS = [(5,5), (7,7), (8,9)]
def draw_window(maze, px, py):
img = Image(5,5)
for dy in range(5):
for dx in range(5):
mx = px + dx - 2
my = py + dy - 2
if 0 <= mx < len(maze[0]) and 0 <= my < len(maze):
if maze[my][mx] == "1":
img.set_pixel(dx, dy, 5)
img.set_pixel(2,2,9)
return img
def play_maze(maze, start, start_opening, exit_tile):
x, y = start
sx, sy = start_opening
ex, ey = exit_tile
# Close the start opening behind the player
maze[sy] = maze[sy][:sx] + "1" + maze[sy][sx+1:]
speed = 120 # starting speed (ms)
while True:
display.show(draw_window(maze, x, y))
dx = dy = 0
# SPEED CONTROL
if button_a.was_pressed():
speed = min(300, speed + 20) # slow down
if button_b.was_pressed():
speed = max(40, speed - 20) # speed up
# MOVEMENT (tilt)
if accelerometer.get_x() < -200:
dx = -1
elif accelerometer.get_x() > 200:
dx = 1
elif accelerometer.get_y() < -200:
dy = -1
elif accelerometer.get_y() > 200:
dy = 1
# APPLY MOVEMENT
nx = x + dx
ny = y + dy
if maze[ny][nx] == "0":
x, y = nx, ny
# EXIT CHECK
if (x, y) == (ex, ey):
return
sleep(speed)
def main():
while True:
display.show(Image.HAPPY)
if button_a.was_pressed():
for i in range(len(MAZES)):
maze = MAZES[i].copy()
play_maze(maze, STARTS[i], START_OPENINGS[i], EXITS[i])
display.show(Image.YES)
sleep(1000)
display.scroll("WIN!")
sleep(100)
main()
1.4. space_invaders
from microbit import *
import random
MIN_COORD, MAX_COORD = 0, 4 # Range of valid coordinates for the display.
MAX_MISSILES = 5 # Number of missiles player can have on screen at once.
DIFFICULTY_INCREASE = 0.25 # Increase in difficulty between waves.
ALIEN_START_POSITIONS = [
# Each row is a unique start pattern, defined as tuples of x,y coordinates.
[(1, 0), (2, 0), (3, 0), (1, 1), (2, 1), (3, 1)],
[(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (2, 1)],
[(1, 0), (2, 0), (3, 0), (0, 1), (2, 1), (4, 1)],
[(1, 0), (2, 0), (3, 0), (1, 1), (3, 1), (2, 2)],
]
def wait_for_button():
""" Wait for either button to be pressed. """
while not (button_a.was_pressed() or button_b.was_pressed()):
sleep(1)
def move(sprite, x, y):
""" Move the given sprite by the given x & y amounts. """
return sprite[0] + x, sprite[1] + y
def in_bounds(pos):
""" Return True if the position is within the valid screen coordinates. """
if pos[0] < MIN_COORD or pos[0] > MAX_COORD:
return False
if pos[1] < MIN_COORD or pos[1] > MAX_COORD:
return False
return True
class Game:
""" Game class holds the current game state. """
def game_reset(self):
# Initial values
self.x = 2 # Player x coordinate start (middle).
self.xf = 2.0 # x coordinate float, allows us to use tilt for move speed.
self.missiles = [] # Active missiles on screen.
self.aliens = [] # Active aliens on screen.
self.alien_velocity_x = 1 # Horizontal speed of aliens.
self.bombs = 3 # Number of bombs the player has.
self.active_bomb = 0 # Countdown timer for the current active bomb.
self.score = 0 # Player score.
self.tick = 0 # Game loop tick.
self.level = 0 # Current game level.
self.difficulty = 20 # Is in reverse, decrement to increase.
def handle_input(self):
self.tick += 1
acc_x = accelerometer.get_x()
# Use the accelerometer / 512 so the player can move x at speed by tilting more.
if acc_x < 0:
self.xf += acc_x / 512
if acc_x > 0:
self.xf += acc_x / 512
# Constrain to the screen dimensions.
if self.xf > MAX_COORD:
self.xf = MAX_COORD
if self.xf < MIN_COORD:
self.xf = MIN_COORD
self.x = int(self.xf)
if button_a.was_pressed():
# Add missile, at players current x position.
self.missiles.append((self.x, 4))
if button_b.was_pressed() and self.bombs:
# Fire bomb. Flash + remove half the aliens.
# randint(0,1) will be 50% 1, 50% 0 ..if 0 (False) alien will be skipped.
self.aliens = [alien for alien in self.aliens if random.randint(0, 1)]
self.active_bomb = 3 # Reduces 1 per tick. Screen at 3 * bright.
self.bombs -= 1
def add_aliens(self):
# We need to copy, or we'll me modifying the original lists.
alien_position = self.level % len(ALIEN_START_POSITIONS)
self.aliens = ALIEN_START_POSITIONS[alien_position].copy()
self.tick = 0
def advance_aliens(self):
""" If aliens have reached the screen edge, advance them all downwards. """
for alien in self.aliens:
if (self.alien_velocity_x == -1 and alien[0] == MIN_COORD) or (
self.alien_velocity_x == +1 and alien[0] == MAX_COORD
):
# If any aliens are at the far edge, increment y, and reverse.
self.alien_velocity_x = -self.alien_velocity_x
self.aliens = [move(alien, 0, 1) for alien in self.aliens]
# This can happen if detached alien slips past bottom.
self.aliens = [alien for alien in self.aliens if in_bounds(alien)]
return True # No other move this time.
def aliens_can_move(self):
if self.tick > self.difficulty:
self.tick = 0
return True
def move_aliens(self):
# Move aliens horizontally.
self.aliens = [move(alien, self.alien_velocity_x, 0) for alien in self.aliens]
def move_missiles(self):
# Advance positions of missiles (upwards)
self.missiles = [move(missile, 0, -1) for missile in self.missiles]
self.missiles = [missile for missile in self.missiles if in_bounds(missile)]
def check_collisions(self):
for missile in self.missiles[:]: # Iterate a copy.
if missile in self.aliens:
# Since we store by coordinates, we can remove using the missile coords.
self.aliens.remove(missile)
self.missiles.remove(missile)
self.score += 1
if not self.aliens:
# Wave complete? Increase difficulty (decrement) and add new aliens.
self.difficulty -= DIFFICULTY_INCREASE
self.level += 1
self.bombs += 1
self.add_aliens()
def draw(self):
display.clear()
if self.active_bomb:
# Bomb is drawn as an overlay of gradually decaying light.
for dx in range(MAX_COORD + 1):
for dy in range(MAX_COORD + 1):
display.set_pixel(dx, dy, self.active_bomb * 3)
# Decrement so next draw is fainter.
self.active_bomb -= 1
# Draw all the aliens.
for pos in self.aliens:
display.set_pixel(pos[0], pos[1], 9)
# Draw all the current player missiles.
for pos in self.missiles:
display.set_pixel(pos[0], pos[1], 5)
# Draw the players spaceship.
display.set_pixel(self.x, 4, 9)
def game_over(self):
return (self.x, 4) in self.aliens
game = Game() # Create our game object.
while True:
display.show(Image.TARGET)
wait_for_button()
game.game_reset() # Reset the game state.
game.add_aliens()
# Main loop
while not game.game_over():
game.handle_input()
if game.aliens_can_move():
if not game.advance_aliens():
game.move_aliens()
game.move_missiles()
game.draw()
game.check_collisions()
sleep(100)
display.show(Image.ANGRY)
sleep(1000)
display.scroll(game.score)
1.5. vertical_scroller
from microbit import *
import random
def draw(track, t, x, y):
img = Image(track)
img.set_pixel(x, y, t * 4 + 1)
return img
def play_game():
# lines of track
track_bits = ["50005:", "53005:", "50305:", "50035:"]
# starting track
track = "50005:50005:50005:50005:50005:"
# co-ordinates of player character
x = 2
y = 4
# time variable for blinking
tick = 0
score = 0
# track pace
sleep_delay = 150
last = 0
alive = True
while alive == True:
tt = draw(track, tick, x, y)
if button_a.was_pressed() and x != 1:
x = x - 1
elif button_b.was_pressed() and x != 3:
x = x + 1
# update ticks
tick += 1
# show track
display.show(tt)
# every third tick
if tick == 3:
# update score
score += 1
# check for collision
if tt.get_pixel(x, y - 1) != 0:
alive = False
# reset ticks
tick = 0
# delete bottom row of track
track = track[:-6]
# update track
if last == 0:
last = random.randint(0, len(track_bits) - 1)
else:
last = 0
track = track_bits[last] + track
# redraw screen
tt = draw(track, tick, x, y)
display.show(tt)
sleep(sleep_delay)
display.scroll(score, delay=80)
def main():
while True:
if button_a.was_pressed():
play_game()
sleep(3000)
sleep(50)
main()
1.6. radio_hotcold
from microbit import *
import radio
radio.config(group=7)
radio.config(power=2)
radio.on()
radio_on = False # Start with radio OFF
while True:
# A turns radio ON
if button_a.was_pressed():
radio_on = True
display.show(Image.HEART)
sleep(300)
display.show(Image.HEART_SMALL)
sleep(300)
# B turns radio OFF
if button_b.was_pressed():
radio_on = False
display.clear()
# Only send if radio is ON
if radio_on:
radio.send("7")
# Pulse heart to show "ON" status
display.show(Image.HEART)
sleep(300)
display.show(Image.HEART_SMALL)
sleep(300)
else:
sleep(1000)
from microbit import *
import radio
# Radio setup
radio.config(group=7)
radio.on()
# Smoothing + timeout
smooth_rssi = -95
last_packet_time = running_time()
def display_level(level):
display.clear()
# Clamp level between 0 and 5
if level < 0:
level = 0
if level > 5:
level = 5
# Level 0 = no bars
if level == 0:
return
# Light rows from bottom upward
for i in range(level):
row = 4 - i
for x in range(5):
display.set_pixel(x, row, 9)
while True:
packet = radio.receive_full()
now = running_time()
if packet:
msg, rssi, timestamp = packet
last_packet_time = now
# Smooth RSSI
smooth_rssi = (smooth_rssi * 0.7) + (rssi * 0.3)
# Map RSSI so:
# -75 = 0 bars (≈1 meter)
# -55 = 5 bars (≈2 cm)
level = scale(int(smooth_rssi), from_=(-75, -55), to=(0, 5))
# Hard cutoff for weak signals
if smooth_rssi < -75:
level = 0
display_level(level)
else:
# No packets for 0.5 seconds → drop to zero
if now - last_packet_time > 500:
display_level(0)
sleep(100)
1.7. radio_draw
from microbit import *
import radio
# Choose own group in pairs 0-255
radio.config(group=6)
# Turn on the radio
radio.on()
x = 2
y = 2
tick = -1
grid = [
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0]
]
def Toggle(tx, ty):
# bitwise or swaps 0 for 1 and 1 for 0
grid[tx][ty] ^= 1
def Draw(t):
img = Image('00000:'*5)
for cy in range(0,5):
for cx in range(0,5):
img.set_pixel(cx, cy, grid[cx][cy]*5)
img.set_pixel(x, y, (t % 2)*9)
return img
def ImageString():
s = ""
for cy in range(0,5):
for cx in range(0,5):
s += str(grid[cx][cy]*9)
s += ":"
return s
while True:
tick += 1
if tick == 2:
tick = 0
# check for movement
dx = accelerometer.get_x()
dy = accelerometer.get_y()
if dx > 300:
x += 1
sleep(200)
if dx < -300:
x -= 1
sleep(200)
if dy > 300:
y += 1
sleep(200)
if dy < -300:
y -= 1
sleep(200)
# keep on grid
x = max(0, min(x, 4))
y = max(0, min(y, 4))
# check for button press
if button_a.was_pressed():
Toggle(x, y)
sleep(200)
# update screen
i = Draw(tick)
display.show(i)
if button_b.was_pressed():
radio.send(ImageString())
sleep(50)
from microbit import *
import radio
# Choose own group in pairs 0-255
radio.config(group=6)
# Turn on the radio
radio.on()
while True:
incoming_message = radio.receive()
if incoming_message:
# print(incoming_message)
i = Image(incoming_message)
display.show(i)