CS21 Lab 4: functions and while loops

Written Assignment: Due Friday, October 1, at the start of class

Programming Assignment: Due Saturday, Oct 2, before midnight

Programming Tips

As you write your first programs, start using good programming practices now:

  • Use a comment at the top of the file to describe the purpose of the program (see example).

  • All programs should have a main() function (see example).

  • Use variable names that describe the contents of the variables.

  • Write your programs incrementally and test them as you go. This is really crucial to success: don’t write lots of code and then test it all at once! Write a little code, make sure it works, then add some more and test it again.

  • Don’t assume that if your program passes the sample tests we provide that it is completely correct. Come up with your own test cases and verify that the program is producing the right output on them.

  • Avoid writing any lines of code that exceed 80 columns.

    • Atom shows the column number in the lower left and draws a vertical line down the editing window at 80 characters.

    • In emacs, at the bottom, center of the window, there is an indication of both the line and the column of the cursor.

Function Comments

All functions should have a top-level comment! Please see our function example page if you are confused about writing function comments.

Are your files in the correct place?

Make sure all programs are saved to your cs21/labs/04 directory! Files outside that directory will not be graded.

$ update21
$ cd ~/cs21/labs/04
$ pwd
/home/username/cs21/labs/04
$ ls
Questions-04.txt
(should see your program files here)

Goals

  • Write programs with multiple functions.

  • Solve problems using indefinite while loops.

  • Use the random library to make pseudo-random choices.

1. Written Assignment: Stack Diagram

The first part of the lab involves you tracing a program with functions and showing the resulting stack that the function calls generate. This is excellent practice for what will almost certainly be a future quiz question! Download the PDF, print it out, and turn it in at the start of class on Friday.

2. Programming Assignment: Odds and Evens

For this week’s lab we’re going to incrementally develop a variant of the game odds and evens.

Our version of the rules.

For our version of the game, a human player will play against the computer, which will make selections randomly.

Initially, the human player predicts either odd or even. Next, both the human and computer player choose an integer between zero and five (inclusive) representing a number of fingers on one hand. Finally, sum the two chosen numbers and determine whether the sum is even or odd. The human player wins if they correctly predicted the odd/even result and loses if they didn’t.

Ultimately, we want the game to keep score of how well the human player is doing against the computer in multiple rounds of odds and evens.

We’ll build this game incrementally. As such, we’ll be modifying the main function as we move from step to step. There’s no need to save your main function from a previous step as you work on each next step. The entire lab will be written in the file odd_even.py.

2.1. Predicting odd or even

The first function you write and test should be named predict_it. It should prompt the human player to predict the result by typing either even or odd, and it should return the string they typed in (either "even" or "odd"). If the user doesn’t enter one of these two 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 predict_it function should not take any input parameters, and it should return a string value. Its function definition will look like:

def predict_it():

To help test your program in small pieces as you go, add a call to the predict_it function in main. For now, just print the value that predict_it returns. Be sure to test it with both good and invalid input to verify that it’s behaving as expected.

Here are some examples of how your program may behave while testing predict_it:

$ python3 odd_even.py
Predict either odd or even: odd
predict_it returned: odd

$ python3 odd_even.py
Predict either odd or even: 1
Whoops, you must predict either odd or even.  Try again.
Predict either odd or even: eeeeven
Whoops, you must predict either odd or even.  Try again.
Predict either odd or even: even
predict_it returned: even

Recall that python strings can be compared with relational operators like == or < just like integers and floats.

"morning" != "evening"   # evaluates to True

2.2. Getting user number choice

Next, write a function named get_choice that prompts the human player to enter an integer between 0 and 5 (the value they are contributing to the sum). Like predict_it, the get_choice function should only accept integers between 0 and 5. It should report an error and ask the user to try again if they enter invalid input. Ultimately, it should return the integer value that the user typed.

Like the predict_it function, get_choice should not take any input parameters. Its function definition will look like:

def get_choice():

Your implementation of get_choice will first need to verify that the string the user types in can be converted to an integer before you call int() on it (otherwise the program might crash). Given a string, you can use .isdigit() on a string to tell you whether or not conversion is safe. Here are some examples working with .isdigit():

>>> "3".isdigit()
True

>>> user_value = "37"
>>> user_value.isdigit()
True

>>> "blah".isdigit()
False

>>> user_value = "swarthmore"
>>> user_value.isdigit()
False

After you’ve confirmed that the player’s input can be converted to an integer, you also need to ensure that it falls within the range [0,5].

As we did with predict_it, let’s add a test call of get_choice to main so that we can verify that it’s working as expected before we proceed:

$ python3 odd_even.py
Predict either odd or even: odd
predict_it returned: odd
Enter a number between 0 and 5: 0
get_choice returned: 0

$ python3 odd_even.py
Predict either odd or even: even
predict_it returned: even
Enter a number between 0 and 5: 10
Sorry, you must enter an integer between 0 and 5.  Try again.
Enter a number between 0 and 5: 5
get_choice returned: 5

$ python3 odd_even.py
Predict either odd or even: odd
predict_it returned: odd
Enter a number between 0 and 5: blue
Sorry, you must enter an integer between 0 and 5.  Try again.
Enter a number between 0 and 5: -2
Sorry, you must enter an integer between 0 and 5.  Try again.
Enter a number between 0 and 5: 3
get_choice returned: 3

2.3. Determining a winner

Now that we have inputs, let’s write a function to determine a winner. The determine_winner function will take three parameters:

  • an even/odd prediction made by the human player (string)

  • the human player’s number choice (integer)

  • the computer player’s number choice (integer)

The function definition should look like:

def determine_winner(prediction, user_choice, comp_choice):

The determine_winner function should return a Boolean:

  • True if the human player who predicted odd/even was correct (and won the game)

  • False if the human player who predicted odd/even was incorrect (and lost the game)

Refer to the rules at the top of the page for a description of how to determine "correct".

Remember, we are writing this program incrementally so there’s no need to preserve your main function as you develop the solution to this next step. After completing determine_winner, you can update main to use predict_it and two calls to get_choice to gather the inputs you need to test determine_winner. For example:

$ python3 odd_even.py
Predict either odd or even: odd
Enter a number between 0 and 5: 1
Enter a number between 0 and 5: 1
For a prediction of odd and choices 1 and 1, determine_winner returned:
False

$ python3 odd_even.py
Predict either odd or even: odd
Enter a number between 0 and 5: 1
Enter a number between 0 and 5: 4
For a prediction of odd and choices 1 and 4, determine_winner returned:
True

$ python3 odd_even.py
Predict either odd or even: even
Enter a number between 0 and 5: 2
Enter a number between 0 and 5: 4
For a prediction of even and choices 2 and 4, determine_winner returned:
True

2.4. Keeping score

Finally, let’s write a print_scores function to nicely display the score between the human player and the computer.

The print_scores function should take the following parameters as input:

  • the user’s name (string)

  • the number of games won by the user (integer)

  • the number of games won by the computer (integer)

Note that this function does not return a value. The program will call it 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 should use string formatting and print out something like:

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

To test print_scores, you can add a few calls to it in main with any name and numbers you want (e.g, Beth, 3, and 1 as shown above). The formatting doesn’t have to match exactly what’s shown above, but please make it look similar so that it’s easier to grade!

2.5. Putting it all together

Now that you have all the functions you need, let’s combine them to play multiple rounds of odds and evens against a computer opponent. Be sure that all of the functions you write for this lab are well commented — if you haven’t done so already, now would be a good time to write those comments, as they may help you to put all the pieces together.

2.6. The main function

The main function of your program should do the following:

  • Ask the player for their name and the number of rounds to play. You may assume the player enters a valid positive integer for the number of rounds.

  • Continue playing the game for the number of requested rounds, keeping track of the number of wins for the human player and the computer. Use string formatting when printing results.

  • In each round, make use of the predict_it and get_choice functions to get the human player’s odd/even prediction and number choice.

  • Use the randint function from python’s random library to randomly choose a value between 0 and 5 for the computer player in each round. For example:

    from random import randint
    
    # Randomly select an integer between 0 and 5 (inclusive)
    random_value = randint(0, 5)
    print(random_value)
    
    # This will print something different every time from the set {0, 1, 2, 3, 4, 5}
  • Use determine_winner to award a win to either the human player or computer.

  • Display the results after each round, using print_scores to show the current scoreboard.

  • After all rounds are over, print the overall winner of the match (which player won the most games). Note: the final score could end in a tie.

2.6.1. 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. The more similar it looks to this output, the easier it will be to grade!

Sample output:

$ python3 odd_even.py
What is your name? Kevin
How many rounds should we play? 3
Predict either odd or even: odd
Enter a number between 0 and 5: 1
Kevin predicts odd and chooses 1.
Computer chooses 2.
    Kevin wins!
------------------------------
Kevin: 1     Computer: 0
------------------------------

Predict either odd or even: even
Enter a number between 0 and 5: 4
Kevin predicts even and chooses 4.
Computer chooses 0.
    Kevin wins!
------------------------------
Kevin: 2     Computer: 0
------------------------------

Predict either odd or even: odd
Enter a number between 0 and 5: 2
Kevin predicts odd and chooses 2.
Computer chooses 4.
    Computer wins!
------------------------------
Kevin: 2     Computer: 1
------------------------------

The champion is: Kevin!
$ python3 odd_even.py
What is your name? Lauri
How many rounds should we play? 2
Predict either odd or even: even
Enter a number between 0 and 5: 5
Lauri predicts even and chooses 5.
Computer chooses 1.
    Lauri wins!
------------------------------
Lauri: 1     Computer: 0
------------------------------

Predict either odd or even: odd
Enter a number between 0 and 5: 0
Lauri predicts odd and chooses 0.
Computer chooses 4.
    Computer wins!
------------------------------
Lauri: 1     Computer: 1
------------------------------

The final score is a tie!

3. 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…​

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!