CS21 Lab 5: Snail Racing

Due 11:59pm Fri, March 1

Run update21, if you haven't already, to create the cs21/labs/05 directory. Then cd into your cs21/labs/05 directory and create the python program for lab 5 in this directory (handin21 looks for your lab 5 assignments in your cs21/labs/05 directory):


$ update21
$ cd ~/cs21/labs/05
$ pwd
  /home/your_user_name/cs21/labs/05

Your programs are graded on both correctness and style. Please review the comments regarding programming style on the main page.

For this lab we will continue using the Zelle graphics library and we will introduce the Snail library.

Snail Objects

In this week's lab, you will write a program that will simulate the exciting, fast-paced world of snail racing! You will write your snail racing program using functions, making use of a new Snail class.

Trying out the Snail class

Included in the lab05 directory is sample.py. This program shows you how to use the Snail class. You use Snails just like you used Circles from the graphics library (with an added name parameter in the constructor):

  1. To create a Snail called gary: gary = Snail(<centerPoint>, <radius>, <name>)
  2. To move gary the Snail: gary.move(<x_distance>, <y_distance>)
  3. To set the fill color of gary's shell: gary.setFill(<color>)
  4. To clone gary: speedy = gary.clone()
  5. To draw gary in a graphics window called win: gary.draw(win)
  6. The getRadius() and getCenter() methods also work, returning the radius of the Snail's big shell and the center Point of the Snail's big shell.
  7. The getName() method returns the name of the snail.
  8. The front_eye() method returns the Circle object that is the front-most (and lower-down) eye of the snail.

We're going to use front_eye() to help decide if a given snail has crossed the finish line!

Try running the sample.py program and play around with the Snails a bit until you are comfortable with how to use them.


Designing the snail race

Since this is the first time you've had to write your own functions, we're going to guide you closely on this lab, describing the functions you should be creating. In later labs, this part of the solution design will be up to you.

Here are the major steps that your program will need to accomplish. These are pretty much in order. Remember to test each function as you write them.

  1. Create a graphics window.
  2. Draw a starting line and a finish line in the graphics window.
    • Your snails will race from near the left side of the window to near the right side of the window.
    • To create the starting line and the finish line, write a function called draw_racing_lines(window, start, finish).
    • This function has three parameters: the graphics window you are drawing to, called window, the x-coordinate of the starting line start, and the x-coordinate of the finish line finish.
    • The function will draw the starting and finish lines in the window at the specified locations.
    • The function does not have a return value.
  3. Create and draw four snails of different colors on the starting line.
    • Create four snails using any four different colors you choose in a function called create_snails(window, start).
    • This function has two parameters: the graphics window you are drawing to, window, and the x-coordinate of the starting line.
    • When creating each snail, use the color (e.g., "blue") as the name of the snail. This will make it easier to say who has won the race.
    • The snails should be evenly spaced on the starting line (see below).
    • The snails can be whatever size and color you'd like as long as they all fit on the screen and don't overlap.
    • Put the four snails you created into a python list.
    • The list of snails that you created is the return value from this function.


  4. Ask the user which snail they think will win the race.
    • Write a function called get_user_pick(window, snail_list) that instructs the user to click on the snail they think will win the race.
    • Your function should get the mouse click, figure out the y coordinate of the click, and then determine which snail was selected.
    • Hint: int(cy/dy) should give you the index of the selected snail (0, 1, 2, or 3), if cy is the y-coordinate of the click point and dy is the height of the window divided by 4.
    • After the user selects a snail, display their choice to the graphics window (see movie below, and use the snail getName() method).
    • This function should return the name of the snail that was selected by the user.
  5. Race the snails.
    • Write a function called race(snail_list, end) that has two parameters, the list of snails snail_list and the x-coordinate of the finish line, end.
    • In this function, you will repeatedly perform the following actions in a for-loop:
      • Move each snail in your snail list forward (towards the finish line) by a random value. We suggest you use something like randrange(5) because this makes for a good race, but you can choose whatever random movement you'd like.
      • After moving all snails by a small random amount, check if the center of the front_eye of any snail is past the finish line. If so, return from the function.
      • Although you call return, this function has no return value.
      • Since you don't know how many steps it will take for the first snail to finish, have the for loop repeat for a large number of steps, say 2000, and simply return from the function when you notice that one snail has finished.
  6. Determine the winner of the race.
    • Because you returned from the race function, you know that at least one snail has crossed the finish line, but many snails may have in fact crossed the finish line and you need to figure out which snail has crossed the finish line by the largest amount.
    • Write a function called winner(snail_list) that takes the list of snails as its only parameter.
    • This function determines which snail has moved the furthest to the right in the graphics window.
    • The return value from this function is the name of the snail that won.
  7. Determine if the user made a correct guess.
    • Write one last function called display_results(user_pick, winner, window)
    • Display a Text Object message in the graphics window saying who won the race and if the user picked the winner.
    • Also instruct the user to click once more to close the window.


Sample images

You can make your snail race look however you'd like, but here's one idea of how your race may look....





Extensions
There are lots of opportunities for extending this lab (just for fun -- no extra points).
  1. Give the user $10 to start. On each race, let them bet $1. If they guess correctly, they win $4. Let them play 5 races. Or, let them play as long as they'd like until they go broke.
  2. Have the snails travel at different speeds so that some snails are more likely to win than others. Of the player bets $1 on a snail that's more likely to win, you pay them less than $4. For snails that are more likely to lose, pay the player more than $4 if that snail wins.
  3. Leave a slime trail behind the snail as it races.
  4. Make the snails have different sizes.
  5. Allow for races with an arbitrary number of snails (let the user decide how many).
  6. Draw horizontal lines to indicate the racing lanes and number each lane to make it easier to identify each snail.
  7. Let snails slip backwards or take a nap on the racetrack by letting zero and negative values be generated by your randrange function.
  8. Anything else you want! Be creative - but use functions while being creative!
Submit
Once you are satisfied with your programs, hand them in by typing handin21 at the unix prompt.

You may run handin21 as many times as you like, and only the most recent submission will be recorded. This is useful if you realize, after handing in some programs, that you'd like to make a few more changes to them.