13. Random Numbers

../../_images/dice_1.svg

Now if our games do the same thing each time the game runs, that’s not very interesting. At the end of this chapter we’ll introduce random numbers. That is, we can have the computer roll the dice to change up the game each time we run it.

../../_images/dice_2.svg

Random numbers are heavily used in computer science for programs that involve games or simulations.

13.1. The randrange Function

By default, Python does not know how to make random numbers. It is necessary to have Python import a code library that can create random numbers. So to use random numbers, the first thing that should appear at the top of the program is an import statement:

import random

Just like with pygame, it is important not to create a file with the same name as what is being imported. Creating a file called random.py will cause Python to start importing that file instead of the system library that creates random numbers.

After this, random numbers can be created with the randrange function. For example, this code creates random numbers from 0 to 49. By default the lower bound is 0.

Random number from 0 to 49
my_number = random.randrange(50)

The next code example generates random numbers from 100 to 200. Just like the range function the second parameter specifies an upper-bound that is not inclusive. Therefore if you want random numbers up to and including 200, specify 201.

Random number from 100 to 200
my_number = random.randrange(100, 201)

13.2. Random Chance

Often in games there is a random chance of something happening. How do we program this? It isn’t too hard. Here’s an example where we have a 1 in 5 chance of meeting a dragon:

Random Chance of Something Happening
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import random


# The line below will "roll the dice" 20 times.
# Don't copy this 'for' loop into your program.
# It is just here so we can try this example over and over.
for i in range(20):

    # The line below will roll a random number 0-4.
    # If we roll a '0' then print that we encountered a dragon.
    if random.randrange(5) == 0:
        print("DRAGON!!!")
    else:
        print("No dragon.")

This code repeats twenty times. Inside the loop, we “roll the dice” and get a number between 0 and 4. If we roll a 0, then we encounter a dragon. Otherwise we don’t.

13.3. The random Function

All of the prior code generates integer numbers. If a floating point number is desired, a programmer may use the random function.

The code below generates a random number from 0 to 1 such as 0.4355991106620656.

Random floating point number from 0 to 1
my_number = random.random()

With some simple math, this number can be adjusted. For example, the code below generates a random floating point number between 10 and 15:

Random floating point number between 10 and 15

my_number = random.random() * 5 + 10

13.4. Number Guessing Game Example

Here is the code for the number guessing game at the start of the chapter.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
"""
Random Number Guessing Game
"""
import random


def main():

    print("Hi! I'm thinking of a random number between 1 and 100.")

    # NEW CONCEPT
    # Create a secret number
    secret_number = random.randrange(1, 101)

    # Initialize our attempt count, we start with attempt 1.
    user_attempt_number = 1

    # Set user guess to something secret number can't be, so we can
    # get our 'while' loop started.
    user_guess = 0

    # NEW CONCEPT
    # Loop until user_guess our secret number, or we run out of attempts.
    while user_guess != secret_number and user_attempt_number < 8:

        # Tell the user what attempt we are on, and get their guess:
        print("--- Attempt", user_attempt_number)
        user_input_text = input("Guess what number I am thinking of: ")
        user_guess = int(user_input_text)

        # Print if we are too high or low, or we got it.
        if user_guess > secret_number:
            print("Too high.")
        elif user_guess < secret_number:
            print("Too low.")
        else:
            print("You got it!")

        # Add to the attempt count
        user_attempt_number += 1

    # Here, check to see if the user didn't guess the answer, and ran out of tries.
    # Let her know what the number was, so she doesn't spend the rest of her life
    # wondering.
    if user_guess != secret_number:
        print("Aw, you ran out of tries. The number was " + str(secret_number) + ".")

# Call the main function
main()

13.5. Mudball Example

This is a fun text-only game that two players can play. It uses a few concepts we haven’t covered yet.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
"""
This is a sample text-only game that demonstrates the use of functions.
The game is called "Mudball" and the players take turns lobbing mudballs
at each other until someone gets hit.
"""

import math
import random


def print_instructions():
    """ This function prints the instructions. """

    # You can use the triple-quote string in a print statement to
    # print multiple lines.
    print("""
Welcome to Mudball! The idea is to hit the other player with a mudball.
Enter your angle (in degrees) and the amount of PSI to charge your gun
with.
        """)


def calculate_distance(psi, angle_in_degrees):
    """ Calculate the distance the mudball flies. """
    angle_in_radians = math.radians(angle_in_degrees)
    distance = .5 * psi ** 2 * math.sin(angle_in_radians) * math.cos(angle_in_radians)
    return distance


def get_user_input(name):
    """ Get the user input for psi and angle. Return as a list of two
    numbers. """
    # Later on in the 'exceptions' chapter, we will learn how to modify
    # this code to not crash the game if the user types in something that
    # isn't a valid number.
    psi = float(input(name + " charge the gun with how many psi? "))
    angle = float(input(name + " move the gun at what angle? "))
    return psi, angle


def get_player_names():
    """ Get a list of names from the players. """
    print("Enter player names. Enter as many players as you like.")
    done = False
    players = []
    while not done:
        player = input("Enter player (hit enter to quit): ")
        if len(player) > 0:
            players.append(player)
        else:
            done = True

    print()
    return players


def process_player_turn(player_name, distance_apart):
    """ The code runs the turn for each player.
    If it returns False, keep going with the game.
    If it returns True, someone has won, so stop. """
    psi, angle = get_user_input(player_name)

    distance_mudball = calculate_distance(psi, angle)
    difference = distance_mudball - distance_apart

    # By looking ahead to the chapter on print formatting, these
    # lines could be made to print the numbers is a nice formatted
    # manner.
    if difference > 1:
        print("You went", difference, "yards too far!")
    elif difference < -1:
        print("You were", difference * -1, "yards too short!")
    else:
        print("Hit!", player_name, "wins!")
        return True

    print()
    return False


def main():
    """ Main program. """

    # Get the game started.
    print_instructions()
    player_names = get_player_names()
    distance_apart = random.randrange(50, 150)

    # Keep looking until someone wins
    done = False
    while not done:
        # Loop for each player
        for player_name in player_names:
            # Process their turn
            done = process_player_turn(player_name, distance_apart)
            # If someone won, 'break' out of this loop and end the game.
            if done:
                break

if __name__ == "__main__":
    main()