Micro:bit Challenges

  • Author: Dr. Jim Marquardson (jimarqua@nmu.edu)
  • Updated 2024-06-19

This exercise assumes that you have had some introduction to Python programming using the Micro:bit platform. Several sample projects are included. Choose projects that you find interesting and challenging. The goal is to have you explore the platform in a semi-structured way.

Learning Objectives

In this exercise, you will learn to:

  • add missing code to complete programs,
  • develop new functions, and
  • investigate the documentation.

Editing Code

  • Go to https://python.microbit.org/ to edit the code.
  • Remove the sample code.
  • Write your Python code.
  • Preview your code using the simulator.
  • Download the code to the micro:bit device to run your program on the micro:bit hardware.

micro:bit code editing

Project Index

Data Type Intro

The following code shows a complete, working program. Follow the instructions to change the values of different variables. You do not need to modify any of the code that displays the variables. This sample code can help you remember the syntax for creating and working with variables in different challenges.

from microbit import *

# Integer variables hold whole numbers (1, 2, 3, etc.).
# Integer variables do not need quotation marks around the values.
# Change the age variable below to your age.
age = 50
# The print() function shows the contents in the
# serial output of the simulator.
print("Age: " + str(age))
# The display.show() function displays the value
# in the LED lights.
display.show(age)
display.clear()
sleep(500)

# Decimal numbers are known as "floats."
# Change the the ideal_temperature variable
# below to you ideal weather temperature.
ideal_temperature = 55.3
# The value will be displayed.
print("Ideal temperature: " + str(ideal_temperature))
display.show(ideal_temperature)
display.clear()
sleep(500)

# String variables store text.
# Use quotation marks around the text
# when setting the value of string variables.
# Change the birth_month variable below to 
# the month you were born.
birth_month="December"
# The value will be displayed.
print("Birth month: " + birth_month)
display.scroll(birth_month)
display.clear()
sleep(500)

# List variables store multiple values.
# The values are separated by commas inside
# of square brackets.
# Change the numbers in the list variable lucky
# to your 3 luckiest numbers.
lucky = [3, 42, 111]
# You can access elements in the list using their
# indices, starting with 0.
print("Lucky #1: " + str(lucky[0]))
display.show(lucky[0])
print("Lucky #2: " + str(lucky[1]))
display.show(lucky[1])
print("Lucky #3: " + str(lucky[2]))
display.show(lucky[2])
display.clear()
sleep(500)

# Dictionaries store values in key/value pairs.
# The key is always a string.
# The value can be any Python variable type.
# The 'about' variable blow has 3 keys: 
#  1) 'city': a string
#  2) 'heigh_cm': an integer
#  3) 'foods': a list of strings
# Change the values to the city where you are
# from, your height in centimeters, and three
# of your favorite foods.
about = {
    'city': "New York",
    'height_cm': 140,
    'foods': ["burgers", "fries", "tortilla chips"]
}
# Access dictionary elements using square brackets
# and the the key, with quotation marks around the key.
print("City: " + about['city'])
display.show(about['city'])
print("Height: " + str(about['height_cm']))
display.show(about['height_cm'])
# Because the value of about['foods'] is a list,
# the items in the list must be access with their indices.
print("Food 1: " + str(about['foods'][0]))
display.show(about['foods'][0])
print("Food 2: " + str(about['foods'][1]))
display.show(about['foods'][1])
print("Food 3: " + str(about['foods'][2]))
display.show(about['foods'][2])
display.clear()

Go back to the project index.

Functions Intro

Functions help organize code. Instead of repeating code several times, it can be helpful to put blocks of code in functions. Read the code below, and modify the function calls at the bottom of the code to test different function inputs.

from microbit import *

# Begin a line with 'def' to define a function.
# The fuction's name follows 'def'.
# Function inputs can be put in parentheses.
# After the paretheses, add a colon.
# The rest of the lines in the function need
# to be indented.
def show_big(text):
    print("UPPER CASE: " + text.upper())
    display.scroll(text.upper())
    sleep(100)

def show_small(text):
    print("lower case: " + text.lower())
    display.scroll(text.lower())
    sleep(100)

# Not all functions need inputs.
# The show_error() function below adoes not
# accept any inputs.
def show_error():
    print("Error")
    display.scroll("Error")
    sleep(100)

# Call functions by providing the function name
# and providing values for the function's inputs.
# Change the function inputs below and run the code.
show_big("hElLo")
show_small("hElLo")
show_error()
show_big("world")
show_small("WORLD")

Go back to the project index.

Loops Intro

Loops let you run code multiple times. Loops are helpful when working with lists or ranges of numbers.

from microbit import *

# The following `for` loop goes from
# 0 to 4 and displays the number.
# The variable `i` takes the value
# of the current integer.
# Change the paramters of the range() function
# to edit the start and end of the `for` loop.
for i in range(0, 5):
    display.show(i)
    sleep(500)

# This `for` loop goes through a list of
# values. The variable `n` takes the value
# of each element in the list as Python
# goes through the loop.
# Add or remove elements from the list.
# Be sure the list elements are separated
# by commas.
for n in ["a", "b", "c"]:
    display.show(n)
    sleep(500)

# A while loop continues until the condition
# is false.
# Change the values for `end` and `i` to see
# how the loop changes.
end = 9
i = 5
while i <= end:
    display.show(i)
    i = i + 1
    sleep(500)

# Creating a `while True` loop will continue forver.
# Notice that the code will never reach the 
# `display.clear() code below the loop.
# Add the `break` keyword after the sleep()
# function to force the while loop to exit,
# then re-run the code.
while True:
    display.show(".X")
    sleep(500)

display.clear()

Go back to the project index.

Hello World 2

This simple project will display "Hello name" as many times as you call the function.

from microbit import *

def greet_name(name):
    display.scroll("Hello " + name)

# Write the code here to call the greet_name()
# function two separate times.

Go back to the project index.

Simple Calculator

The Python code below performs basic math operations and shows the results. Run the code to make sure it works. Then, modify the code to find the answers to these questions:

  • What happens if the result is a number with more than 1 digit?
  • What happens if a number is not evenly divisible (e.g., 7/2)?
  • What happens if you raise a number to a very large power (e.g., 2**800)?
from microbit import *

added = 5 + 2
display.scroll(added)

divided = 9 / 3
display.scroll(divided)

multiplied = 2 * 3
display.scroll(multiplied)

squared = 3**2
display.scroll(squared)

Go back to the project index.

Indentation Matters

Python code must be indented properly to work. Fix the code by indenting the lines properly. The code creates a list of lists, has a function to print letters (skipping the letter '2'), and creates an infinite loop to cycle through the data.

from microbit import *

data = [['a', 'b', 'c'],
['1', '2', '3']]

# Show letters, but skips the text '2'
def show_letter_but_not_two(letter):
if letter=='2':
pass
else:
display.show(letter)

# Indent the code properly.
# The program should pause the same
# amount for each letter displayed.
while True:
for i in data:
for n in i:
show_letter_but_not_two(n)
sleep(200)

Go back to the project index.

Data Types

This exercise asks you to create variables using different data types. After you create the variables, you will show the variable values. Replace the question marks with the appropriate code.

from microbit import *

################################
# Create the variables
################################

# Make name a string variable with your first name
name = ?

# Make age an integer variable with your age.
age = ?

# Make exact_age decimal number with your age .
# If it has been 6 months since your birthday,
# your exact age would be 20.5
exact_age = ?

# Make the friends a list variable with the
# names of 2 or more friends
friends = ?

# Make the favorites variable a dictionary
# with 3 key-value pairs:
#   1) "team" containing your favorite team
#   2) "color" containintg your favorite color
#   3) "food" containing your favorite food
favorites = ?

################################
# Show the variables
################################

# Show the value of the name variable
display.scroll(?)

# Show the value of the age variable
display.scroll(?)

# Show the value of the exact_age variable
display.scroll(?)

# Show the first element of the friend list
display.scroll(?)

# Show the second element of the friend list
display.scroll(?)

# Show the value of team from the favorites dictionary
display.scroll(?)

# Show the value of color from the favorites dictionary
display.scroll(?)

# Show the value of food from the favorites dictionary
display.scroll(?)

Go back to the project index.

Countdown

from microbit import *

countdown = 9
# Create a while loop that goes down to zero
while ????: # Complete the while loop condition so that it continues until countdown is 0
    display.scroll(countdown)
    countdown = ???? # Edit the countdown variable to subtract 1

display.scroll("Go!")

Go back to the project index.

Greet Loop

This challenge requires you to create a list of names. Then, you will loop through those names to call the greet_name function.

from microbit import *

def greet_name(name):
    display.scroll("Hi " + name)
    print("Hello " + name)

# Create a list with 3 names
names = ???? # Finish this line of code

# Loop through each name and call the greet_name() function
for ???? # Finish this line of code
    greet_name(name)

Go back to the project index.

Out of Bounds

The following code creates a list named items. The code will print the current index of the list. The A button goes to the next item in the index. The B button goes to the previous item. But the code will crash if the index goes outside of the items list. Fix the code. There are several ways to fix this program. Two options are below.

  • Option 1: Prevent the index from going below zero or higher than two. Essentially, the A button is rendered useless if index is zero. The B button becomes useless if index is two.
  • Option 2: If index goes lower than zero, set it to two. Set index to zero if the index is changed to something greater than two. Essentially, the A and B buttons will loop forever in either direction.
from microbit import *

items = ['a', 'b', 'c']
index = 0

while True:
    if button_a.was_pressed():
        index = index - 1
    if button_b.was_pressed():
        index = index + 1
    # The following line can crash the program
    display.show(items[index])

Go back to the project index.

Button Events

This challenge requires you to run functions when buttons are pressed. The code already works when pressing the A and B buttons separately. Your task is to add the code to handle when both A and B are pressed at the same time.

from microbit import *

while True:
    # Add code at the beginning to check if A and B are both pressed.
    # If so, show the North arrow.
    if button_a.is_pressed():
        display.show(Image.ARROW_W)
    elif button_b.is_pressed():
        display.show(Image.ARROW_E)
    sleep(100)

Go back to the project index.

Guessing Game Mod

The following code works okay. It's a simple guessing game. The starting guess is 5. When the A button is pressed, the program reduces the guess by 1 and checks if it matches the secret number. When the B button is pressed, the guess is increased by one and checked to see if it matches the secret. Make the game better. Here are a few suggestions:

  • Reduce duplicate code. For example, the logic to check whether the guess is correct could be extracted into a separate function.
  • Instead of checking the guess each time, only check guesses when A and B are pressed simultaneously.
  • Set the minimum and maximum guess. For example, the lowest guess could be 0, and the maximum guess could be 20. Enforce these minimums and maximums in the code.
  • Randomly generate the secret integer.
from microbit import *

guess = 5
secret = 7
print(secret)
display.show(guess)

while True:
    if button_a.was_pressed():
        guess = guess - 1
        display.show(guess)
        sleep(500)
        if guess == secret:
            display.scroll("Yes!")
        else:
            display.scroll("No")
            display.show(guess)
    elif button_b.was_pressed():
        guess = guess + 1
        display.show(guess)
        sleep(500)
        if guess == secret:
            display.scroll("Yes!")
        else:
            display.scroll("No")
            display.show(guess)
    sleep(100)

Go back to the project index.

Fix the Mine Game

The code below implements a simple mine-finding game. The A and B buttons move the current position. Pressing A and B together checks for a mine. The movement logic needs to be improved. If the position gets to the end of a line and B is pressed, the position should move to the following row in the first column. Likewise, if the current position is in the first column and A is pressed, the position should move up a row to the last column. Basically, the current position should never leave the grid.

  • The grid is 5 by 5. The top-left coordinate is 0, 0. The bottom-right coordinate is 4, 4.
  • If the current position is 0, 0 and the A button is pressed, the current position should not change.
  • If the current position is 4, 4 and the B button is pressed, the current position should not change.
  • If the current position is 0, 4, and the A button is pressed, the position should change to 4, 3.
from microbit import *

# Game Start Conditions
mine_x = 3
mine_y = 2
current_x = 2
current_y = 2
display.set_pixel(current_x, current_y, 9)

while True:
    if button_a.is_pressed() and button_b.is_pressed():
        if current_x == mine_x and current_y == mine_y:
            display.show(Image.HEART)
    elif button_b.was_pressed():
        display.set_pixel(current_x, current_y, 0)
        current_x = current_x + 1
        # Add logic here to move rows
        display.set_pixel(current_x, current_y, 9)
    elif button_a.was_pressed():
        display.set_pixel(current_x, current_y, 0)
        current_x = current_x - 1
        # Add logic here to move rows
        display.set_pixel(current_x, current_y, 9)
    sleep(200)

Go back to the project index.

Artist Struggle

In this program, the A and B buttons move the current position left and right. When A and B are pressed together, the current pixel is toggled (i.e., if it's off, it will be turned on and vice versa). The program works, but it can be a bit frustrating to use. Sometimes, the position does not change the amount you think it should and so the wrong pixel is toggled. Can you improve the program? Here are some ideas:

  • Try changing the sleep() function.
  • Should the current pixel be changed to a different brightness?
  • Is there a different way to access the button codes?

The goal of this exercise is to make the program more friendly for our artist friends.

from microbit import *

position = [0,0]
pixels = [[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_current_pixel():
    # Toggle the pixel of the current position
    if pixels[position[0]][position[1]] == 0:
        pixels[position[0]][position[1]] = 9
    else:
        pixels[position[0]][position[1]] = 0
    display.clear()
    for x in range(0, len(pixels)):
        for y in range(0, len(pixels)):
            display.set_pixel(x, y, pixels[x][y])

while True:
    if button_a.is_pressed() and button_b.is_pressed():
        print("A and B pressed")
        print(position)
        toggle_current_pixel()
    elif button_b.was_pressed():
        print("B pressed")
        position[0] = position[0] + 1
        if position[0] > 4 and position[1] == 4:
            position[0] = 4
        elif position[0] > 4:
            position[0] = 0;
            position[1] = position[1] + 1
        elif position[0] < 0:
            position[0] = 0
            position[1] = position[1] - 1
        print(position)
    elif button_a.was_pressed():
        print("Button A pressed")
        position[0] = position[0] - 1
        if position[0] < 0 and position[1]==0:
            position[0] = 0
        elif position[0] < 0:
            position[0] = 4;
            position[1] = position[1] - 1
        print(position)
    sleep(200)

Go back to the project index.

Atbash Cipher

The Atbash cipher is a monoalphabetic substitution cipher. See Wikipedia for an overview. You can experiment with the Atbash cipher using the Cyber Chef. A basic outline of a sample program is included, but you must develop the logic.

from microbit import *

def atbash_encrypt(input):
    ciphertext = ''
    # Complete this function
    return ciphertext

cleartext = "hello"
ciphertext = atbash_encrypt(cleartext)
display.scroll(ciphertext)
# 'hello' should produce 'svool'

Go back to the project index.

Vigenere Cipher

The Vigenere cipher is a polyalphabetic substitution cipher. It is similar to the Caesar cipher except that the letters are rotated different amounts based on a multi-character key. Read about the Vigenere Cipher on Wikipedia. Experiment with the Vigenere cipher using the Cyber Chef. In the Cyber Chef, try making the key 'aaa' or 'bbb' and look at the results on the output.

from microbit import *

def vigenere_encrypt(input, key):
    ciphertext = ''
    # Complete this function
    return ciphertext

cleartext = "hello"
key = "abc"
ciphertext = vigenere_encrypt(cleartext, key)
display.scroll(ciphertext)
# 'hello' with the key 'abc' should produce 'hfnlp'

Go back to the project index.

Free Play

Develop your own idea! Push yourself to see what you can do with the micro:bit.

Go back to the project index.

Reflection

  • What were the most challenging parts of writing the code?
  • Think of projects that you could do if the micro:bit had GPS, a microphone, or other modules. What programs would you write?