For the codelabs in this pathway, you will be building a Dice Roller Android app. When the user "rolls the dice," a random result will be generated. The result takes into account the number of sides of the dice. For example, only values from 1-6 can be rolled from a 6-sided dice.

This is what the final app will look like.

To help you focus on the new programming concepts for this app, you will use the browser-based Kotlin programming tool to create core app functionality. The program will output your results to the console. Later you will implement the user interface in Android Studio.

In this first codelab, you will create a Kotlin program that simulates rolling dice and outputs a random number, just like a dice would.

Prerequisites

Create and run a Kotlin program that uses variables and functions, and prints a result to the console.

Format numbers within text using a string template with the ${variable} notation.

What you'll learn

How to programmatically generate random numbers to simulate dice rolls.

How to structure your code by creating a Dice class with a variable and a method.

How to create an object instance of a class, modify its variables, and call its methods.

What you'll build

A Kotlin program in the browser-based Kotlin programming tool that can perform a random dice roll.

What you need

A computer with an internet connection

Games often have a random element to them. You could earn a random prize or advance a random number of steps on the game board. In your everyday life, you can use random numbers and letters to generate safer passwords!

Instead of rolling actual dice, you can write a program that simulates rolling dice for you. Each time you roll the dice, the outcome can be any number within the range of possible values. Fortunately, you don't have to build your own random-number generator for such a program. Most programming languages, including Kotlin, have a built-in way for you to generate random numbers. In this task, you will use the Kotlin code to generate a random number.

Set up your starter code

Delete all the existing code in the code editor and replace it with the code below. This is the main() function you worked with in earlier codelabs (see Write your first Kotlin program codelab).

fun main() {
}

Use the random function

To roll a dice, you need a way to represent all the valid dice roll values. For a regular 6-sided dice, the acceptable dice rolls are: 1, 2, 3, 4, 5, and 6.

Previously, you learned that there are types of data like Int for integer numbers and String for text. IntRange is another data type, and it represents a range of integer numbers from a starting point to an endpoint. IntRange is a suitable data type for representing the possible values a dice roll can produce.

Inside your main() function, define a variable as a val called diceRange. Assign it to an IntRange from 1 to 6, representing the range of integer numbers that a 6-sided dice can roll.

val diceRange = 1..6

You can tell that 1..6 is a Kotlin range because it has a start number, two dots, followed by an ending number (no spaces in between). Other examples of integer ranges are 2..5 for the numbers 2 through 5, and 100..200 for the numbers 100 through 200.

Tip: Notice that it does not say IntRange in this definition, in the same way you did not have to specify Int or String when creating a variable for an integer or a string. Most of the time, the system can figure out what data type you intend.

For example, the system interprets this:

val diceRange = 1..6

as this:

val diceRange: IntRange = 1..6

Similar to how calling println() tells the system to print the given text, you can use a function called random() to generate and return a random number for you for a given range. As before, you can store the result in a variable.

Inside main(), define a variable as a val called randomNumber.

Make randomNumber have the value of the result of calling random() on the diceRange range, as shown below.

val randomNumber = diceRange.random()

Notice that you are calling random() on diceRange using a period, or dot, between the variable and the function call. You can read this as "generating a random number from diceRange". The result is then stored in the randomNumber variable.

To see your randomly generated number, use the string formatting notation (also called a "string template") ${randomNumber} to print it, as shown below.

Run your code several times. Each time, you should see output as below, with different random numbers.

Random number: 4

Tips about ranges:

Ranges can be between any integers. The following are valid ranges: 3..46, 0..270, -6..+6, -10..-4.

You can call functions directly on a range, for example: (1..6).random().

When you roll dice, they are real objects in your hands. While the code you just wrote works perfectly fine, it's hard to imagine that it's about actual dice. Organizing a program to be more like the things it represents makes it easier to understand. So, it would be cool to have programmatic dice that you can roll!

All dice work essentially the same. They have the same properties, such as sides, and they have the same behavior, such as that they can be rolled. In Kotlin, you can create a programmatic blueprint of a dice that says that dice have sides and can roll a random number. This blueprint is called a class.

From that class, you can then create actual dice objects, called object instances. For example, you can create a 12-sided dice, or a 4-sided dice.

Tip: A class is similar to how an architect's blueprint plans are not the house; they are the instructions of how to build the house. The house is the actual thing or object instance created according to the blueprint.

Note: Organizing everything about dice into a class is called encapsulation. Encapsulation is a big fancy word, but all it means is that you can enclose functionality that is logically related into a single place.

Define a Dice class

In the following steps, you will define a new class called Dice to represent a rollable dice.

To start afresh, clear out the code in the main() function so that you end up with the code as shown below.

fun main() {
}

Below this main() function, add a blank line, and then add code to create the Dice class. As shown below, start with the keyword class, followed by the name of the class, followed by an opening and closing curly brace. Leave space in between the curly braces to put your code for the class.

class Dice {
}

Note:

Similar to using the fun keyword in Kotlin to create a new function, use the class keyword to create a new class.

You can choose any name for a class, but it is helpful if the name indicates what the class represents. By convention, the class name is in camel case. For example: Car, ParkingMeter, and CustomerRecord are all valid class names, and you can guess at what they represent.

Inside a class definition, you can specify one or more properties for the class using variables. Real dice can have a number of sides, a color, or a weight. In this task, you'll focus on the property of number of sides of the dice.

Inside the Dice class, add a var called sides for the number of sides your dice will have. Set sides to 6.

class Dice {
var sides = 6
}

That's it. You now have a very simple class representing dice.

Create an instance of the Dice class

With this Dice class, you have a blueprint of what a dice is. To have an actual dice in your program, you need to create a Dice object instance. (And if you needed to have three dice, you would create three object instances.)

To create an object instance of Dice, in the main() function, create a val called myFirstDice and initialize it as an instance of the Dice class. Notice the parentheses after the class name, which denote that you are creating a new object instance from the class.

fun main() {
val myFirstDice = Dice()
}

Now that you have a myFirstDice object, a thing made from the blueprint, you can access its properties. The only property of Dice is its sides. You access a property using the "dot notation". So, to access the sides property of myFirstDice, you call myFirstDice.sides which is pronounced "myFirstDice dot sides".

Below the declaration of myFirstDice, add a println() statement to output the number of sides of myFirstDice.

println(myFirstDice.sides)

Note: You used the dot notation earlier when calling diceRange.random(). Generalized, you can think of the dot notation as saying, "on something-dot-perform some action". Such as here, with myFirstDice.sides, "on this instance, get the sides property".

Run your program and it should output the number of sides defined in the Dice class.

6

You now have a Dice class and an actual dice myFirstDice with 6 sides.

Let's make the dice roll!

Make the Dice Roll

You previously used a function to perform the action of printing cake layers. Rolling dice is also an action that can be implemented as a function. And since all dice can be rolled, you can add a function for it inside the Dice class. A function that is defined inside a class is also called a method.

In the Dice class, below the sides variable, insert a blank line and then create a new function for rolling the dice. Start with the Kotlin keyword fun, followed by the name of the method, followed by parentheses (), followed by opening and closing curly braces {}. You can leave a blank line in between the curly braces to make room for more code, as shown below. Your class should look like this.

class Dice {
var sides = 6
fun roll() {
}
}

Note: You can name this method anything you want, but it is helpful to give it a name that indicates what action it performs. The naming convention for functions and methods is to start with a lowercase letter, use camel case, and start with an action verb, if possible.

When you roll a six-sided dice, it produces a random number between 1 and 6.

Inside the roll() method, create a val randomNumber. Assign it a random number in the 1..6 range. Use the dot notation to call random() on the range.

val randomNumber = (1..6).random()

After generating the random number, print it to the console. Your finished roll() method should look like the code below.

To actually roll myFirstDice, in main(), call the roll() method on myFirstDice. You call a method using the "dot notation". So, to call the roll() method of myFirstDice, you type myFirstDice.roll() which is pronounced "myFirstDice dot roll()".

Run your code! You should see the result of a random dice roll below the number of sides. Run your code several times, and notice that the number of sides stays the same, and the dice roll value changes.

6
4

Congratulations! You have defined a Dice class with a sides variable and a roll() function. In the main() function, you created a new Dice object instance and then you called the roll() method on it to produce a random number.

Currently you are printing out the value of the randomNumber in your roll() function and that works great! But sometimes it's more useful to return the result of a function to whatever called the function. For example, you could assign the result of the roll() method to a variable, and then move a player by that amount! Let's see how that's done.

In main() modify the line that says myFirstDice.roll(). Create a val called diceRoll. Set it equal to the value returned by the roll() method.

val diceRoll = myFirstDice.roll()

This doesn't do anything yet, because roll() doesn't return anything yet. In order for this code to work as intended, roll() has to return something.

In previous codelabs you learned that you need to specify a data type for input arguments to functions. In the same way, you have to specify a data type for data that a function returns.

Change the roll() function to specify what type of data will be returned. In this case, the random number is an Int, so the return type is Int. The syntax for specifying the return type is: After the name of the function, after the parentheses, add a colon, space, and then the Int keyword for the return type of the function. The function definition should look like the code below.

fun roll(): Int {

Run this code. You will see an error in the Problems View. It says:

A ‘return' expression is required in a function with a block body.

You changed the function definition to return an Int, but the system is complaining that your

code doesn't actually return an Int. "Block body" or "function body" refers to the code between the curly braces of a function. You can fix this error by returning a value from a function using a return statement at the end of the function body.

In roll(), remove the println() statement and replace it with a return statement for randomNumber. Your roll() function should look like the code below.

Run your program and you should see a message for the 6-sided dice, and a second message for the 20-sided dice.

Your 6 sided dice rolled 3!
Your 20 sided dice rolled 15!

The idea of a class is to represent a thing, often something physical in the real world. In this case, a Dice class does represent a physical dice. In the real world, dice cannot change their number of sides. If you want a different number of sides, you need to get a different dice. Programmatically, this means that instead of changing the sides property of an existing Dice object instance, you should create a new dice object instance with the number of sides you need.

In this task, you are going to modify the Dice class so that you can specify the number of sides when you create a new instance. Change the Dice class definition to accept an argument for the number of sides. This is similar to how a function can accept arguments for input.

Modify the Dice class definition to accept an integer argument called numSides. The code inside your class does not change.

class Dice(val numSides: Int) {
// Code inside does not change.
}

Inside the Dice class, delete the sides variable, as you can now use numSides.

Note: Changing code to make it shorter, more efficient, or easier to read and understand is called refactoring. It's like writing a document, where you write a first draft that has all the information, and then edit and refine your words.

Call the random() function on an IntRange to generate a random number: (1..6).random()

Classes are like a blueprint of an object. They can have properties and behaviors, implemented as variables and functions.

An instance of a class represents an object, often a physical object, such as a dice. You can call the actions on the object and change its attributes.

You can pass input to a class when you create an instance by specifying an argument for the class definition. For example: class Dice(val numSides: Int) and then create an instance with Dice(6).

Functions can return something. Specify the data type to be returned in the function definition, and use a return statement in the function body to return something. For example: fun example(): Int { return 5 }