View on GitHub

Making a Game of IT

Michigan State University - Summer 2019

Making a Game of IT - Day 1

Introductions & Getting Started

Why python?

Getting Started

Python - the very basics

The code for this section is in basics.py.

Comments in Python

Comments give programmers a way to annotate their code.

# '#' denotes a single-line comment. For example,
# This is a single-line comment!

"""
Three double quotes can be used to denote the start and end of a... you guessed it...
a multi-line comment!



This is all part of this multi-line comment!

And this, too!
"""

''' You can also use single quotes to denote a multi-line comment.

Remember, though, a multi-line comment started with three single-quotes must be
ended with three single-quotes!

For example, """
does not end this multi-line comment. But, '''

Why use comments?

Printing to the screen

We can use the print instruction to print things to the screen:

print("Hello world")
print("My name is Alex Lalejini")
print("I'm 26 years old.")
print("Ikea is adult disney land.")

Note that every time you run your program, those sentences are in the same order. Python programs are executed procedurally, instruction-by-instruction, from top to bottom.

What is a variable?

We use variables to store data and subsequently refer to that data. As a pet name lets us to refer to our 🐶, variables give us a way to refer to our data.

Variables in python must begin with a letter or underscore, but after the first character letters, numbers, and underscores are 👌. In contrast to pet names (where your pet does not care about the capitalization of their name), python variables are case sensitive (i.e, ‘DOGGO’ is not the same as ‘doggo’).

We can assign ‘strings’ to variables:

first_name = "Alex"     # This is a string
last_name = "Lalejini"  # This is also a string

In this above example, first_name is a variable. I assigned it the value "Alex" using the assignment operator =.

We can also assign numbers to variables:

age = 26              # This is an integer
half_of_three = 3.5   # This is a float (i.e., it has a decimal)

We can refer to previously assigned variables. For example, we can print out the values of some of our variables:

print(first_name)
print(last_name)
print(age)

Python can be used as a glorified calculator

You can (and we will) use python as a fancy calculator. All the classics are available out of the box: addition +, subtraction -, multiplication *, division /, modulus % (remainder), and exponentiation **.

In python:

this_year = 2019
my_age = 26

twice_my_age = 2 * age

ten_years_from_now = this_year + 10

year_born = this_year - my_age

half_my_age = age / 2

Just like in math class, you can enforce a particular order of operations using parentheses:

a = (1 + 1) * (2 + 2) # = 8
# is different from
b = 1 + 1 * 2 + 2     # = 5

More math is available in Python’s math module.

Getting user input

We can use python’s input() instruction to request information from the user:

user_input = input("I demand input: ")

In the code above, whatever the user types in gets stored in user_input. The string "I demand input: " is used as the prompt for input.

Working with strings

Find more things you can do to strings here: https://docs.python.org/3/library/stdtypes.html#string-methods

Basics - Challenges

Basics - Example code

|>> download basics.py

Python - conditionals and loops

Boolean Operators

The operator == will tell you if two things are equal. Note that one equal sign = means “assignment” and two equals signs == means “test equal.” If x and y are equal, x == y will turn into True. If x and y are not equal, x == y will turn into False.

For example,

print(11 == 11)
print("hello" == "hello")

< will tell you if the left thing is smaller than the right thing.

> will tell you if the left thing is bigger than the right thing.

<= and >= will do exactly what you expect.

Challenge: Which of the following three are equal to 1111?

Which is bigger, 123 * 45 or 8765?

Can test whether a user said “yes” using input?

if, elif, and else

Conditional statements (syntax: if) allow your code to make decisions based on input. Code inside an if block is only executed if the test next to the if evaluates to True. Note how whitespace at the beginning of a line determines which block a line of code is in.

print("duu du duu du dududu...")
print("duu du duu du dududu...")
if input("Is there something strange in your neighborhood? ") == "yes":
  print("who ya gonna call??? ghostbusters!!")

The syntax elif (else if) allows you to perform a subsequent test if the first if doesn’t evaluate to True. The syntax else is a catch-all that executes at the end of a series of if and elif tests if nothing else has triggered.

print("duu du duu du dududu...")
print("duu du duu du dududu...")
if input("Is there something strange in your neighborhood? ") == "yes":
  print("who ya gonna call??? ghostbusters!!")
elif input("An invisible man... sleepin in your bed? ") == "yes":
  print("who ya gonna call??? ghostbusters!!")
elif input("Mm.. if you've had a dose... of a  freaky ghost baby? ") == "yes":
  print("who ya gonna call??? ghostbusters!!")
else:
  print("you better NOT call... ghostbusters!")

Challenge: Ghostbusters is a PG-13 movie. Ask the user for their age and then tell them if they’re ready to see Ghostbusters. If they’re younger than thirteen, tell them no! Else, if they’re older than 113, tell them that they’re the oldest person in the world. Otherwise, tell them they’re cleared to watch Ghostbusters.

while and break

According to urban legend, saying “bloody mary” 13x into a mirror will summon a scary ghost. Here’s one way of doing that.

print("Bloody Mary!")
print("Bloody Mary!")
print("Bloody Mary!")
print("Bloody Mary!")
print("Bloody Mary!")
print("Bloody Mary!")
print("Bloody Mary!")
print("Bloody Mary!")
print("Bloody Mary!")
print("Bloody Mary!")
print("Bloody Mary!")
print("Bloody Mary!")
print("Bloody Mary!")

Pretty annoying, right? The syntax while repeats a block of code until the test next to it evaluates False.

while input("Keep going?") == "yes":
  print("Bloody Mary!")

We can make Python count to 13 for us. The variable i increases by one until it reaches 13.

i = 0
while i < 13:
  print("Bloody Mary!", i)
  i = i + 1

What if we want a way to back out of summoning the scary mirror ghost? Python’s break statement allows the programmer to end a loop. Let’s put a break statement inside an if to stop the summoning if we get scared.

i = 0
while i < 13:
  print("Bloody Mary!", i)
  i = i + 1
  if input("Scared yet??? ") == "yes":
    print("ok let's stop")
    break

for and range

Programmers want to execute a code block n times so often that Python gives us a way to do just that: a for loop coupled with the function range(0,n). Like so,

for i in range(0,13):
  print("Bloody Mary!", i)

Conceptually, for iterates over each element in a collection — it puts each element in the collection one at a time into the variable i. The function range(0,n) creates a collection with the numbers 0 through n-1. (This way, when code inside for i in range(0, n): runs n times.) If we wanted the numbers 1 through 13 instead of 0 through twelve, we would write range(1,14).

Comprehension Question: How many times will “Boo!” get printed?

for i in range(0, 3):
  for j in range(0, 3):
    print("Boo!")

Challenge: There’s one ghost in the first room. There’s two ghosts in the second room. There’s three ghosts in the third room… and so on and so forth. There’s thirteen rooms in this haunted 80’s penthouse. Can you use math and a loop to calculate how many ghosts we’re going to run into total?

Number Guessing Game

Let’s put it all together to make a number guessing game. Python will randomly choose a number and then we’ll make successive guesses until we get it. Each time we guess, Python will tell us if our guess was too low or too high.

Number guessing game solution

'''
guessing.py

Guessing game! Guess a number between (inclusive) 1 and 100.

Skills
- variables/user input
- looping
- generating random numbers
'''

import random

secret = random.randint(1, 101) # Question: why 101 instead of 100?
print('Secret is', secret) # sanity check our secret generator

while True:
    guess = int(input('Guess my secret: '))

    # (1) if user guessed correctly, they win!
    if guess == secret:
        print('YOU WON!! SUCH VICTORY!')
        break

    # (2) Can we give the player some hints?
    # - What sorts of hints might we want to give a player?
    if guess < 1 or guess > 100:
        print('Hint: 1-100')

    if guess > secret:
        print('Too high')
    else:
        print('Too low')

print('End')

# Challenge: Get rid of the magic numbers (min secret value and max secret value)
# Challenge: Tell the user how many guesses it took them to win
# Challenge question: What's the optimal strategy for playing this game?
# SUPER CHALLENGE: Make input request safe from bad user input
# - e.g., with try/catch or isnumeric

|>> download num_guess_game.py

Rock paper scissors

Extra Challenge: Can you write a program that lets two players play Rock, Paper, Scissors against eachother? Your program should request player 1 and player 2’s choices (rock, paper, or scissors), and determine whether player 1 wins, player 2 wins, or the two players tied.

Rock paper scissors solution

'''
Implements a one or two player game of rock-paper-scissors
'''

# Two-player version
print('Starting a game of ROCK-PAPER-SCISSORS')

# Get player 1's move
play = input('Player 1 move: ')
while play not in 'RPS' or len(play) != 1:
    print('Bad move')
    play = input('Player 1 move: ')

player_1_move = play

# Get player 2's move
play = input('Player 2 move: ')
while play not in 'RPS' or len(play) != 1:
    print('Bad move')
    play = input('Player 2 move: ')

player_2_move = play

# Determine a winner

# First, what are all of the possibilities?
# - What is the outcome of each?

# Question: How can we simplify (make it shorter) this code?
# - Tie:
# if player_1_move == player_2_move:
#     print('Tie game')

if player_1_move == 'R' and player_2_move == 'R':
    print('Tie game')

if player_1_move == 'R' and player_2_move == 'P':
    print('Paper covers rock!')
    print('Player 2 wins')

if player_1_move == 'R' and player_2_move == 'S':
    print('Rock smashes scissors!')
    print('Player 1 wins')

if player_1_move == 'P' and player_2_move == 'R':
    print('Paper covers rock!')
    print('Player 1 wins')

if player_1_move == 'P' and player_2_move == 'P':
    print('Tie game')

if player_1_move == 'P' and player_2_move == 'S':
    print('Scissors shred paper!')
    print('Player 2 wins')

if player_1_move == 'S' and player_2_move == 'R':
    print('Rock smashes scissors!')
    print('Player 2 wins')

if player_1_move == 'S' and player_2_move == 'P':
    print('Scissors shred paper!')
    print('Player 1 wins')

if player_1_move == 'S' and player_2_move == 'S':
    print('Tie game')

# Challenge: first to win three rounds
# Challenge: add ai player
# - static, random, copy-cat, opposite

|>> download rock_paper_scissors.py

Python - data structures

Lists

We can compose simple data types (e.g., strings, integers, etc) into more complex data structures.

A list, for example, lets us store a sequence of values (often referred to as elements):

pet_names = ['Yogi', 'Boomer', 'Gunther', 'Banana']

You can access and reassign individual positions (or indexes) in a list using square brackets []. NOTE: lists in python always start at 0 (e.g., ‘Yogi’ in our example is at position 0 of the pet_names list).

print(pet_names[0]) # will print Yogi
print(pet_names[1]) # will print Boomer
print(pet_names[3]) # will print Banana

# We can access a list with negative numbers, too...
print(pet_names[-1]) # will print Banana

CHALLENGE QUESTION: how might we get the second-to-last value in the list?

Answer:

print(pet_names[-2])

We can modify the value of something in the list:

pet_names[1] = "BOOMER"
print(pet_names[1]) # will print BOOMER

A word of warning: if you try to index into a position beyond the size of the list, python will yell at you: IndexError: list index out of range.

pet_names[4] # will give you an error
pet_names[100] # will give you an error
pet_names[-4] # will give you an error

We can loop over a list using a for loop:

for name in pet_names:
    print(name)

It’s often useful to check to see if a particular value is in the list:

print("'Alex' in the list? " + str('Alex' in pet_names))         # no
print("'Yogi' in the list? " + str('Yogi' in pet_names))         # yes
print("'BANANA' in the list? " + str('BANANA' in pet_names))     # nope - remember, python is case sensitive
print("'gunther' in the list? " + str('gunther' in pet_names))   # nope

We can append things to the end of lists:

pet_names.append("Doggo")
# We can print the entire list
print(pet_names)

We can insert things into the list at a particular position:

pet_names.insert(1, "Fishy")
print(pet_names)

We can remove a particular value from the list:

pet_names.remove("Gunther")
print(pet_names)

We can remove something from the list by position:

pet_names.pop(1)
print(pet_names)

Wait, how long is our list? We can use the len() instruction to check:

list_len = len(pet_names)
print(list_len)
# We could also:
print(len(list_len))

We can sort a list:

sorted_pet_names = sorted(pet_names)
print(sorted_pet_names)

# What if we want reverse order?
reverse_sorted_pet_names = sorted(pet_names, reverse=True)
print(reverse_sorted_pet_names)

We can remove everything from a list:

pet_names.clear()
print(pet_names)

For more things you can do with lists see: https://docs.python.org/3/tutorial/datastructures.html#more-on-lists

CHALLENGES

Taking the average (using a for loop):

numbers = [0, 1, 4, 8, -1, 100, 75, 20] # An arbitrary list of numbers
total = 0
for num in numbers:
  total = total + num
print(total / len(numbers)) # This will print out the average

Taking the average (using python’s sum instruction):

numbers = [0, 1, 4, 8, -1, 100, 75, 20] # An arbitrary list of numbers
total = sum(numbers)
print(total / len(numbers))

Getting the minimum and maximum value (using a for loop):

numbers = [0, 1, 4, 8, -1, 100, 75, 20] # An arbitrary list of numbers
min_num = numbers[0] # We'll assume the first number in the list is the minimum number
max_num = numbers[0] # We'll assume the first number in the list is the maximum number
for num in numbers:
  if num < min_num: # If the current number is less than the smallest number we've found so far
    min_num = num   #   - update minimum number
  if num > max_num: # If the current number is larger than the largest number we've found so far
    max_num = num   #   - update the maximum number

print("Minimum number is: " + str(min_num))
print("Maximum number is: " + str(max_num))
print("Min - max is: " + str(min_num - max_num))

Getting the minimum and maximum value (using python’s min and max instructions):

numbers = [0, 1, 4, 8, -1, 100, 75, 20] # An arbitrary list of numbers
min_num = min(numbers)
max_num = max(numbers)
print("Minimum number is: " + str(min_num))
print("Maximum number is: " + str(max_num))
print("Min - max is: " + str(min_num - max_num))

Dictionaries

We won’t spend much time on dictionaries for the moment, but we’ll point them out because they’re super useful.

A dictionary (often refered to as a dict) in Python is a set of key-value pairs.

In Python, dictionaries are denoted using {}.

info_dict = {"name": "Dumbledore", "age": 115}

In the above example, we created a dictionary with 3 entries with the following keys: "name", "age".

We access the values in a dictionary using their keys:

print(info_dict["name"])                  # Dumbledore
print(info_dict["age"])                   # 115

We can update the value associated with a particular key:

info_dict["name"] = "Harry Potter"
print(info_dict["name"])            # Harry Potter

We can add entries to a dictionary:

info_dict["muggle"] = False
print(info_dict)

CHALLENGE: Make a dictionary where at least one entry has a list for a value and another entry has a dictionary for a value.

For more on dictionaries: ttps://docs.python.org/3/tutorial/datastructures.html#dictionaries

Example code:

|>> download data_structures.py

Data structures - example games

World guessing game

In the word guessing game, the programmer has selected a secret word, and the player has 10 rounds to guess reveal what the secret is by guessing one letter at a time.

Word guessing game solution
'''
Game of Hangman
By: Josh

Skills:
- Looping
- Lists
'''

secret = 'banana'
guesses = []

rnd = 1
has_won = False

while rnd <= 10:
    print('Round', rnd)

    # Get a guess from the player (we only one one letter)
    guess = input('Guess a letter: ')
    print('You guessed:', guess)

    # We have some requirements for player input: e.g., len
    if len(guess) != 1:
        print('Only one letter at a time, please')
        continue

    if not guess.islower():
        print('Must be a lowercase letter.')
        continue

    guesses.append(guess)

    # Reveal the known/unknown letters
    revealed = ''
    for letter in secret:
        if letter in guesses:
            revealed += letter
        else:
            revealed += '*'

    print('Revealed so far: ', revealed)

    # How do we know if the player won?
    is_all_revealed =  '*' not in revealed

    if is_all_revealed:
        has_won = True
        print('You won!')
        break

    rnd += 1

if not has_won:
    print('YOU FAILURE!')

|>> download word_guess_game.py

Simon Says

Game description:

Simon says is played in rounds. Starting the game with and empty list, the program selects a random letter each round. The program prints the chosen letter for the player to see. The player must then input each letter that the program previously output. Any deviation from the correct sequence results in a loss. The player’s goal is to achieve as high a score as possible.

Example gameplay:

Simon says:  B
> B
Simon says: C
> B
> C
Simon says: A
> B
> C
> A
Simon says: C
> B
> C
> A
> C
Simon says: D
> C
WRONG! Final score = 4

In the above example, the program output all of the ‘simon says’ lines (using print("Simon says:", letter)), and player input (using input(">")) is given after the ‘>’ prompt. When the player fails to repeat the full sequence, the player loses, and the game reports their final score.

After you have a working game please put up a green sticky Then add the following optional features:

Simon says solution
'''
Simple game of simon says

Skills:
- Lists, random, looping/conditionals
'''

import random

items = [] # Things simon said
while True:
    # What does simon say?
    new_item = random.choice('ABCDEF')
    items.append(new_item)
    print('Simon says: ', new_item)

    # Can the player correct repeat everything simon has said so far?
    was_wrong = False
    for correct_item in items:
        player_item = input('> ')
        if correct_item != player_item:
            was_wrong = True
            break

    if was_wrong:
        print('You lose')
        break

|>> download simon_says.py