And more turtle!
Let’s take stock of what we’ve looked at so far.
General programming ideas:
For
loopsinput()
/print()
Last week we were looking at this function and deciding whether it was (1) correct and (2) efficient :
def isEven(value): numbers = list(range(0, 100)) # List all the numbers from 0, 99) odd = False for num in range(0, 100): # Remove every other number starting with the second one. if odd: numbers.remove(num) odd = not odd if value in numbers: # Check to see if the number is still in the list. return True else: return False
And perhaps antoher question to ask is: (3) is it easy to understand?
One of your classmates suggested we use the modulo operator %
for a better solution.
def isEven(value): if value % 2 == 0: return True else: return False
We use the ==
operator to compare values.
Is it correct, efficient, and easy to understand?
Let’s try it in IDLE!
Here we see a new structure we haven’t discussed yet: the conditional statement.
So far, our turtle programs, when run, execute every statement beginning from the top to the bottom, sometimes with a loop over a block of statements.
The if
keyword allows the program we write to make a decision whether to execute some statement or not during runtime.
Syntax:
if {boolean expression}: (1) Some statement (2) Another statement in the block (3) A statement outside of the block
If the boolean expression is true
, statements (1), (2), and (3) are executed. If false
, only (3) is executed.
We can also specify some alterative behavior if the boolean expression is false:
if {boolean expression}: Some statements else: Some alternate behavior
Before we make use of the conditional structure in a turtle program, let’s discuss one more idea:
A nested loop is a loop within another loop.
Try this in IDLE
for i in range(0, 3): for j in range(0, 5): print("i=", i, "j=", j)
What do you expect will happen?
for i in range(0, 3): for j in range(0, 5): print("i=", i, "j=", j)
Notice that the second for
statement is inside the block of the first for
statement.
Recall an earlier program we looked at: PolygonSides.py
import turtle shape = turtle.Turtle() num_sides = int(input("How many sides do you want on your shape?")) #num_sides = 6 # We don't need this line anymore! side_length = 200/ (num_sides * .5) # What does this do? pen_width = 3 color = 'orange' angle = 360.0 / num_sides for i in range(num_sides): shape.width(pen_width) shape.color(color) shape.forward(side_length) shape.right(angle) turtle.exitonclick()
This program asked the user to specify the number of sides they wanted for their regular polygon.
Suppose instead of a “side” drawn on each side of a polygon, we want to draw a polygon on each side. How do we modify our code to make it do that?
The basic idea is that we can use nested loops to achieve the desired effect. We can modify our loop to include another loop. The outer loop moves the turtle to each “side” while the inner loop draws the polygons at each “side.” Let’s try it.
for i in range(num_sides): shape.right(angle) shape.forward(side_length) for j in range(num_sides): shape.width(pen_width) shape.color(color) shape.forward(side_length) shape.right(angle)
Here’s the code with that modification: Polygons with nested loop
import turtle shape = turtle.Turtle() num_sides = int(turtle.numinput("Number of Sides", "How many polygons do you want?", 4)) #num_sides = 6 # We don't need this line anymore! side_length = 200/ (num_sides * .5) # What does this do? pen_width = 3 color = 'orange' angle = 360.0 / num_sides for i in range(num_sides): shape.right(angle) shape.forward(side_length) for j in range(num_sides): shape.width(pen_width) shape.color(color) shape.forward(side_length) shape.right(angle) turtle.exitonclick()
Let’s run it and see what happens!
What if we don’t want a polygon on every side? Instead, let’s draw a rosette on each even side.
A rosette is a small decoration, usually circular in shape or with circular patterns. I gave you an example earlier that drew a rosette: Circles.py
import turtle t = turtle.Pen() turtle.bgcolor("black") t.speed(40) # Set turtle drawing speed colors=['deep sky blue', 'orange red', 'purple', 'yellow', 'cyan', 'green', 'deep pink', 'navy', 'lavender', 'aquamarine', 'pink', 'gold'] sides = int(turtle.numinput("Number of sides", "How many spiral sides?", 4, 1, 12)) for m in range(0, 120): t.pencolor(colors[m % sides]) t.left(360/sides + 20/sides) t.width(m//25+1) # // is floor division t.penup() t.forward(m*20/(1.2*sides)) # Scale for number of sides t.pendown() if (m % 2 == 0): # Draw a rosette at each even corner for n in range(sides): t.circle(m/3) t.right(360/sides) else: # Draw a polygon at each odd corner for n in range(sides): t.forward(m/2) t.right(360/sides) turtle.exitonclick()