Lab 8 - More Functions with Turtle Graphics

Directions for Labs


  • Submit your completed lab file online to CourSys (not Canvas). Labs are marked on completion, not correctness, so complete each part to the best of your ability and learn!
  • It is recommended that students attend in-person lab sections for lots of help!
    • If you would like to attend an in-person lab section, you are welcome to come to any (or more than one) lab section.
    • There is no need to attend the section you are enrolled in.
    • There is no need to attend any lab sections: there is no attendance taken.
    • You can complete the lab on your own time or own computer if you like.
  • While completing these labs, you are encouraged to help your classmates and receive as much help as you like. Assignments, however, are individual work and you must not work with another person on assignments.


Part 1) Print factors


  1. Inside your cmpt120 folder, create a new folder for lab8 and make a lab8.py file.
    • See lab 1 for more detailed directions.
  2. Create a fruitful function which asks the user to enter a number (an integer) between 1 and 20 inclusive.
    • If the user enters a value less than 1, or greater than 20, print an error message and have the user enter a new value.
    • Once the user enters a valid integer, return the value.
    • In your calling "main" code, call your function and store the value in a variable named num.
    • For now, just print num in your calling code (we'll use it in the next steps).
    • Hint - return and receive: Your function must return the value the user entered, and your calling code must store the return value into a variable.
    • Hint - No print: Your function should not print the number the user entered: we'll have the calling code print it for the moment.
    • Hint - While: Ues a while loop in your function to ensure the user's input is valid.
    • Sample output:
      Enter a number: -1
      Number must be between 1 and 20        
      Enter a number: 22
      Number must be between 1 and 20        
      Enter a number: 16
  3. Create a fruitful function named is_divisible(...) which accepts two integer arguments name num and div.
    • Return True if num can be evenly divided by div. Otherwise, return False.
    • Hint - mod: Remember that you can check if A is divisible by B with: if A % B == 0:...
    • Hint - Code: Here is some code that works (but can be improved! See next 2 hints):
      
      def is_divisible(num, div):
          if num % div == 0:
              return True
          else:
              return False
      
      
    • Hint - no if: Rather than using an if statement, you can just return the Boolean expression.
    • Improvement - Better Code: Here is some better code. It just uses the expression directly and saves us some logic. Any time your if statement just returns True/False, you likely want to do this:
      
      def is_divisible(num, div):
          return num % div == 0
      
      
  4. In the "main" code, create a loop to print out which integers between 1 and num (inclusive) divide evenly into num (i.e., for which is_divisible() is True)
    • Hint - for range: Create a for loop in the "Main" area (outside of any function) which has a range of range(1, num + 1)
    • Hint - code: The full code in the "main" area may look like:
      
      num = read_number()
      for i in range(1, num + 1):
          print(f"Is {i:2} a factor of {num:2}? {is_divisible(num, i):2}")
      
      
    • Sample output:
      Enter a number: 12
      Is  1 a factor of 12?  1
      Is  2 a factor of 12?  1
      Is  3 a factor of 12?  1
      Is  4 a factor of 12?  1
      Is  5 a factor of 12?  0
      Is  6 a factor of 12?  1
      Is  7 a factor of 12?  0
      Is  8 a factor of 12?  0
      Is  9 a factor of 12?  0
      Is 10 a factor of 12?  0
      Is 11 a factor of 12?  0
      Is 12 a factor of 12?  1
  5. Print only the factors of num.
    • Change your calling code's loop to only print the factors of num, rather than printing all numbers between 1 and num.
    • Hint - if: use an if statement such as:
      
      if is_divisible(num, i):
          print(f"Factor: {i}")
      
      

Part 2) Draw Factors

  1. Add the necessary code to do turtle graphics
    • This includes the import, declaring your turtle, and likely holding the window open until click.
    • You may want to speed up the drawing with: picasso.speed(0)
  2. Create a function to draw a rectangle.
    • Pass in (arguments) a the location of the lower-left corner: x, y.
    • Also pass in (arguments) the width and height of the rectangle.
    • Use turtle graphics to draw the rectangle up and to the right of the lower left corner (x,y).
    • Hint - Function: 1st line of function definition might be: def draw_rectangle(x, y, width, height):
    • Hint - Turtle: Use the turtle .penup(), .pendown(), and .goto(...) functions to move around and control drawing. Or, instead of using goto(...) you can also draw with the pen down by turning the turtle and moving forward.
  3. Draw a rectangle for each factor.
    • For each factor h compute w such that h * w == num. For example, if num is 12 and h is 3, then w would be 4.
    • Draw a rectangle starting at (0,0) with height h * 30 and width w * 30.
    • For example, for num = 5 there will be two boxes. One for 5x1 and the other for 1x5. Each dimension is multiplied by 30 pixels so the two boxes will have height and width of 150x30 and 30x150 pixels.
    • Hint - Integer Division: For all h where is_divisible(num, h) is true, height is h * 30; width is (num // h) * 30
    • Example (OK to end up with the turtle in any position).
      Example rectangles
  4. Create a function named draw_message(...) which writes some text at location (x,y).
    • Pass in (argument) the x and y locations, plus a message.
    • Move to that location and then use my_turtle.write(message)
    • Remember to use penup() and pendown() as needed.
    • Hint - Function Definition: Use the following 1st line of the function: def draw_message(x, y, message):
  5. Add messages to your drawing
    • For each factor rectangle, write beside it the numbers for its size. For example, with num = 10, you'll have boxes labeled "1x10", "2x5", "5x2", and "10x1". OK to have numbers in opposite order. Labels may be placed anywhere on the rectangles that it is clear.
    • For the entire graph, write "Factors of {num}" using your draw_message(...).
    • Sample output with labels
      Example rectangles
  6. Refactor your code to put the calling code from the "main" area into is own function.
    • Suggested function draw_factors(num)
    • Your code in the "main" area should look like:
      num = read_number()
      draw_factors(num)

Part 3) Draw a Parabolic Curve


  1. We will be drawing the following figure.
  2. Comment out the calls to the above code.
  3. In the "main" area, loop through lines:
    • Setup a variable named SIZE to be 300.
    • Setup a loop going from 0 to the SIZE (inclusive) in steps of 10. Name the variable offset
  4. In the loop, draw the lines for the top half of the figure:
    • Hint - use goto(x,y): When you know the coordinates, it's easiest to use my_turtle.goto(x, y) rather than trying to move forwards/backwards and turning.
    • Hint - Left: Start on the left at position (-SIZE + offset, 0); use my_turtle.goto(x,y).
    • Hint - Middle: Move to the middle point at position (0, offset).
    • Hint - Right: Move to the right point at position (SIZE - offset, 0)
    • Hint - Pen up/down: Put the pen up before moving to the starting position without drawing. Put the pen down to start drawing when doing goto(...) operations.
    • Test your code: you should see the top half of the figure.
  5. Do the same for the bottom lines.
  6. Move your code to draw the shape into a well named function.
  7. Now pass in an (x,y) parameter to the function so you can draw your shape on the screen in a different location.
    • Remember to add +x and +y as needed to where the turtle will move.
    • Have your code draw a total of two of these shapes.
  8. Optional: Convert your code which draws the parabolic curved shape to use a while loop over a for loop.
    • A for loop is easier for this situation; however, it's possible to use a while loop. Give it a try.

Submission


Uncomment all your code before submitting.

Submit your lab8.py file to CourSys by Sunday midnight. Remember you can submit up to 3 days late with no penalty if needed (but please plan to get it done on time to stay up to date on the course!)

Topics Covered

  • Designing with functions
  • DRYing out code using functions
  • Functions calling functions
  • Fruitful functions
  • While loop
  • Draw the + straight line figure