I am trying to create a loop that takes an input by a user and draws however many squares but it increases the size of the squares with each loop, however 2 sides are stay connected. I'll include the graphic to better explain.
import turtle
squares = 1
while squares >= 1:
squares = int(input('How many squares would you like drawn?:'))
if squares == 0:
print("You must have at-least 1 square.")
squares = int(input('How many squares would you like drawn?:'))
else:
for count in range(squares):
turtle.forward(30)
turtle.left(90)
turtle.forward(30)
turtle.left(90)
turtle.forward(30)
turtle.left(90)
turtle.forward(30)
turtle.left(90)
turtle.done()
The input request and the drawing logic ought to be separated.
Here is one approach that returns the turtle at the start at each turn, after increasing the side length.
import turtle
num_squares = 3
t = turtle.Turtle()
t.pendown()
side = side_unit = 30
while True:
try:
num_squares = int(input('input the number of squares'))
except ValueError:
print("please enter an integer")
if num_squares > 3:
break
for sq in range(1, num_squares + 1):
t.left(90)
t.forward(side)
t.left(90)
t.forward(side)
t.left(90)
t.forward(side)
t.left(90)
side = side_unit + 3 * sq # increase the size of the side
t.goto(0,0) # return to base
turtle.done()
While waiting for #ReblochonMasque's solution to finish drawing 100 squares, there's plenty of time to implement an alternate, faster solution based on stamping.
The first thing to note is in the provided instructions it says to draw 100 squares to create the design in the figure, but that figure consists of just under 50 squares. It's also been scaled in some non integral fashion which makes it appear to have different line thicknesses.
Let's focus on the spirt of the problem rather than the example. The OP had a 1 square minimum so I've preserved that. This solution also naturally tends to center the square on the window:
from turtle import Turtle, Screen
DELTA = 3
MINIMUM = DELTA * 2
CURSOR_SIZE = 20
num_squares = -1
while num_squares < 1:
try:
num_squares = int(input('Input the number of squares: '))
except ValueError:
print("please enter an integer.")
if num_squares < 1:
print("You must have at least 1 square.")
screen = Screen()
turtle = Turtle("square", visible=False)
turtle.fillcolor("white")
for size in range(((num_squares - 1) * DELTA) + MINIMUM, MINIMUM - 1, -DELTA):
turtle.goto(turtle.xcor() + DELTA/2, turtle.ycor() - DELTA/2)
turtle.shapesize(size / CURSOR_SIZE)
turtle.stamp()
screen.exitonclick()
This is clearly not the kind of solution the OP was looking for, but maybe next time a problem like this comes up, it might be one the OP will at least consider.
Related
I need help turning polygon shapes (triangle and square) in Python turtle to match a picture.
Below I am trying to copy the image.
I specifically need help on what to add to my code given the triangle and square to have them repeat outwards like the picture. Because as of now the triangles and squares look like this (pentagon code is correct and works) All help is appreciated. Thank you.
import turtle
def polygon(turtle, side, length):
turtle.color("Blue")
for i in range(4):
turtle.backward(length)
turtle.left(side)
def polygon1(turtle, side1, length):
turtle.color("Green")
for i in range(3):
turtle.left(side1)
turtle.forward(length)
def polygon2(turtle, side2, length):
turtle.color("Red")
for i in range(5):
turtle.forward(length)
turtle.left(side2)
def main():
my_turtle = turtle.Turtle()
wn = turtle.Screen()
Bill = turtle.Turtle()
length = 100
side = 90
side1 = 120
side2 = 72
Bill.pensize(5)
Bill.speed(0)
#Pentagons
Bill.pu()
Bill.right(180)
y = -45
for i in range(5):
Bill.pu()
Bill.goto(60, y)
Bill.pd()
polygon2(Bill, side2, length)
y -= 20
#Triangle
Bill.pu()
Bill.left(240)
x = 45
for j in range(5):
Bill.pu()
Bill.goto(10, x)
Bill.pd()
polygon1(Bill, side1, length)
x += 20
#Square
Bill.pu()
Bill.left(240)
b = 6
for b in range(5):
Bill.pu()
Bill.goto(148, b)
Bill.pd()
polygon(Bill, side, length)
b -= 20
wn.exitonclick()
if __name__ == '__main__':
main()
pentagon code is correct and works
I don't believe the pentagon code is correct nor that you're approaching this in the correct way. The inner three shapes should form an equilateral triangle -- yours don't as you're eyeballing instead of calculating. Instead of trying to get the turtle to be in the right spot, why not have the turtle move forward in the direction of the sides of this central triangle, drawing polygons as it goes.
That is, embrace the drawing as a whole rather than trying to divide and conquer.
We'd need to make sure the polygon drawing code restores the turtle's state when it's done, so it can simply move forward to the next polygon. We'll need to make explicit which numbers are arbitrary, and which are calculable. Although the original diagram appears to use at least three turtles to achieve it's result, we'll do it with one as you attempted:
from turtle import Turtle, Screen
SHAPES = [(5, "Red"), (3, "Green"), (4, "Blue")]
LENGTH = 100
DELTA = 20
REPLICATIONS = 5
THICKNESS = 5
HEIGHT = (3 ** 0.5 / 2) * LENGTH # assumes 3 shapes, should fix!
DIVISIONS = 360 / len(SHAPES)
def polygon(turtle, sides, color):
turtle.color(color)
turtle.left(90)
turtle.forward(LENGTH / 2)
for _ in range(sides):
turtle.right(360 / sides)
turtle.forward(LENGTH)
turtle.backward(LENGTH / 2) # restore turtle to original state
turtle.right(90)
wn = Screen()
bill = Turtle()
bill.speed('fastest')
bill.pensize(THICKNESS)
bill.penup()
for offset, (sides, color) in enumerate(SHAPES):
bill.setheading(-DIVISIONS * offset - 90)
bill.forward(HEIGHT / 3) # assumes 3 shapes, should fix!
for _ in range(REPLICATIONS):
bill.pendown()
polygon(bill, sides, color)
bill.penup()
bill.forward(DELTA)
bill.home()
wn.exitonclick()
QUESTION: Implement the following pseudo-code to draw a checkered flag to the screen.
1. Ask the user for the size of the checkered flag (n).
2. Draw an n x n grid to the screen.
3. For i = 0,2,4,...,62:
4. row = i // n
5. offset = row % 2
6. col = (i % n) + offset
Please copy and paste the link see the output:
I implemented the pseudocode, but I need some help. I can able to draw the n*n grid; moreover, I am keep getting this error: NameError: name 'row' is not defined
My program:
from turtle import*
def size():
size = eval(input("Please enter the size of the checkered flag: "))
return size
def draw(n):
wn = Screen()
wn.setworldcoordinates(-1,-1,10,10)
pen = Turtle()
for i in range(0,n+1):
pen.up()
pen.goto(0,i)
pen.down()
pen.forward(n)
pen.left(90)
for i in range(0,n+1):
pen.up()
pen.goto(i,0)
pen.down()
pen.forward(n)
def findGrid(n):
for i in range(0,63):
row = i // n
offset = row % 2
col = (i % n) + offset
return row, col
def fillSquare(x,y):
pen = Turtle()
pen.hideturtle()
pen.speed(10)
pen.up()
pen.goto(x,y)
pen.fillcolor("black")
pen.begin_fill()
def main():
x = size()
y = draw(x)
row, col = findGrid(x) #I think the problem is here.
f = fillSquare(row, col)
main()
The code you posted in your question doesn't draw squares because you don't have any turtle operations after pen.begin_fill().
You can draw a filled square like so:
turtle.begin_fill()
for i in range(4):
turtle.forward(1)
turtle.right(90)
turtle.end_fill()
There's actually a mistake in the pseudocode. The offset calculation offset = row % 2 is only valid when n, the number of rows, is an even number. The pseudocode fails to calculate checkered square locations when n is odd.
To make the code work for even and odd values of n, you can evaluate the offset as follows:
offset = ~(n % 2) & (row % 2)
I have implemented these changes in the code below. I have also modified the structure of your program by defining the turtle outside the drawing functions and passing it in as an argument. This lets us set the turtle's speed and visibility settings just once instead of having to do so within each drawing function.
from turtle import*
# Ask the user for the size of the checkered flag (n).
def getSize():
size = eval(input('Please enter the size of the checkered flag: '))
return size
# Draw an n x n grid to the screen.
def drawGrid(turtle, n):
for i in range(0, n+1):
turtle.up()
turtle.goto(0, i)
turtle.down()
turtle.forward(n)
turtle.left(90)
for i in range(0, n+1):
turtle.up()
turtle.goto(i, 0)
turtle.down()
turtle.forward(n)
# Fill the square in the given row and column.
def fillSquare(turtle, row, col):
turtle.up()
turtle.goto(col, row)
turtle.begin_fill()
for i in range(4):
turtle.forward(1)
turtle.right(90)
turtle.end_fill()
def main():
# Get the user's input.
n = getSize()
# Set up the drawing coordinates.
screen = Screen()
screen.setworldcoordinates(-1, -1, 10, 10)
# Make a turtle object for use in drawing. Maximize its speed.
turtle = Turtle()
turtle.speed('fastest')
turtle.hideturtle()
# Draw the checkered flag.
drawGrid(turtle, n)
for i in range(0, n*n, 2):
row = i // n
offset = ~(n % 2) & (row % 2)
col = i % n + offset
fillSquare(turtle, row, col)
print('Hit Enter to quit.')
input()
main()
This is a situation where I believe stamping makes things simpler than drawing in Python turtle:
from turtle import Turtle, Screen
CURSOR_SIZE = 20
def getSize():
""" Ask user for the size of the checkered flag. """
return int(input('Please enter the size of the checkered flag: '))
cells = getSize()
screen = Screen()
size = min(screen.window_width() - 10, screen.window_height() - 30) / cells
offset = (cells % 2) * size/2 + size/2 # properly center odd & even cells
turtle = Turtle('square', visible=False)
turtle.shapesize(size / CURSOR_SIZE)
turtle.speed('fastest')
turtle.color('black')
turtle.penup()
for row in range(-cells // 2, cells // 2):
parity = row % 2 # properly color cells
turtle.goto(-cells // 2 * size + offset, row * size + offset)
for column in range(cells):
turtle.fillcolor(['white', 'black'][parity == column % 2])
turtle.stamp()
turtle.forward(size)
screen.exitonclick()
Stamping also makes the program faster as we're working with larger chunks of the drawing.
I'm trying to make a repeating pattern program in Python that asks you for how many sides you want the repeated shape to be, how many times it should be repeated and the color of the background and shape fill. It should draw the shape before turning by 360 divided by the amount of sides. However, it keeps repeating on the spot continually. My code is below.
from turtle import*
bgColor = input("What colour background do you want?: ")
fillColor = input("What colour shape fill do you want?: ")
numberOfSides = int(input("How many sides?: "))
rotationsWanted = int(input("How many rotations?: "))
rotationsCompleted = 0
def drawshape():
fillcolor(fillColor)
bgcolor(bgColor)
begin_fill()
while (rotationsCompleted < rotationsWanted):
for x in range(numberOfSides):
forward (100)
right(360/numberOfSides)
end_fill()
drawshape()
right(360/rotationsWanted)
rotationsCompleted = rotationsCompleted + 1
Try to modify the while-loop
rotationsCompleted = 0
while (rotationsCompleted < rotationsWanted):
rotationsCompleted = rotationsCompleted + 1
and after end_fill() you should go to an other position maybe using goto(100, 100) to draw the next shape at a different position.
How can I play with a turtle and how can I use a turtle?
I have trouble getting the thing to work as in the picture shown below (ignore the colors).
from turtle import *
from math import *
def formulaX(R, r, p, t):
x = (R-r)*cos(t) - (r + p)*cos((R-r)/r*t)
def formulaY(R, r, p, t):
y = (R-r)*sin(t) - (r + p)*sin((R-r)/r*t)
def t_iterating(R, r, p):
t = 2*pi
up()
goto(formulaX, formulaY)
down()
while (True):
t = t + 0.01
formulaX(R, r, p, t)
formulaY(R, r, p, t)
def main():
R = int(input("The radius of the fixed circle: "))
r = int(input("The radius of the moving circle: "))
p = int(input("The offset of the pen point, between <10 - 100>: "))
if p < 10 or p > 100:
input("Incorrect value for p!")
t_iterating(R, r, p)
input("Hit enter to close...")
main()'
I am trying to make that kind of shape. Here is the coding I have done so far.
Try changing your t_iterating function to this:
def t_iterating(R, r, p):
t = 2*pi # It seems odd to me to start from 2*pi rather than 0.
down()
while t < 20*pi: # This loops while t goes from 2*pi to 20*pi.
t = t+0.01
goto(formulaX(R, r, p, t), formulaY(R, r, p, t))
up()
No! You're missing the point of the turtle! You should try to do it all with relative movements of the turtle. Think about how you would draw the shape if you were the turtle, crawling on a large floor, dragging a paintbrush from your butt.
At each small fragment of time, the turtle will perform one small iteration of a differential equation which governs the whole behavior. It is not generally wise to precompute the x y coordinates and use the turtle's GOTO function.
The turtle itself should have only relative knowledge of its surroundings. It has a direction, and a position. And these two pieces of state are modified by turning and moving.
So, think about how you would draw the spiral. Particularly, think about drawing the very first circle. As the circle appears to close, something interesting happens: it misses. It misses by a tiny little amount, which turns out to be a fraction of a circle. It is this missing curvature that closes the large pattern of circles in a circle, as they add up to one complete turn.
When the whole figure is drawn, the turtle is back to its original position and orientation.
This is my code. The color may not be exact, but here it is:
from turtle import *
from random import randint
speed(10000)
for i in range(20):
col = randint(1, 5)
if col == 1:
pencolor("orange")
elif col == 2:
pencolor("blue")
elif col == 3:
pencolor("green")
elif col == 4:
pencolor("purple")
elif col == 5:
pencolor("dark blue")
circle(50)
left(20)
This is the output:
My code is here and the function was built for automatically choosing the random colour.
from turtle import Turtle, Screen
import random
timmy = Turtle()
screen = Screen()
screen.colormode(255)
timmy.shape("turtle")
timmy.speed("fastest")
angle = [0, 90, 180, 270]
def random_color():
red = random.randint(0, 255)
green = random.randint(0, 255)
blue = random.randint(0, 255)
colour = (red, green, blue)
return colour
def draw_circles(num_of_gap):
for _ in range(int(360 / num_of_gap)):
timmy.color(random_color())
timmy.circle(100)
timmy.right(num_of_gap)
draw_circles(20)
screen.exitonclick()
Spirograph using Python Turtle with random colours
Code:
import random
from turtle import Turtle, Screen
tim = Turtle()
tim.shape("classic")
def turtle_color():
R = random.random()
G = random.random()
B = random.random()
return tim.pencolor(R, G, B)
tim.speed("fastest")
for _ in range(72):
turtle_color()
tim.circle(100)
tim.left(5)
screen = Screen()
screen.exitonclick()
Output:
You basically get the turtle to loop through the 360 degrees and you can choose two pen colours.
from turtle import Turtle, Screen
tim = Turtle()
tim.shape("turtle")
tim.color("green")
### total degrees in circle = 360
### turn left must be a divisor of 360 (1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 18, 20, 24, 30, 36, 40, 45, 60, 72, 90) NOTE: some divisors do not work as well
degrees = 360
turn_left = 12
total_circles = int(degrees / turn_left)
tim.pensize(3)
tim.speed(0)
def circle_colour1():
### choose your colour here:
tim.pencolor("pink")
tim.circle(-100)
tim.left(turn_left)
def circle_colour2():
### choose your colour here:
tim.pencolor("grey")
tim.circle(-100)
tim.left(turn_left)
for _ in range(0, int(total_circles / 2)):
circle_colour1()
circle_colour2()
screen = Screen()
screen.exitonclick()
Real basic (360°/10) is:
from turtle import Turtle as d
draw = d()
draw.speed(0)
draw.pensize(3)
for _ in range(0, 36):
draw.circle(-100)
draw.left(10)
I am trying to fill the color in these squares:
Right now the turtle only fills the corners of theses squares, not the entire square.
Here is my code:
import turtle
import time
import random
print ("This program draws shapes based on the number you enter in a uniform pattern.")
num_str = input("Enter the side number of the shape you want to draw: ")
if num_str.isdigit():
squares = int(num_str)
angle = 180 - 180*(squares-2)/squares
turtle.up
x = 0
y = 0
turtle.setpos(x,y)
numshapes = 8
for x in range(numshapes):
turtle.color(random.random(),random.random(), random.random())
x += 5
y += 5
turtle.forward(x)
turtle.left(y)
for i in range(squares):
turtle.begin_fill()
turtle.down()
turtle.forward(40)
turtle.left(angle)
turtle.forward(40)
print (turtle.pos())
turtle.up()
turtle.end_fill()
time.sleep(11)
turtle.bye()
I've tried moving around turtle.begin_fill() and end_fill() in numerous locations with no luck… Using Python 3.2.3, thanks.
I haven't really used turtle, but it looks like this may be what you want to do. Correct me if I've assumed the wrong functionality for these calls:
turtle.begin_fill() # Begin the fill process.
turtle.down() # "Pen" down?
for i in range(squares): # For each edge of the shape
turtle.forward(40) # Move forward 40 units
turtle.left(angle) # Turn ready for the next edge
turtle.up() # Pen up
turtle.end_fill() # End fill.
You're drawing a series of triangles, using begin_fill() and end_fill() for each one. What you can probably do is move your calls to begin_fill() and end_fill() outside the inner loop, so you draw a full square and then ask for it to be filled.
Use fill
t.begin_fill()
t.color("red")
for x in range(4):
t.fd(100)
t.rt(90)
t.end_fill()
Along with moving begin_fill() and end_fill() outside the loop, as several folks have mentioned, you've other issues with your code. For example, this is a no-op:
turtle.up
I.e. it doesn't do anything. (Missing parentheses.) This test:
if num_str.isdigit():
Doesn't do much for you as there is no else clause to handle the error. (I.e. when it isn't a number, the next statement simply uses the string as a number and fails.) This calculation seems a bit too complicated:
angle = 180 - 180*(squares-2)/squares
And finally there should be a cleaner way to exit the program. Let's address all these issues:
from turtle import Screen, Turtle
from random import random
NUMBER_SHAPES = 8
print("This program draws shapes based on the number you enter in a uniform pattern.")
num_str = ""
while not num_str.isdigit():
num_str = input("Enter the side number of the shape you want to draw: ")
sides = int(num_str)
angle = 360 / sides
delta_distance = 0
delta_angle = 0
screen = Screen()
turtle = Turtle()
for x in range(NUMBER_SHAPES):
turtle.color(random(), random(), random())
turtle.penup()
delta_distance += 5
turtle.forward(delta_distance)
delta_angle += 5
turtle.left(delta_angle)
turtle.pendown()
turtle.begin_fill()
for _ in range(sides):
turtle.forward(40)
turtle.left(angle)
turtle.forward(40)
turtle.end_fill()
screen.exitonclick()