Turn the reaction timer into a two-player race over radio. First to press after the heart wins.
Quiz shows use buzzers that lock out everyone else the moment one player presses. That is a few radio messages and a true/false variable.
Two players, two micro:bits. Either player presses B to start a round. After a random wait, the heart appears on both; the first to press A wins the round. Both micro:bits run the same program, and they agree on a code: 0 means get ready, 1 means go, 2 means I pressed first.
In the simulator, the second micro:bit appears because the program uses radio. Press B on one, then race yourself by pressing A on either.
Make your prediction first. Help opens once you've locked it in.

let racing = false
radio.setGroup(7)
input.onButtonPressed(Button.B, function () {
radio.sendNumber(0)
racing = false
basic.clearScreen()
basic.pause(randint(1000, 4000))
radio.sendNumber(1)
basic.showIcon(IconNames.Heart)
racing = true
})
radio.onReceivedNumber(function (receivedNumber) {
if (receivedNumber == 0) {
racing = false
basic.clearScreen()
} else if (receivedNumber == 1) {
basic.showIcon(IconNames.Heart)
racing = true
}
})
Press B on either micro:bit and watch both.

let racing = false
radio.setGroup(7)
input.onButtonPressed(Button.B, function () {
radio.sendNumber(0)
racing = false
basic.clearScreen()
basic.pause(randint(1000, 4000))
radio.sendNumber(1)
basic.showIcon(IconNames.Heart)
racing = true
})
radio.onReceivedNumber(function (receivedNumber) {
if (receivedNumber == 0) {
racing = false
basic.clearScreen()
} else if (receivedNumber == 1) {
basic.showIcon(IconNames.Heart)
racing = true
}
})

let racing = false
radio.setGroup(7)
input.onButtonPressed(Button.B, function () {
radio.sendNumber(0)
racing = false
basic.clearScreen()
basic.pause(randint(1000, 4000))
radio.sendNumber(1)
basic.showIcon(IconNames.Heart)
racing = true
})
radio.onReceivedNumber(function (receivedNumber) {
if (receivedNumber == 0) {
racing = false
basic.clearScreen()
} else if (receivedNumber == 1) {
basic.showIcon(IconNames.Heart)
racing = true
}
})
Match each message with its meaning.
Look for blocks that appear twice.
def on_received_number(receivedNumber):
global racing
if receivedNumber == 0:
racing = False
basic.clear_screen()
elif receivedNumber == 1:
basic.show_icon(IconNames.HEART)
racing = True
radio.on_received_number(on_received_number)
elif is Python's short way to write else if.
Match each message with what it means in the duel.
The receiving part in Python. Match each line with what it does.
Make a function go that shows the heart and sets racing to true. Call it in both places, so there is one copy to change.
Make a Function called go, and drag show heart and set racing to true into it.
Put call go in both places where those blocks were.
Make a function go for the heart and racing, and call it from both places.
This ticks by itself when your blocks do what is asked.
In A: if racing, set racing to false, send 2 and show a happy face.
In on radio received, add else if receivedNumber = 2: if racing, set racing to false and show a sad face.
The first press after the heart sends 2 and wins; the other player sees they lost.
This ticks by itself when your blocks do what is asked.
Make it a match: the first player to win three rounds wins.
A variable wins goes up by 1 each time you win a round. A+B shows it.
When wins reaches 3, send 3 and show a trophy (a picture). When 3 arrives, the other player shows game over.
Count wins, and the first to three wins the match: send 3, and the other shows game over.
This ticks by itself when your blocks do what is asked.
Play a match against a partner. Agree a group number of your own before you start.

let racing = false
radio.setGroup(7)
input.onButtonPressed(Button.B, function () {
radio.sendNumber(0)
racing = false
basic.clearScreen()
basic.pause(randint(1000, 4000))
radio.sendNumber(1)
basic.showIcon(IconNames.Heart)
racing = true
})
radio.onReceivedNumber(function (receivedNumber) {
if (receivedNumber == 0) {
racing = false
basic.clearScreen()
} else if (receivedNumber == 1) {
basic.showIcon(IconNames.Heart)
racing = true
}
})
Students turn the reaction game into a two-player race over radio, using a shared message code, a function to remove copied blocks, a true/false variable and a score. About 60 minutes.
Open the teacher guide: answers, solutions, slides and a worksheet.
Both micro:bits run the same program. The players agree a code: 0 = get ready, 1 = go, 2 = I pressed first (and 3 = I won the match, in Milestone 3). Whoever presses B sends 0, waits, sends 1 and shows its own heart; the other shows its heart when 1 arrives. racing is true only while a round is on, so only the first press counts, and a late press after receiving 2 does nothing. Milestone 1 is a refactor: the starter shows the heart and sets racing in two places (a design fault: copies must be kept the same by hand), and students fold them into one function. In the simulator, two micro:bits appear; one student can play both sides to test.
Keeping two micro:bits in step with a code of messages. Ask them to trace one round on paper: who sends what, and who checks it.
Stretch: Add an early-press penalty: pressing A before the heart sends 4, and the other player wins the round.
Support: Run Milestone 3 in pairs: one student builds the winner side (counting and sending 3), the other the loser side (receiving 3).
Two optional lessons go further: Fake-outs and levels (one player, harder rules) and Tournament (a scoreboard list and a round function). Class ideas: a class knockout tournament; a quiz buzzer for real class quizzes.