Computer Science 110
Foundations of Computing through Digital Media

Denison

CS 110 Lab Project 3

Creating Pictures through Recursion

Due: By 11:59 p.m. Monday, October 7th

In this lab, we will introduce Turtle graphics, a complement to the Graphics library we have been using thus far. The Turtle class builds on the Arrow shape provided in the Graphics library. Turtle graphics are particularly helpful in recursive functions that perform drawing, as they can perform a set of drawing operations that are relative to the notion of a "current position" on the drawing screen, and can avoid using parameters carrying information about the absolute and global coordinates in which we are drawing. We will use these in the Snowflake and the Binary Tree drawings, while we will see the contrast with absolute coordinates when we program Sierpenski's carpet.

Background: Turtle Graphics and a Template main() function

Start by going to the SHARED volume, and, under the Resources/lab03 subfolder, copy the Turtle.py file onto your local system, and in the same folder where you will be developing your Lab03 programs. If you haven't already, now would be a good time to create the folder named Lab03 that you will use for this assignment. Also go ahead and copy the turtleExample.py file in the same folder under Resources.

In turtle graphics, we start with a standard Window object. The coordinate system is as before, with (0,0) in the upper left corner and x increasing to the right and y increasing down. Coordinates and distances are again measured in screen pixels.

Now imagine a computer/robotic "turtle" starting at the center of the Window. Through Python, we can issue method invocations to this turtle, telling it to move forward, turn left or right by a certain number of degrees. As the turtle moves, the movement is animated, and the turtle draws a line showing the path of the given commands, as if the turtle has a pen associated with it. We can also issue other commands like setting the color of the pen, or its line width, and even raising and lowering the pen so that we can move the turtle without the associated drawing taking place.

Just to get a feel for this model, start by bringing up Calico and opening and running turtleExample.py:

from Graphics import *
from Turtle import *

win = Window('Turtle', 500, 500)
t = Turtle(win)

t.forward(100)
t.left(120)
t.width(3)
t.color('red')
t.forward(75)

t.up()
t.forward(25)
t.left(60)
t.down()
t.forward(50)
      

Experiment for yourself, by issuing additional method invocations in the shell. If you want to know the full set of functions available in the Turtle class, issue the help(Turtle) function invocation to the shell (after a from Turtle import * has already been issued). You can get the description for an individual function by invoking help(Turtle.forward), and replacing forward with the desired function.

Problem 1: Practicing with turtles and functions

Write a program in a file named polygon.py. The main() function should create the Window and the Turtle and then use function invocations to thoroughly demonstrate the functions specified in the list below.

  1. Write a fuction called square that takes parameters for a Window, win, and a Turtle named t. It should use the turtle to draw a square.
  2. Add another parameter, named length, to your definition of function square. Modify the body so the length of the sides of the square is length, and then modify the function call to provide the additional length argument. From your main() invoke the function multiple times from different locations and headings to demonstrate its correct operation.
  3. Next modify the main program to call the input function to get a length from the user, assigning to a variable. Use this length as the argument to the function invocation to square.
  4. Make a copy of the square function and change the name to polygon. Add another parameter named n and modify the body so it draws an n-sided regular polygon. Hint: The exterior angles of an n-sided regular polygon are 360.0/n degrees
  5. Write a function called circle that takes a Window, w, a Turtle, t, and a radius, r, as parameters and then draws an approximate circle by invoking polygon with an appropriate length and number of sides. Test your function with a range of values of r.

    Hint: First calculate the circumference given the radius. (Google if you don't remember the calculation for a circle's circumference.) Then compute length by observing that length * n should equal the circumference.

  6. Make a more general version of circle called arc that takes an additional parameter, called angle, which determines what fraction of a circle to draw. angle is in units of degrees, so when angle=360, arc should draw a complete circle. Note: if this one is giving you trouble, save it for later and move on to the recursive drawing problems described below. ... just don't forget to come back to this one before the due date.

Problem 2: Sierpinski's Carpet

Note:This first drawing problem does not need the Turtle class. The only drawing required is that of a Rectangle, so the Graphics library is sufficient.

Sierpinski’s carpet is defined as follows. A problem instance is defined by giving an (x, y) coordinate for the upper left corner of the instance along with a length of a side. Consider the window region defined by the problem instance (i.e. from (x, y) to (x+side, y+side)). Partition this square-sized region into 9 equal-sized smaller regions in a 3 by 3 region grid. Color in the middle region with a filled Rectangle. Recursively invoke Sierpinski’s carpet for the remaining 8 squares. The parameters to our function also require a depth variable, so that the base of the recursion can be determined when depth is zero; we start with depth at perhaps 4 or at most 5, and each recursive invocation decrements depth by one. Here is what you should get:

Create a new program called carpet.py. In the main function, set up for an 972 x 972 turtle screen. Even in the base case, the drawing of the center square is performed. Hint: My solution had a function header for the recursive carpet function as follows:

def carpet(depth, win, x, y, side):
This function has no return value.

Problem 3: Snowflake

Create a new program called snowflake.py. In the main function, set up for an 800 x 350 window. Create a Turtle object and set the pen width to 2, and the pen position to an initial position at coordinate (35, 275) (look for the moveTo() function in the documentation). Be careful to not let the pen draw as the position moves from the center of the screen to this initial position.

Create a function called snow() which returns nothing but is given a window, a turtle object and two ints called depth and length. This function should do one of two things.

Once you’ve got this, we can test it out. Try calling the function snow in your main function with parameters (win, t, 0, 729). (I picked 729 just because it is a power of 3, so when we do integer division by 3 repeatedly, we’ll still have the right integer). You should see a line drawn across most of the image. Reset and try this again, but this time change the initial value of depth to 1. This should add a kink to the middle of the line. Once you have this working, change your main function so that, from the top level, you make a total of six calls to snow, where you start with snow(win, t, 0, 729) and go up to snow(win, t, 5, 729), incrementing iteration by 1 each time. Between each of these top level calls, reset the pen position to the above starting position, and change the pen color so you can distinguish the lines.

A correct solution should look something like this:

Problem 4: Binary Tree

A Binary Tree is a tree where, at each branching point, we branch into exactly two directions. Binary trees are a great application of recursion, whether we are drawing the tree or have a data structure that utilizes the tree structure. In this case, I give you the picture of the desired result, but I want you to figure out how to use recursion to solve the problem of drawing a binary tree. As in the carpet recursion above, we can use a parameter for governing the depth of the recursion. Part of the problem solving is determining the set of parameters and finding a "consistent" relative position and heading that can be assumed as a precondition to any invocation of the tree() recursive function. Here is what you should get: