CS21 Lab 4: functions and while loops

Due Saturday, Oct 7, before midnight

Goals

  • Develop your understanding of the stack and how function calls and returns work

  • Write programs with multiple functions.

  • Solve problems using indefinite while loops.

  • Learn to use the random library to make pseudo-random choices.

1. Written Assignment: Stack Diagram

The first part of this lab is a written assignment to trace through some Python code, show the program output and draw the stack. Download the following .pdf file, print it out: lab4stack.pdf

You should write your solution on the print out, and submit it at the start of the class on Friday.

2. Big picture for solving this lab

In this lab, we will be writing a program for a human user to play rock-paper-scissors against a computer. (If you aren’t familiar with the game, the rock-paper-scissors wikihow page should help explain it.)

Building a two-player game requires a lot of planning! You shouldn’t just sit down and start writing a two-player game from scratch. So in this lab, we’re going to guide you through writing each step of the process, building the program incrementally.

Each section will have you write one function which will be part of the larger program. After you write each new function, we’ll have you test that function by calling it in main. Until you get almost to the very end, you’ll be modifying the main function in order to test each function. There’s no need to save your main function from a previous step as you work on each next step. At the very end, we’ll tell you when it’s time to put all the functions together into a working version of the two-player game.

You’ll put all of your code for the rest of this lab in the file rps.py.

3. Get a choice for rock-paper-scissors

In the file named rps.py, write a function named get_choice that asks a user to enter one of "rock", "paper", or "scissors", and returns the string value entered by the user. If the user doesn’t enter one of these three string values, your function should print an error message, and prompt the user to try again. The function should only return when the user enters a valid string value.

The get_choice function does not take any input values (it has no parameters), but it should return a string value. Its function definition will look like:

def get_choice():

3.1. Test get_choice in main

To test get_choice, you should have your main function call the get_choice function and print out the value returned. Your main should something look like this:

def main():
    chosen = get_choice()
    print("get_choice returned %s" % (chosen))

You can now test to make sure the get_choice function is working properly. Here are some examples of what your program should do at this point:

$ python3 rps.py
Pick one of rock, paper, or scissors: rock
get_choice returned rock

$ python3 rps.py
Pick one of rock, paper, or scissors: Paper
Whoops! Paper isn't a valid choice. Try again.
Pick one of rock, paper, or scissors: hey, it should work!
Whoops! hey, it should work! isn't a valid choice. Try again.
Pick one of rock, paper, or scissors: ok, fine
Whoops! ok, fine isn't a valid choice. Try again.
Pick one of rock, paper, or scissors: paper
get_choice returned paper
Remember that python strings can be compared with relational operators like == or < just like integers and floats:
$ python3
>>> "rock" == "paper"   # evaluates to False
>>> "rock" != "paper"   # evaluates to True

4. Play one game of rock-paper-scissors

Let’s extend our program to add a function that plays one game of rock-paper-scissors.

Remember, we are solving this incrementally so there’s no need to preserve your main function as you develop the solution to this next step.

To play a game, add a new function called determine_winner. This function takes as input two string values, the first representing player 1’s choice (of "rock", "paper", or "scissors"), and the second representing player 2’s choice. The function should determine the winner of one game of rock-paper-scissors based on the players' choices, and return a value indicating which player won. The function should return:

0 if the game ends in a tie
1 if player one wins
2 if player two wins

Its function definition will look like:

def determine_winner(player1, player2):

The rules of rock-paper-scissors are:

  • if both players choose the same thing, the game is a tie

  • rock beats scissors (rock breaks scissors)

  • scissors beat paper (scissors cut paper)

  • paper beats rock (paper wraps rock)

4.1. Test determine_winner in main

To test the determine_winner function, you need to simulate having two players playing the game. For now, let’s just get two inputs from the user.

In main, use the get_choice function to read a value for one player. Then use the get_choice function again to read a value for the second player.

Once you have the choices made by each player, you can test your determine_winner function to see who won. Use the return value from determine_winner to print out a nice message in main.

Here are some example runs. Your main does not need to run exactly like this, but it should test determine_winner in the same way as shown below.

$ python3 rps.py
Player 1:
Pick one of rock, paper, or scissors: scissors
Player 2:
Pick one of rock, paper, or scissors: rock
Player 1 picked scissors and Player 2 picked rock
determine_winner returned 2
Player 2 wins!


$ python3 rps.py
Player 1:
Pick one of rock, paper, or scissors: papper
Whoops! papper isn't a valid choice. Try again.
Pick one of rock, paper, or scissors: paper
Player 2:
Pick one of rock, paper, or scissors: rock
Player 1 picked paper and Player 2 picked rock
determine_winner returned 1
Player 1 wins!

$ python3 rps.py
Player 1:
Pick one of rock, paper, or scissors: rock
Player 2:
Pick one of rock, paper, or scissors: rock
Player 1 picked rock and Player 2 picked rock
determine_winner returned 0
A tie.

5. Play rock-paper-scissors against the computer

For the final part, you are going to add code so that you can play multiple rounds of rock-paper-scissors against the computer.

After each round of the game, you should print out the current scores using a function called print_scores.

There’s no need to preserve your main function from the previous steps, but much of what you wrote in the last step can be reused in this step if you find that helpful.

5.1. The print_scores function

The print_scores function should take the following parameters as input:

  • a string containing the user’s name

  • the integer number of games won by the user

  • the integer number of games won by the computer

Note that this function does not return a value. It is called for the side-effect of printing some information. The function definition will look like:

def print_scores(name, user_wins, comp_wins):

The function should print out the current scores of the two players between lines of dashes. For example, with the argument values "Beth", 3, and 1, it would print out something like:

------------------------------
Beth: 3     Computer: 1
------------------------------

5.1.1. Test print_scores in main

Now that you’ve had some practice testing get_choice and determine_winner, write some code in main that will let you test the print_scores function. When you’re satisfied that print_scores works as expected, you can move on to the next section.

5.2. Choosing a random item from a sequence

There is nothing for you to code in this section, but if you are unfamiliar with the choice function from the random library, this should help you with the next section of the lab.

In the random library there is a function called choice that will randomly select an item from a sequence. The program below shows two examples:

from random import choice

# When you run this program multiple times, you should get different,
# random results each time you run it.

def main():
    day = "tuesday"
    letter = choice(day) # choose a random letter from the string "tuesday"
    print(letter)

    semester = ["september", "october", "november", "december"]
    month = choice(semester) # choose a random string from the list
    print(month)

main()

In the main function described below, you will use the choice function to randomly choose between "rock", "paper" or "scissors", similar to the example above showing how to use choice to choose a random month of the semester.

5.3. The main function

The main function of your program should do the following:

  • Ask the user for their name and the number of wins (num_wins) needed to win the match. You can assume the user enters a valid positive integer for the number of wins needed.

  • Enable the user to play as many rounds of rock-paper-scissors as needed until either the player or the computer wins a total of num_wins times.

  • Be sure to make use of the get_choice function to get the human player’s choice each round and the determine_winner function to compute the winner of each round of play.

  • To get the computer’s choice, don’t use the get_choice function. Instead, use the choice function described above to randomly choose "rock", "paper" or "scissors". Be sure the computer randomly selects one of these each round. Remember that you will need to put from random import choice at the top of your program in order to use the choice function.

  • Display the result (e.g. report that it was a tie, or report which player won) after each round. Also, use the print_scores function to show the current scores.

  • When either the player or the computer wins num_wins times, print the winner of the match and the total number of rounds that it took to finally win the match.

5.4. Sample output

Your program’s output does not need to be identical to the following output, but you should make sure to have all the required functionality and that your program displays the information in a readable way.

Sample output:

$ python3 rps.py
What is your name? Jocelyn
How many wins should we play until? 2
Let's see who can win 2 games first! Good luck.

Next round:
Pick one of rock, paper, or scissors: rock
Jocelyn picks rock and Computer picks paper
... Computer wins!
--------------------
Jocelyn: 0   Computer: 1
--------------------

Next round:
Pick one of rock, paper, or scissors: scissors
Jocelyn picks scissors and Computer picks paper
... Jocelyn wins!
--------------------
Jocelyn: 1   Computer: 1
--------------------

Next round:
Pick one of rock, paper, or scissors: woo!
Whoops! woo! isn't a valid choice. Try again.
Pick one of rock, paper, or scissors: scissors again
Whoops! scissors again isn't a valid choice. Try again.
Pick one of rock, paper, or scissors: scissors
Jocelyn picks scissors and Computer picks scissors
... A tie.
--------------------
Jocelyn: 1   Computer: 1
--------------------

Next round:
Pick one of rock, paper, or scissors: rock
Jocelyn picks rock and Computer picks scissors
... Jocelyn wins!
--------------------
Jocelyn: 2   Computer: 1
--------------------
... in 4 rounds.

$ python3 rps.py
What is your name? Gautam
How many wins should we play until? 3
Let's see who can win 3 games first! Good luck.

Next round:
Pick one of rock, paper, or scissors: scissors
Gautam picks scissors and Computer picks paper
... Gautam wins!
--------------------
Gautam: 1   Computer: 0
--------------------

Next round:
Pick one of rock, paper, or scissors: paper
Gautam picks paper and Computer picks rock
... Gautam wins!
--------------------
Gautam: 2   Computer: 0
--------------------

Next round:
Pick one of rock, paper, or scissors: paper
Gautam picks paper and Computer picks paper
... A tie.
--------------------
Gautam: 2   Computer: 0
--------------------

Next round:
Pick one of rock, paper, or scissors: paper
Gautam picks paper and Computer picks rock
... Gautam wins!
--------------------
Gautam: 3   Computer: 0
--------------------
... in 4 rounds.

6. Answer the Questionnaire

Each lab will have a short questionnaire at the end. Please edit the Questions-04.txt file in your cs21/labs/04 directory and answer the questions in that file.

Once you’re done with that, run handin21 again.

Turning in your labs…​.

Answer the Questionnaire

Each lab will have a short questionnaire at the end. Please edit the Questions-04.txt file in your cs21/labs/04 directory and answer the questions in that file.

Once you’re done with that, you should run handin21 again.

Submitting lab assignments

Remember to run handin21 to turn in your lab files! You may run handin21 as many times as you want. Each time it will turn in any new work. We recommend running handin21 after you complete each program or after you complete significant work on any one program.

Logging out

When you’re done working in the lab, you should log out of the computer you’re using.

First quit any applications you are running, like the browser and the terminal. Then click on the logout icon (logout icon or other logout icon) and choose "log out".

If you plan to leave the lab for just a few minutes, you do not need to log out. It is, however, a good idea to lock your machine while you are gone. You can lock your screen by clicking on the lock xlock icon. PLEASE do not leave a session locked for a long period of time. Power may go out, someone might reboot the machine, etc. You don’t want to lose any work!