CS 151: Project #3

Grids and Mosaics

The purpose of this project is to give you more practice in designing and writing an algorithm. The focus of the assignment is to integrate the use of conditional expressions and iteration control structures.

Tasks

The goal of this project is to write a program to interpret strings of characters as different shapes. The individual shapes can be whatever you like. Your programs will draw the shapes along a horizontal line and in a 2D grid.

  1. Create a new file in BBEdit, or whatever editor you wish to use. Save the file with your username followed by an underscore character as a prefix. In other words, I would call my file bmaxwell_shapes.py. All of the functions you create for drawing shapes should go into this file. Put only functions into this file, no top level code. You will never run this file directly, only import it into other files. You should only need to import turtle into this file.
  2. Create three functions. Each function should draw a different shape with the constraints given below. Make these shapes very simple (like a line at a particular angle) to start with. You can make them more interesting later.
    • The name of each shape function should begin with your username followed by an underscore character. So my functions might be something like bmaxwell_square(), bmaxwell_circle(), and bmaxwell_teapot(). You should use descriptive names.
    • Each function should draw the shape based on the turtle location and orientation (no parameters). You can use a different color for each shape.
    • Each shape should fit into a 20x20 area with the point (x, y) being the lower left corner of the 20x20 area.
    • The position of the turtle should be the same at the end of the function as it was at the beginning.
    • The orientation of the turtle should be the same at the end of the function as it was at the beginning. One way to guarantee that is to store the value of the turtle orientation at the start of the function and the reset it at the end.

          # get the current position and heading of the turtle
          # note that the function returns a value 
          x, y = position()
          originalOrientation = heading()
      
          # draw stuff here
      
          # reset the turtle heading and position
          up()
          setheading(originalOrientation)
          goto(x, y)
          down()
      
  3. Create a new file called linear.py. This file will create the first scene. You will need to import turtle, turtleUtils, and your shapes into this file.
  4. In linear.py, create a function called main() that takes no arguments. To start with, just have the main() function print out something. At the bottom of the file put a call to main() at the top level (not tabbed in). Now the only code at the top level is a call to the main() function. Everything else with either be in the main function or in other functions we define. Test your linear.py program.
  5. Now use the main() function to test the shape functions you just wrote. Use the turtleSetup() and turtleWait() functions to create and hold open a window. Then call each shape function once at different locations. Test the linear.py program.
  6. In linear.py, define a function called processString(). It should have one parameter, which will be a string. Write a for loop that iterates over the elements of the string and just prints them out for now. Add a call to processString() to your main function and test linear.py. Pass a string to processString() and make sure it does the right thing (prints out all of the elements of the string).

    The structure of your program at this point should be as follows.

    def processString( aStringParameter ):
        for char in aStringParameter:
            print char
    
    def main():
        processString( 'some string to test' )
    
    main()
    

    Run it and see what happens.

  7. Pick three characters, one for each of your shapes. In linear.py define a function drawShape() that takes in a character as its parameter and draws the appropriate shape at the current turtle location. If the character is not one of the three, it should print out a message apologizing for not knowing what to do.
  8. Before the for loop in processString(), put the turtle on the far left side of the window. Then modify the for loop in the processString function so that it calls drawShape() on each character (instead of printing out the character) and then moves the turtle forward by 20 pixels (without drawing). Test linear.py by passing a string with several of the selected characters in it. It should create a series of shapes along a line. Try out several strings of different length with different characters.
  9. Create a new file grid.py. Structure it similarly to linear.py with a main() function and a processString() function. The main() and drawShapes() functions will be identical in the two files (so use copy and paste).
  10. Code the processString() function so that the shapes appear in a grid with 10 shapes in each row (possibly fewer on the last row). There are a number of different ways to do this. One approach is to have nested for loops. The inner for loop would count across the ten column locations, shifting the turtle horizontally on each loop; the outer loop would count across however many rows are appropriate given the string, shifting the turtle vertically each time through the loop. Whatever you do, write out your algorithm first in regular English and walk through it by hand. Once you have written your algorithm in python, test it on several different cases.

    One way to think about making a grid is that it is exactly the same as making a line except that every 10 shapes you move the turtle to the start of the next line. There are two things that may be useful here. First, you can use a for loop to iterate over the characters in a string or you can iterate over the indexes of the characters in the string. In one case your loop variable contains each character of the string in succession. In the other case the loop variable contains the indices of the characters in succession. You can see the difference by testing the following examples. Both examples will print out the same thing.

    mystring = "abcdef"
    for char in mystring:
        print char
    
    for i in range( len(mystring) ):
        print mystring[i]
    

    If you use the second method, then the variable i holds the index of the shape you are drawing. If you want to move back to the beginning of the row after each ten shapes, then you want to test for when i is 9, 19, 29, 39, and so on. The modulo operator (or remainder operator) is your friend in this case.

  11. Now go back and make some interesting shapes to draw (still following the rules). Create a scene with linear.py using a string with at least 20 characters in it. Capture an image and save it as sceneA.
  12. Create a scene with grid.py using a string with at least 30 characters in it. Capture an image and save it as sceneB.
  13. Get together with one other person. Create a copy of your linear.py file called linear2.py. Then modify linear2.py so that you import your partner's shapes.py file as well as your own. Modify your drawShape so that it checks for six characters. Then create a third scene using both your and your partner's shapes and save it as sceneC.

Extensions

Below are some suggested extensions. Focus your extensions on the use of conditionals and iteration to make the results more interesting.

  1. Use loops to create patterns other than simple grids.
  2. Extend the conditional to allow for more shapes of your own.
  3. Work your partner's shapes into your grid scene as well as the linear scene.
  4. Allow the insert of skips into the scene using a space in the string.
  5. Add colors to the shapes, random or structured.
  6. Create a mosaic by passing in an appropriately structure string. (The only difference in shapes might just be there color)

Writeup

Create a web page for your writeup. Your writeup should include the following.

Handing in

When your writeup is ready for viewing and linked to your index page, send me an email.

To hand in your python code, place it on the Academics fileserver in the private folder. Do not post it on the web. You may include snippets from your code in your writeup to demonstrate how certain aspects of the function work, but please do not include the whole thing.

To place the code on the fileserver, go to the server fileserver1 and select the Academics volume. Within that there ought to be a CS151 folder, and within that there should be a folder with your username, and within that ought to be a folder labeled private. You can read and write files to the private directory and I can read them, but no one else can access them. Put your python files (at least three) in that directory to hand them in.