LEAD Computer Science - Lab 3

Due: Thursday, July 19 at 8pm

Please complete all parts of this lab in a file called lab3.py. When you are finished, run the test script (see below) and if you're satisfied that everything is working correctly, submit the file on csman for Lab 3.

This assignment should not take too long, but it will serve as a "warm-up" for lab 4, which will involve drawing more complex figures as well as using recursion.

Introduction to turtle graphics

Computer graphics is an interesting and useful application area for computer programming. There are many ways to do computer graphics in Python, but the easiest way is using what is called "turtle graphics". In turtle graphics, a window is displayed along with a shape called a "turtle" (it doesn't have to look like a turtle) that moves around the window and draws lines as it moves. We say that the turtle controls a "pen" which draws the lines. The pen can be down (drawing lines) or up (not drawing lines) and the pen can have any color the programmer wants. The programmer can control where the turtle moves, what color gets drawn, whether closed shapes get filled with colors, and so on. Using only a small number of commands, you can create very interesting and complex images.

On a computer graphics display, we measure distances in "pixels", which are very small squares of a single color. Pixels aren't always the same size on every computer, but we will still measure distances as some number of pixels. The window uses an X-Y coordinate system like you've seen in math classes; the origin of the coordinate system is in the center of the window. The "turtle" starts at the origin and is initially pointing to the right.

Here is a very simple example of a program which draws the outline of a red square in a window:

  from turtle import *

  # Set the pen's color to red.
  pencolor('red')  

  # Go 100 pixels to the right (in the direction the turtle is pointing).
  forward(100) 

  # Turn the turtle 90 degrees to the right.
  right(90)

  # Go another 100 pixels forward.
  forward(100)

  # Turn right again.
  right(90)

  # Do this two more times.
  forward(100)
  right(90)
  forward(100)
  right(90)

  # Now we've drawn a square in the window, and the turtle is back
  # where it started.

This will display the following image:

./img1.jpg

Note the shape of the turtle (the little arrow-shaped thingy in the center). You should type this program into Python to see what it does. Note that we could simplify it like this:

  from turtle import *

  pencolor('red')  

  for i in range(4):
      forward(100) 
      right(90)

Type this program in too. To clear the screen, use the clear() command. If you don't want to see the turtle type in the hideturtle() command. Most of the pictures below have the turtle hidden.

You may have noticed the line:

  from turtle import *

We've told you in lecture to avoid using the from <module> import * form in your code. Usually this is the case, but here we need to use a lot of functions from the turtle module, and it would be a nuisance to write e.g. turtle.forward(100) instead of just forward(100). There are no absolute rules in programming!

If you wanted to fill the square with the red color, you could do it like this:

  from turtle import *

  pencolor('red')  
  fillcolor('red')  # set the fill color to red
  begin_fill()  

  for i in range(4):
      forward(100) 
      right(90)

  end_fill()       # fill the square with red

Again, try this out.

One very important thing to be aware of when using turtle graphics is that if you don't set a particular value (say, the pen color) it will use a default value (for the pen color, it will be black by default). So you don't have to specify everything if the default values are what you want. Also, if you change a value, it stays in effect until you change it again. So if you change the pen color to red, the pen will always draw red lines unless you change the pen color again. Some of the functions below require you to specify the pen color, and others don't. If not, don't worry about it! Similarly, if you turn the turtle so it's pointing straight up, it will always draw lines in that direction until you turn it again.

Useful functions in the turtle module

Here are the functions you will be using. You should spend a little time experimenting with them by using them to draw very simple drawings so that you know what they do. You can also read the Python documentation on the turtle module, which is located here.

Random colors

Some functions will need the ability to get a random color. The random_color function below will return a random string which can be used as a color name. You should type it into your program file, and don't forget to import random at the top of the file.

  def random_color():
      '''Returns a random RGB color string.'''
      r = random.randint(0, 255)
      g = random.randint(0, 255)
      b = random.randint(0, 255)
      return '#%02x%02x%02x' % (r, g, b)

Basic exercises using turtle graphics

In the following functions, make sure that nothing gets drawn on the screen except what is asked for. Using the penup and pendown functions judiciously will make this much easier. Make sure that the pen is always up when your functions return.

  1. Write a function called draw_polygon that draws polygons with any number of sides and any color. It takes 4 arguments, which are (in order): the number of sides, the length of each side (all sides are the same length), a string representing the color, and a boolean value which is True if the polygon is filled or False if it isn't. For instance, the function call draw_polygon(5, 100, 'blue', False) will produce this image:

    ./test1.jpg

    And the function call draw_polygon(7, 100, 'red', True) will produce this image:

    ./test2.jpg

    You can even use this function to draw circles if the polygon has enough sides (it won't technically be a circle, but your eyes won't be able to tell the difference). The function call draw_polygon(90, 10, 'green', True) will produce this image:

    ./test3.jpg
  2. By making a tiny change to the previous function, write a function called draw_star which draws star shapes. This function will have the same arguments as draw_polygon. It will only work properly for odd numbers of sides (why?). For instance, the function call draw_star(11, 100, 'red', False) (an 11-pointed star) will produce this image:

    ./test4.jpg
  3. Write a function called draw_square that draws squares that are centered on the turtle's location when the function is called. The turtle should return to its original position and direction at the end of the function too.

    Note that this is more complicated than the code for drawing squares given above, because you have to move the starting point of the drawing to keep the square centered properly. This should work regardless of what direction the turtle is facing. The function takes three arguments: the color, the side length, and a boolean value which is True if the square is filled or False otherwise. For instance, if the turtle's orientation is facing the lower-right-hand corner (rotated 45 degrees right from its original orientation), the function call draw_square('red', 100, True) will produce this image:

    ./test5.jpg

    The orientation of the square isn't specified in the function call; it's just whatever direction the turtle was pointing in when the function was called. If you like, you can use showturtle() to remind you of what this direction is. The dot function can also be useful for debugging; it will draw a black dot at the current location of the turtle. Try debugging it using unfilled squares so you can see the dot.

  4. Write a function called rotated_squares which will draw a series of squares all centered at the starting point of the turtle, but where each one is rotated relative to the previous one so that the squares rotate 360 degrees in all. The arguments are: the square color, the number of squares to draw, and the length of the sides of the squares. For instance, the function call rotated_squares('red', 10, 200) will produce this image:

    ./test6.jpg

    Use the draw_square function in your definition of rotated_squares to simplify the code. (This is much simpler than duplicating the code from draw_square in this function!)

  5. Write a function called square_spiral which will draw a spiraling shape with 90 degree angles. It has three arguments: the number of sides, the initial side length, and the amount the side length decreases every turn. For instance, the function call square_spiral(40, 400, 10) will produce this image:

    ./test7.jpg

    Don't bother trying to center the spiraling shape at the origin; just start it at whatever location the turtle is at.

  6. Write a function called draw_random_squares which will draw a number of randomly-colored, randomly-sized, and randomly-located squares in the window. It will take six arguments:

    1. the number of squares to draw
    2. the lowest location in the x or y direction where the squares can be centered on
    3. the highest location in the x or y direction where the squares can be centered on
    4. the smallest allowable side length of a square
    5. the largest allowable side length of a square
    6. a boolean value which (if True) says that the squares should be filled with the same color as their outline, or (if False) says that the squares should not be filled (outline only)

    Each square to be drawn has a random color, a random X-Y position, and a random side length. Each square will have a different random color, position, and side length. Here's how you figure out these values:

    1. Use the random_color() function above to compute a random color.

    2. The lowest and highest location values are used to randomly choose the center location of the square (using the random.randint function we talked about in class). Choose a random X coordinate and a random Y coordinate, and that will be the location of the center of the next square to be drawn.

    3. The lowest and highest side length values are used to randomly choose the length of the side of the next square to be drawn.

    The function call draw_random_squares(50, -300, 300, 50, 200, False) might generate an image like this:

    ./test9.jpg

    The function call draw_random_squares(50, -300, 300, 50, 200, True) might generate an image like this:

    ./test10.jpg

    Note that the first image has unfilled squares while the second one has filled squares. Each image has 50 squares. The centers of the squares are located in the X-Y plane between location -300 and 300 in both the X and Y directions. Each square has a side length no smaller than 50 pixels and no larger than 200 pixels.

    This problem should again use the draw_square function to draw the squares themselves.

Testing your functions

We're supplying you with a test program called turtle_tests.py which you should download and put into the same directory as your lab3.py file. You can run the tests by typing this at the terminal prompt:

  python turtle_tests.py

If you've defined the functions properly, this program will show a series of windows and images in the windows which look like the pictures above (the randomly-generated ones won't look exactly like the pictures above, but they will be similar). If you've forgotten to define a function, it will also notify you of that. The test program won't try to determine if the output from your program is correct or not; for that, look at the pictures above and see if your functions' output looks similar.

Submission

Once you have completed this lab, submit lab3.py for Lab 3 on csman. Do not submit the turtle_tests.py file.


Copyright (c) 2012, California Institute of Technology. All rights reserved.