CS21 Lab 5: More Advanced Functions

Due Sunday, October 11, before midnight

As you write programs, use good programming practices:

  • 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.

    • Always work in a terminal window that is 80 characters wide (resize it to be this wide)

    • In vscode, at the bottom right in the window, there is an indication of both the line and the column of the cursor.

Function Comments

All functions should include a comment explaining their purpose, parameters, return value, and describe any side effects. Please see our function example page if you are confused about writing function comments.

Make sure you are working in the correct directory when you edit and run lab 05 files.

Run update21 to get the starting point code of the next lab assignment. This will create a new ~/cs21/labs/05 directory for your lab work. Edit and run Lab 05 programs from within your cs21/labs/05 directory.

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

$ update21
$ cd ~/cs21/labs/05
$ pwd
/home/username/cs21/labs/05
$ ls
(should see your program files here)

Then edit and run program files in your ~/cs21/labs/05 directory:

$ code filename.py
$ python3 filename.py

Goals

  • More practice writing programs with multiple functions.

  • Perform input validation using indefinite while loops.

  • Index into lists.

  • Write functions that mutate lists.

For this week’s lab we’re going to incrementally develop an implementation of Milo’s Day, a cat themed version of the game Mastermind.

Game rules.

Milo the Cat loves to do four activities every day but only knows how to do six activities at all! You, the player, need to figure out which activities Milo did and the order he did them today. You will have a certain number of turns to determine the order Milo did four activities. The number of turns is determined by the user (3-7 turns may be most appropriate). After each turn, the program will let the player know how many of the activities were in the right spot. If after all turns, they do not correctly guess Milo’s schedule, they lose and Milo gets to live a life of mystery.

Milo’s possible activities:

  1. eating

  2. napping

  3. vandalism

  4. playing

  5. burglary

  6. sunbathing

For example, if Milo’s schedule is “eating, vandalism, playing, napping” then:

  • a guess of " vandalism, playing, burglary, sunbathing" has 0 exact matches.

  • a guess of " eating, vandalism, playing, napping " has 4 exact matches.

  • a guess of " eating, burglary, playing, sunbathing " has 2 exact matches.

1. print_activities

print_activities(activities):

This function takes one list, which will have four strings.

This function doesn’t return anything or modify the input list.

It should print the input list of activities with commas separating them.

For example, if the input list was ["vandalism", "playing", "burglary", "sunbathing"], the output should be

$ python3 milo.py
vandalism, playing, burglary, sunbathing

To Test: Try passing a list of activities to print_activities in main.

def main():

    test_list = ["vandalism", "playing", "burglary", "sunbathing"]
    print_activities(test_list)

Hint if you keep printing a comma at the end: A possible solution is to have an if statement to verify if you are on the last list item.

2. get_one_guess

get_one_guess(activity_num, all_activities):

The program should take one list and one integer as parameters. The list is provided in the main function of your starter code in milo.py.

The program should prompt the player for a valid activity from the all_activities list.

The function should repeatedly ask for an activity until the player enters a valid one.

Return the valid activity.

To Test:

def main():
  all_activities = ["eating", "napping", "vandalism", "playing", "burglary", "sunbathing"]
  guess = get_one_guess(1, all_activities)
  print("You guessed: %s" % (guess))

See the example code below (player input in bold).

$ python3 milo.py
Please choose from the following activities:
eating, napping, vandalism, playing, burglary, sunbathing
Enter activity 1: jumping
jumping is not a valid activity, Milo doesn’t know how to do that.

Please choose from the following activities:
eating, napping, vandalism, playing, burglary, sunbathing
Enter activity 1: napping

3. get_all_guesses

get_all_guesses(all_activities): The function takes in one list of all_activities, provided in main.

The function should get all 4 activity guesses from the user. Do this by using the get_one_guess function you have already made.

Users can repeat activities within their 4 activities, so you do not need to verify for repetition.

Store all 4 activities in a list.

Print the activities the user has guessed.

Return the guess list.

To Test:

def main():

  all_activities = ["eating", "napping", "vandalism", "playing", "burglary", "sunbathing"]
  guesses = get_all_guesses(all_activities)
  print("guess list is:  %s" % (guesses))
$ python3 milo.py
Please choose from the following activities:
eating, napping, vandalism, playing, burglary, sunbathing
Enter activity 1: jumping
jumping is not a valid activity, Milo doesn’t know how to do that.

Please choose from the following activities:
eating, napping, vandalism, playing, burglary, sunbathing
Enter activity 1: napping

Please choose from the following activities:
eating, napping, vandalism, playing, burglary, sunbathing
Enter activity 2: playing

Please choose from the following activities:
eating, napping, vandalism, playing, burglary, sunbathing
Enter activity 3: napping

Please choose from the following activities:
eating, napping, vandalism, playing, burglary, sunbathing
Enter activity 4: burglary

You guessed:
napping, playing, napping, burglary

4. make_schedule

make_schedule(all_activities):

The program should take one list as a parameter. This list is provided in the main function of your starter code in milo.py.

This function should return the list of Milo’s schedule for the game.

It will do this by selecting four of the 6 possible activities at random.

The activities must not duplicate.

You can use the choice function from the random library.

The choice function takes a sequence (e.g. a list) as input and returns a random element from the sequence. For example:

groceries = ["apple", "milk", "bagel"]
random_item = choice(groceries)

To Test: Call make_schedule in main. Try this several times to make sure different schedules are being produced each time make_schedule is called.

def main():

    all_activities = ["eating", "napping", "vandalism", "playing", "burglary", "sunbathing"]
    schedule = make_schedule(all_activities)
    print_activities(schedule)

Output example:

$ python3 milo.py
vandalism, playing, burglary, sunbathing

5. check_guess

check_guess(schedule, guess).

This function should take two lists. One list is the randomly generated schedule and the other is the user’s guesses for that round. It should return an integer that represents how many activities in the schedule the user guessed in the correct place.

To Test: have a set schedule and compare it to guess lists with varying accuracy. Does it correctly determine 0, 1, 2, 3, or 4 exact matches?

def main():
	schedule = ["vandalism", "playing", "burglary", "sunbathing"]
	guess = ["eating", "burglary", "eating", "sunbathing"]
	print(check_guess(schedule, guess))

Output example:

$ python3 milo.py
1

6. print_introduction , did_player_win, and check_num_turns

  • print_introduction(): Prints out the instructions to Milo’s Day.

  • did_player_win(num_exact_matches): Takes one integer. This function should return True if the player won the game. Winning the game requires four exact matches.

  • check_num_turns(): Prompts the user to input how many turns they want. This function needs to validate that the number is greater than 0 but can assume user input is an integer. Returns an integer.

To Test: try each one out in main. Does print_introduction display the instructions? Try did_player_win with different integers. Try check_num_turns with different user input, be sure to try negative numbers, 0, and positive numbers.

7. main()

The final game should do the following:

  1. Print out instructions to the player.

  2. Ask the player to choose how many turns they would like to have to try and guess the schedule.

  3. Generate Milo’s schedule

  4. Until the player guesses the schedule or runs out of turns:

    • Show the current turn number

    • Ask the player for a guess

    • Compute the number of exact matches

    • Print out the number of exact matches

  5. Check to see if the player won.

  6. If they win, congratulate them.

  7. If they lose, offer them condolences.

8. Requirements

The code you submit for labs is expected to follow good style practices, and to meet one of the course standards, you’ll need to demonstrate good style on six or more of the lab assignments across the semester. To meet the good style expectations, you should:

  • Write a comment that describes the program as a whole using a comment at the top of the file.

  • All programs should have a main() function.

  • Use descriptive variable names.

  • Write code with readable line length, avoiding writing any lines of code that exceed 80 columns.

  • Add comments to explain complex code segments (as applicable).

  • Write a comment for each function (except main) that describes its purpose, parameters and return value.

Your program should meet the following requirements:

  1. Your program should implement print_activities function with the output explained above (printing activities with each activity separated by a comma, no comma after the last activity).

  2. Your program should implement the get_one_guess function with the same number of parameters, the same return type, and the same behavior described above.

  3. Your program should implement the get_all_guesses function with the same number of parameters, the same return type, and the same behavior described above. Remember: it must use get_one_guess.

  4. Your program should implement the make_schedule function with the same number of parameters, the same return type, and the same behavior described above. Remember: activities must not duplicate.

  5. Your program should implement the check_guess function with the same number of parameters, the same return type, and the same behavior described above.

  6. Your program should implement the print_introduction function as described above.

  7. Your program should implement did_player_win with the same number of parameters, the same return type, and the same behavior described above.

  8. Your program should implement check_num_turns with the same number of parameters, the same return type, and the same behavior described above.

  9. Your program should implement a main function that plays one full game of Milo’s Day and prints the result (player guesses correctly and wins, player never guesses correctly and loses) at the end of the game.

9. Sample output

The output of your program does not need to perfectly match the example. However, all of the above functions should be implemented correctly.

$ python3 milo.py
Welcome to Milo's Day!

Milo the Cat does four activities every day.
He knows how to do six activities, but which four
did he do today, and in what order?

Your job is to figure out Milo's schedule.
After each guess, you will be told how many
activities are in exactly the right position.

Milo's possible activities are:
eating, napping, vandalism, playing, burglary, sunbathing

How many turns would you like? 4

Turn 1 of 4

Please choose from the following activities:
eating, napping, vandalism, playing, burglary, sunbathing
Enter activity 1: eating
Enter activity 2: dancing
dancing is not a valid activity, Milo doesn't know how to do that.

Please choose from the following activities:
eating, napping, vandalism, playing, burglary, sunbathing
Enter activity 2: vandalism
Enter activity 3: playing
Enter activity 4: eating

You guessed:
eating, vandalism, playing, eating
You have 1 exact matches.

Turn 2 of 4

Please choose from the following activities:
eating, napping, vandalism, playing, burglary, sunbathing
Enter activity 1: eating, burglary, vandalism, playing
eating, burglary, vandalism, playing is not a valid activity, Milo doesn't know how to do that.

Please choose from the following activities:
eating, napping, vandalism, playing, burglary, sunbathing
Enter activity 1: eating
Enter activity 2: burglary
Enter activity 3: vandalism
Enter activity 4: playing

You guessed:
eating, burglary, vandalism, playing
You have 2 exact matches.

Turn 3 of 4

Please choose from the following activities:
eating, napping, vandalism, playing, burglary, sunbathing
Enter activity 1: eating
Enter activity 2: playing
Enter activity 3: vandalism
Enter activity 4: burglary

You guessed:
eating, playing, vandalism, burglary
You have 3 exact matches.

Turn 4 of 4

Please choose from the following activities:
eating, napping, vandalism, playing, burglary, sunbathing
Enter activity 1: eating
Enter activity 2: playing
Enter activity 3: vandalism
Enter activity 4: napping

You guessed:
eating, playing, vandalism, napping
You have 2 exact matches.

Oh no! You didn't figure out Milo's schedule.
Milo gets to live a life of mystery!
His schedule was:
eating, napping, vandalism, burglary

10. Answer the Questionnaire

After each lab, please complete the short Google Forms questionnaire. Please select the right lab number (Lab 05) from the dropdown menu on the first question.

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, including your vscode editor, the browser and the terminal. Then click on the logout icon (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!