An optional, harder extension of the Radio duel. Students keep a two-place scoreboard list, move a round into a function so rounds carry on, and end the tournament at three wins.
Load these into Waypoints Prepare: choose Load URL and paste the copied address, or download the file and import it. In Prepare, the worksheet's Teacher edition shows the answers; the student copy hides them.
Predict, Run, Investigate 10 min · Milestone 1 10 min · Milestone 2 15 min · Milestone 3 20 min · Class tournament 5 min
This lesson is optional: it is for students who finished the Radio duel and want a harder challenge. It needs nothing new. The scoreboard is a list of two numbers: place 0 is this micro:bit's player, place 1 is the other player. Because both micro:bits run the same program, each one sees the match from its own side (2 - 1 on one is 1 - 2 on the other). Adding a point uses set value at 0 of scores to (get value at 0 of scores + 1). Milestone 2 moves the round into a function startRound, so the winner's micro:bit can start the next round by itself. Milestone 3 adds message 3 (champion) and a reset.
Each micro:bit keeps itself at place 0, so the two scoreboards are mirrored. Ask which place a win and a loss each add to.
| What you will see | A question to ask | The fix |
|---|---|---|
| Both scoreboards count the same player's wins. | Which place does a loss add to? | A win adds at place 0; a loss (2 arrives) adds at place 1. |
| Rounds stop after the first one. | Where is startRound called after a win? | Call startRound at the end of the winning branch in A. |
| The scores do not reset after a champion. | Do both sides reset? | Set scores to [0, 0] on the champion's side and when 3 arrives. |
One possible solution for each task. Other correct programs are fine.

let scores = [0, 0]
let racing = false
radio.setGroup(7)
function go () {
basic.showIcon(IconNames.Heart)
racing = true
}
function showScores () {
basic.showNumber(scores[0])
basic.showString("-")
basic.showNumber(scores[1])
}
input.onButtonPressed(Button.B, function () {
radio.sendNumber(0)
racing = false
basic.clearScreen()
basic.pause(randint(1000, 4000))
radio.sendNumber(1)
go()
})
input.onButtonPressed(Button.A, function () {
if (racing) {
racing = false
radio.sendNumber(2)
scores[0] = scores[0] + 1
basic.showIcon(IconNames.Happy)
}
})
input.onButtonPressed(Button.AB, function () {
showScores()
})
radio.onReceivedNumber(function (receivedNumber) {
if (receivedNumber == 0) {
racing = false
basic.clearScreen()
} else if (receivedNumber == 1) {
go()
} else if (receivedNumber == 2) {
if (racing) {
racing = false
scores[1] = scores[1] + 1
basic.showIcon(IconNames.Sad)
}
}
})

let scores = [0, 0]
let racing = false
radio.setGroup(7)
function go () {
basic.showIcon(IconNames.Heart)
racing = true
}
function showScores () {
basic.showNumber(scores[0])
basic.showString("-")
basic.showNumber(scores[1])
}
function startRound () {
radio.sendNumber(0)
racing = false
basic.clearScreen()
basic.pause(randint(1000, 4000))
radio.sendNumber(1)
go()
}
input.onButtonPressed(Button.B, function () {
startRound()
})
input.onButtonPressed(Button.A, function () {
if (racing) {
racing = false
radio.sendNumber(2)
scores[0] = scores[0] + 1
basic.showIcon(IconNames.Happy)
basic.pause(1000)
showScores()
startRound()
}
})
input.onButtonPressed(Button.AB, function () {
showScores()
})
radio.onReceivedNumber(function (receivedNumber) {
if (receivedNumber == 0) {
racing = false
basic.clearScreen()
} else if (receivedNumber == 1) {
go()
} else if (receivedNumber == 2) {
if (racing) {
racing = false
scores[1] = scores[1] + 1
basic.showIcon(IconNames.Sad)
basic.pause(1000)
showScores()
}
}
})

let scores = [0, 0]
let racing = false
radio.setGroup(7)
function go () {
basic.showIcon(IconNames.Heart)
racing = true
}
function showScores () {
basic.showNumber(scores[0])
basic.showString("-")
basic.showNumber(scores[1])
}
function startRound () {
radio.sendNumber(0)
racing = false
basic.clearScreen()
basic.pause(randint(1000, 4000))
radio.sendNumber(1)
go()
}
function newTournament () {
scores = [0, 0]
}
input.onButtonPressed(Button.B, function () {
startRound()
})
input.onButtonPressed(Button.A, function () {
if (racing) {
racing = false
radio.sendNumber(2)
scores[0] = scores[0] + 1
basic.showIcon(IconNames.Happy)
basic.pause(1000)
showScores()
if (scores[0] == 3) {
radio.sendNumber(3)
basic.showString("Champion")
newTournament()
} else {
startRound()
}
}
})
input.onButtonPressed(Button.AB, function () {
showScores()
})
radio.onReceivedNumber(function (receivedNumber) {
if (receivedNumber == 0) {
racing = false
basic.clearScreen()
} else if (receivedNumber == 1) {
go()
} else if (receivedNumber == 2) {
if (racing) {
racing = false
scores[1] = scores[1] + 1
basic.showIcon(IconNames.Sad)
basic.pause(1000)
showScores()
}
} else if (receivedNumber == 3) {
basic.showString("Game over")
newTournament()
}
})
Open task: any program that does what the step asks.
Stretch: Keep a list of round times as well, and show the fastest reaction of the tournament on the champion's micro:bit.
Support: Students who find this heavy can stop after Milestone 1: a working scoreboard is a good result.
You win a round. Why does your scoreboard add at place 0 while your partner's adds at place 1?
Both run the same program, and each keeps its own player at place 0. Your win is a loss on your partner's side.
This ends micro:bit Foundations. Robotics challenges comes next: each idea in the simulator, then on a real MOVE Motor. Class ideas: a class knockout bracket on the board; a rematch where students change one rule and explain why it is fairer.