Written by Mr Rebecchi
Building a Python dice game for the BBC Micro:Bit
What is the Micro:Bit?
The Microbit is a small-embedded system, which can run code. It uses a SoC (System on a Chip), which is a low-power chip which integrating all of the necessary components for a computer to run.
The Microbit has a number of features, which make it extremely useful for writing simple programs:
• LED Matrix – The LED (Light Emitting Diode) Matrix on the Micro:Bit is a 5x5 grid of pixels that can be turned on or off. This is used to display scrolling text, images or almost anything your imagination can think of.
• Input Buttons – There are two buttons, A and B, on the Micro:Bit which allows the programmer to wait for a button to be pressed before responding by doing something simple, such as displaying an image or text.
• Compass – The Micro:Bit features a compass, which can be used to test which direction the circuit board is facing. This could be incredibly useful if you were building an outdoor adventure game or simply if you want to display a compass on the LED Matrix.
• Accelerometer – Although this sounds like a complicated component, there is a clue in the name. The accelerometer is able to detect which direction the Micro:Bit is moved in. This allows you to test if the user has shaken the device, which direction the device is and other interesting things.
Now you know a little bit about the Micro:Bit, it’s time to get started coding. This tutorial is going to introduce you to all of the basic information you need to get started writing programs for the Microbit, using the Python editor.
Before we get down to writing any code however, let’s get over to the Micro:Bit website in order to open the Micro:Bit editor. Visit http://microbit.org and click on the ‘Let’s Code’ option. On the following screen you are given the options for the different ways to write code for the Microbit. Some of these are visual and work very similar to Scratch, whilst others are textual and work like Python. Select the Python option, as that is what we will be using.
You should now see the following screen:
Before we learn how to upload this onto our Microbit however, let’s break down the code to see if we can work out what is going on.
The first line:
from microbit import *
is very simple. This line of code searches for the microbit library, and from this library we are importing *. The * here simply means everything, so with this line of code we import all of the microbit libraries we need to use in Python.
The next line of code:
is a little more complicated. The while statement is something called a loop and a while loop is a type of loop that will run until the condition inside of the loop is no longer true. Take a look at the following section of code:
x = 0 while x < 2: x = x + 1 x = 3
The first line of this code creates a new variable called x, which we set the initial value of to one. We then enter a while loop, which states ‘while x is less than 2’ we are going to run the code inside the loop. The code inside of the loop says that we should take the value of x and set it’s value to x + 1. Since x is initially equal to zero, once our loop has run once the value of x will be one as 0 + 1 = 1.
Now that the loop has run through once we are going to run our check to see if x is less than 2. The value of x is currently one, which means the check we are doing is ‘is one less than two?’ The answer to this is of course True, therefore we will run the code inside the loop again. This takes the value of x, which is one, and adds one to it. After the second time our loop has run the value of x is therefore 2.
Now our condition will be checked again for the current value of x. The code will say is x less than 2/is 2 less than 2 (since our value of x is 2). The answer to this is of course False as two is equal to two so the code inside of the loop is no longer run and we move onto the next section of code. In this case, the final line of code is simply setting the value of x to 3. Notice how the code after the colon on the while loop is indented. This is to tell the computer which line of codes are part of the loop and which aren’t. The line ‘x = 3’ is not indented, therefore the computer knows that every time the loop runs it shouldn’t set the value of x to 3, but should wait until after the loop has finished executing before moving onto this section of the code.
Back to the original line of code then, our ‘while True:’ statement is simply saying to the computer, run whatever code is inside of this loop forever. Since True can never be False this loop will not stop executing unless we explicitly tell the code to stop running or our device runs out of battery. This construct is called an infinite loop and is an important part of game theory.
Notice now that the next three lines of code are all indented. This means that they are part of the loop and will run forever and ever.
Let’s break down the next line of code:
Look familiar? In Python we have written a Hello World program before, but here instead of having the text displayed on the screen it will scroll across the front of the display on the Microbit.
How does this happen? Well ‘display’ is a variable that has been imported with the first line of code and allows us to access the LEDs on the front of the Micro:Bit and turn them on. The ‘scroll’ function lets us pass in a String of text that will automatically be scrolled across the front of the Microbit. Remember that the quotation marks dictate that what we pass to the function is a String, so this line of code will simply scroll Hello, World! across the front of the Micro:Bit.
The next line of code:
also accesses our display variable, however this time we use a different function, the ‘show’ function in order to display an Image on the screen. An image is made up of different pixels that are switched on or off. The Image.HEART call gets an image of a heart that can be displayed on the Microbit LED Matrix. There are a number of other images that can also be displayed such as smiley faces, clocks or even Pacman.
The last line of code:
is extremely simple. This call simply makes the thread ‘sleep’ for 2000 milliseconds (2 seconds) before the loop is run again.
Running the code
Now that we understand what the code is doing, let’s learn how to run it. First of all plug the Microbit into your USB slot. Now press the start button at the bottom left of your screen and select ‘Computer’. From here Windows Explorer should load and you should see the following screen:
Notice on the left hand side that you can see Microbit listed as a device you can use. Now we have the Microbit connected in your browser window (on the Microbit website) click on the Download button and save the file to your documents. Once you have the file saved, find it in Windows Explorer and then drag it over to the Microbit. Once the file has finished downloading your program will run automatically. Congratulations you just ran your first program!
Displaying an image
Now that we have learned how to run our first piece of code, let’s start writing. To display the dice for our dice game we are going to need a way of displaying the face of the dice on the Microbit. To do this we have two options:
1.Create a set of six images, each one depicting a face of the dice. We can then use the display.show() function to print these images on the LED matrix.
2.Instead of creating six images we could turn on the individual pixels on the Microbit that corresponded to the face of a dice.
So without further ado, let’s get coding.
The first thing we are going to need to do is create a new image and store it as a variable. Once we have created this image we will then be able to call the show function on it to display it onto the Microbit screen.
We create an image by making a call to the Image() constructor. To this constructor we need to pass some information. This information is going to have to correspond to the pixels on the screen and tell the code which pixels should be turned on and which should be turned off. The way we do this is using a 1-9 for on and a 0 for off. The higher the value of the pixel the brighter it will be when it is switched on.
The number of pixels we are going to have to pass can be calculated by looking at the number of pixels on the screen. Our LED Matrix has 5 columns of pixels with 5 pixels per row. This means that we have a total of 5x5 pixels, which is equal to 25.
How are we going to pass this information to the constructor to tell it which pixels to turn on? Well we pass a long String of numbers corresponding to each row, separated by colons. The first line of code we write will create a new image with the centre pixel turned on and store it in a variable called one. This is going to look like this:
one = Image(“00000:00000:00900:00000:00000”)
Notice that the first 2 rows and last 2 rows are all set to 0/off. The middle row has the middle pixel set to a light intensity of 9 (full power).
Now that we have an image, we need to print it on the screen. The next thing we are going to do is delete the display.scroll(“Hello, World!”) line so that we no longer scroll text across the screen. We are then going to replace the variable Image.HEART in our display.show() function with:
This will pass the image we have printed to the display so that we are able to print it out onto the Microbit. After we have made our changes our code should look like this:
Download the script and copy it over to the Microbit and you should see that only the middle pixel lights up. Now for your first task:
Write another 5 lines of code that create variables two, three, four, five and six and create images that relate to the sides of a dice. You can test each of these images by changing the variable that is passed to our show function to two, three… etc. See the images below for reference.
When you throw a dice it is impossible to guess which number it will land on unless the dice is loaded. This means that we can consider whatever the result of the dice throw is as random. The moment you throw the dice the face it will land on will already be decided (without intervention such as a hand or wind), however the result is determined on a number of inputs such as the height and velocity it was thrown with, how much spin it has, the first surface it hits and many other variables.
Computers do not have the same luxury that we have here, which is an element of chaos. If you enjoy maths, chaos theory is the idea that the Universe we live in is chaotic and random. Human nature allows us to make decisions and if these decisions had already been made, then they wouldn’t need making. Therefore every time you make a decision to throw a dice there is a different outcome to if you had decided to not throw the dice, or if you had waited an extra second before throwing the dice.
Computers are programmed in a set way. Of course we can write program logic that states ‘if this variable is equal to 5 then do this, otherwise do this’ however this isn’t really a chaotic decision. The outcome is set and limited, the computer can only do one thing OR the other thing. There isn’t a decision making process that lets the computer create it’s own solutions. For example imagine I write a program that can play chess and pit it against the worlds best chess player. At one stage in the match the world number one sees a move, which allows him to put the computer into check. Because of the complexity of my program however the computer has already predicted this move and can immediately counter, putting the world number one into check.
The world number one gets so angry he is unable to beat my program that he flips the chessboard and walks away angrily. This is a decision he has made, it is completely random and if he had made other choices in the game then perhaps he would not have gotten angry enough to flip the board. If the tables had been turned and my computer program had been unable to beat the world’s best player it would not have been able to flip the board and walk away. My program has a set number of things it is allowed to do and cannot operate outside of these bounds.
A pseudo-random number is a number that satisfies the needs of a random number but has been generated by a defined mathematical process. What does this mean?
It sounds really complicated but in truth is quite simple. Think of the first thing that crops into your head. Mine was sweet corn. I can remember the last time I ate sweet corn but it wasn’t recent and if I’m honest I have no idea why that particular word cropped into my head. If I had been sat writing this worksheet and spilled a glass of water then it may have been 5 minutes later that I wrote up this paragraph. Would I have thought of sweet corn then or would I have thought of something else? Would I have even written this paragraph or would I have decided it wasn’t important? My point is: nobody knows how I made the decision I did and so this was a truly random decision. If I had to make the same decision again there is no telling if it would have been the same result.
Pseudo-random then is slightly different. Imagine that I have a list of names on different coloured pieces of paper. Red is Andy, Yellow is Paul, Green is Ellie and Blue is Anna. Now I get a group of 30 people together and ask them a questionnaire. One of the questions asks what their favourite colour is and after I process the results I find 11 people who’s favourite colour is blue. These people are then invited one at a time into a room where they are asked to choose one piece of paper. 9 out of the 11 people choose the blue card. The choice of each person is random, but due to knowing their favourite colour I am able to predict what the majority of them will choose.
This is similar to how pseudo-random works. Computers, as we discussed above, are unable to make random choices. However I am able to use an algorithm to generate a pseudo-random number. A pseudo-random number is calculated based on one or more limiting factors, such as the current time of the clock, how warm it is or how much light is hitting a sensor. For the purposes of most programs, particularly games, this is suitable as I have a number calculated in my program that is seemingly a random choice. If I were using this random number however to keep data secure, then it wouldn’t be suitable. If someone was able to re-create the exact parameters with which my program originally ran, they could discover the random number that was generated and then unlock all of my secure data.
The random library
Today for the purposes of our code we are going to be using a new library called random. From this library we will be using a specific function called randint which is used to generate a random number between two inputs, a maximum and a minimum. So to get started, head to the top of your code and just after the line where we have imported everything from Microbit (from microbit import *) we are going to write:
from random import randint
This line of code searches for the random library and from that library imports the randint function. In our code then, let’s generate a random number x:
x = randint(1, 6)
This line of code creates a new variable called x and sets it’s value equal to what is returned from our randint function. Notice the randint function takes two parameters in the form of integers, separated by a comma. The first integer is our minimum and the second is our maximum. We call randint an inclusive function – this means that the value of our maximum is included in the optional results i.e we are able to have a value of 5 for x. After this line of code is run then the value of x is going to be 1, 2, 3, 4, 5 or 6, exactly the number of faces on a dice.
In our program we are going to use this value of x to determine which face of the dice will be shown. If the value of x is 1 then we will use our ‘show’ function to display the variable ‘one’ which is an image with the centre pixel turned on. If we have a value of x equal to 2 then we will show two and so forth. We are going to achieve this by using the ‘if’ statement. Now however your code should look something like this:
The ‘if’ statement
Remember the while loop? We were entering into a loop of code that ran over and over until a condition became false. An ‘if’ statement is an extremely similar concept, the only difference is that an ‘if’ statement is only run once if the condition we are testing is true. Don’t worry, this will all make sense in a moment. Let’s take a look at an if statement:
x = randint(1, 2) if x == 1: print x if x == 2: print “NO”
The first line of code here is very similar to something we have already written up. We are creating a new random integer with a value or 1 or 2 and assigning it’s value to the variable x. We then test the value of x and if the value is 1 then we print x. The output of this would therefore be 1. If the value of x is equal to 2 then we simply print the word NO. The output of this would therefore be NO. Notice how if the value of x is 1, then the value of x can’t be equal to 2 therefore the second ‘if’ statement is not run and the same vice versa.
How can we make this work in our code then? Well we are going to write six simple if statement like the one above. The inner section of these ‘if’ statements however will not be to print anything, but we are going to call our display.show() function on whichever Image needs to be shown. So if the value of x is 1 we will call display.show(one). If the value of x is 2 we will call display.show(two). What is this going to look like in code? Inside of your while loop write:
if x == 1: display.show(one)
Every time the loop runs we will now print out the corresponding dice face to the number that we have just generated.
Write another 5 if statements that test for 2, 3, 4, 5 and 6 and print the corresponding dice face on the screen. Once you have done this deploy your code to the Microbit and every time you press the reset button (on the back) you will generate a new dice roll. Where could you move the line that sets the value of x in order to roll the dice every time the loop runs instead of every time we reset?
Shake it up
Now we have a way of ‘rolling’ the dice. At the minute our code should look like this:
However every time we want to roll the dice we have to press the reset button (or alternatively the dice will re-roll every 2 seconds if you have completed the end of task 2).
How can we give the user a way of rolling the dice? Well remember at the start of this worksheet we discussed the accelerometer in the Microbit and how it can be used to tell which way the device is facing and whether it is moving. Well we can use the gestures for the Microbit to tell when the device has been moved in a certain way. One option for a gesture is a ‘shake’. We can test in our main loop whether the device has been shaken and then generate a new value for x when it has. The way we detect gestures is by getting them from the accelerometer:
if accelerometer.was_gesture(“shake”): x = randint(1, 6)
These lines of code use an ‘if’ statement to test whether the device has been shaken before generating a new random value for x if it has. When the loop runs again therefore, since the value of x has changed the face that is printed will be changed to the new value of the dice roll. The last thing we have to do now is remove the call at the end of our loop to sleep the device for 2 seconds. Whilst the device is sleeping it is unable to detect any accelerometer data so be careful to not sleep the device if you need to detect gestures.
The final code
Now that we have finished our code should look something along these lines. I have written up a full example but please, if you are reading forward and haven’t yet completed task one and two then do so before reading the following:
And congratulations, we have built our first game for the Microbit. This is a very simple piece of code, only 30 lines long but we have introduced a lot of important concepts:
• Logic – Test if two things are equal and if so do something
• Random – What random means to a computer
• Loops – Getting the code to run over and over again
• Variables – Storing information to use at a later stage