I am writing a Python code for a school project. The program is to draw a number of circles based on the user input, (2-6 circles). I have done that but now need to draw multiple rows of circles based on user input. For example, if a user picks 3 circles I need to draw 3 circles by 3 circles.
#import tkinter and turtle
import tkinter as tk
from turtle import *
#ask for user input using tkinter
from tkinter import simpledialog
application_window = tk.Tk()
answer = simpledialog.askinteger('Request', 'number of circles(2-6)?',
parent=application_window, minvalue=2, maxvalue=6)
#set position of turtle and define turtle
t = Turtle()
t.penup()
t.setpos(-200,-200)
t.pendown()
#draw appropriate number of circles using loop
i = 2
for i in range (answer):
circle(30)
penup()
forward(60)
pendown()
i = +1
Don't make us do your homework. Tell us the problem, tell us what you've tried, then ask a question. For example, "How do I make the turtle draw three rows of circles?"
Surround the for loop you already have with another for loop. Every time the outer loop runs, the inner loop will run to create one row, and then move the turtle down before the next iteration.
#import tkinter and turtle
import tkinter as tk
from turtle import *
#ask for user input using tkinter
from tkinter import simpledialog
application_window = tk.Tk()
answer = simpledialog.askinteger('Request', 'number of circles(2-6)?',
parent=application_window, minvalue=2, maxvalue=6)
#set position of turtle and define turtle
t = Turtle()
t.penup()
t.setpos(-200,-200)
t.pendown()
#draw appropriate number of circles using loop
for row in range(answer):
for col in range(answer):
circle(30)
penup()
forward(60) # must be undone after loop
pendown()
penup()
backward(60) # undo the backward on line 20
backward(60 * col) # go backwards the length of the diameter times the number of circles
right(90) # turn right 90 degrees
forward(60) # forward the length of one diameter
left(90) # turn back left 90 degrees
pendown()
I'm offering an alternate solution to that of #JacksonH for two reasons: first, if you're using Python 3 (and you should be), then you don't need to grab simpledialog out of tkinter, use Python 3 turtle's numinput() (and textinput()) instead; second, an aesthetic goal should be to have the turtle move as little as possible to achieve your result, even if that requires more, smarter code. Watch the difference in how this solution draws the picture as opposed to the other:
from turtle import Screen, Turtle
# Ask for user input
DEFAULT_COUNT = 3
screen = Screen()
answer = screen.numinput('Request', 'number of circles(2-6)?', default=DEFAULT_COUNT, minval=2, maxval=6)
if answer is None:
answer = DEFAULT_COUNT
else:
answer = int(answer) # int for range()
# define turtle and set position of turtle
turtle = Turtle()
turtle.speed('fast') # because I have little patience
turtle.penup()
turtle.setpos(-200, -200)
direction = 1
# draw appropriate number of circles using nested loops
for row in range(answer - 1, -1, -1): # loop backward to use last iteration as a flag
for column in range(answer - 1, -1, -1):
turtle.pendown()
turtle.circle(30 * direction)
turtle.penup()
if column:
turtle.forward(60) # not done final time
if row: # every time but the last
turtle.left(90 * direction) # turn +/-90 degrees
turtle.forward(60) # forward the length of one diameter
turtle.left(90 * direction) # turn +/-90 degrees
direction *= -1 # reverse our sense of direction
turtle.hideturtle()
screen.exitonclick()
Related
So I have an assignment that asked me to draw any regular polygon using Turtle and I created the code. It works but my mentor said to try again. I would like to know what I did wrong, Thank you!
The requirements for this assignment are:
The program should take in input from the user.
The program should have a function that:
takes in the number of sides as a parameter.
calculates the angle
uses the appropriate angle to draw the polygon
from turtle import Turtle
turtle = Turtle()
side = int(input("Enter the number of the sides: "))
def poly():
for i in range(side):
turtle.forward(100)
turtle.right(360 / side)
poly()
I think this might be better suited on math stackexchange.
A regular polygon has interior angles (n−2) × 180 / n. Theres a good blog post on that here.
You just need to change the angle by which you rotate every time:
from turtle import Turtle
turtle = Turtle()
num_sides = int(input("Enter the number of the sides: "))
def poly():
for i in range(num_sides):
turtle.forward(100)
# change this bit
turtle.right((num_sides - 2) * 180 / num_sides)
poly()
This is the function I used to draw a polygon using Turtle:
Draws an n-sided polygon of a given length. t is a turtle.
def polygon(t, n, length):
angle = 360.0 / n
polyline(t, n, length, angle)
I am trying to draw 7 staircases with a loop but I have missed something and not sure why it's not working. It draws the first staircase and then goes completely off track and doesn't put the pen back down and I'm not sure why.
#Draw stairs 7 times
from turtle import*
#Stair repeat
for i in range (3):
forward (25)
left (90)
forward(25)
right(90)
#move to next stair
for i in range(7):
penup()
forward(25)
right(90)
forward(75)
left(90)
pendown()
My understanding is that the for loop would repeat the code, so if I want it to move for 7 separate stairs then the range is 7? This is obviously not correct though as it doesn't work. Hoping someone could point me in the correct direction as to why it's wrong.
A couple things seem amiss:
The body of the for i in range(7): loop doesn't make sense. It never does any movement when the pen is down, so the turtle draws nothing.
The for i in range (3): loop doesn't make sense either if you want to draw 7 stairs. What do you need to do 3 times here?
Beyond that, avoid from turtle import *. This is confusing and can lead to bugs, because it brings hundreds of functions into your namespace, creating potential name clashes and making it hard to tell which functions are yours and which belong to the turtle module. Better to import turtle or from turtle import Screen, Turtle and create a turtle instance.
Here's a rework that hopefully matches your intended result:
import turtle
t = turtle.Turtle()
step_size = 25
for _ in range(7):
t.left(90)
t.forward(step_size)
t.right(90)
t.forward(step_size)
turtle.exitonclick()
Based on the follow-up comment, if you want to draw staircases of 3 stairs 7 times, then nest your loops and add some code to reposition the turtle to wherever it needs to be to draw each staircase. For example:
import turtle
t = turtle.Turtle()
step_size = 25
for i in range(7):
t.penup()
# whatever logic puts you in the right position for the next stair
t.goto(-step_size * i, 1.5 * step_size * i)
t.pendown()
for _ in range(3):
t.left(90)
t.forward(step_size)
t.right(90)
t.forward(step_size)
turtle.exitonclick()
I don't know what your expected goal is, so you'll need to adjust this to match that, but the general approach should be the same.
I am trying to make a turtle analog clock, and to make the second, minute, an hour hands I am making a shape with turtle, and using .tilt() to tilt it 6 degrees every second.
The thing is, when I run .tilt() it rotates the ship from the middle, whereas I want to have it rotate from the bottom point (like an analog clock).
Is there a way to do that, or do I need to find another way to make this program?
Here is my code:
from turtle import *
import time
turtle = Turtle()
turtle.shape("square")
turtle.shapesize(6, .1)
tilt_amnt = 0
for x in range (60):
turtle.tilt(tilt_amnt)
tilt_amnt = tilt_amnt + 6
time.sleep(1)
I don't think there is a way to tilt the turtle in such a way where it turns from the bottom but you can rewrite the code to essentially do the same thing but using forward instead. Check this out.
from turtle import *
import time
turtle = Turtle()
turtle.pensize(2)
turtle.hideturtle()
turtle.speed(0)
tilt_amnt = 0
for x in range (60):
turtle.right(tilt_amnt)
turtle.forward(100)
turtle.backward(100)
tilt_amnt = tilt_amnt + 6
time.sleep(1)
turtle.clear()
Some thoughts: first, I wouldn't use tilt() (high overhead, forces an update), even if you do use turtles as hands, consider using right() or setheading(); second, I would use mode('logo') as this makes 0 degrees the top of the screen and makes headings clockwise (like, say a 'clock') instead of counterclockwise; third, if you want accuracy, don't use sleep() but rather extract the current time from the system and set your hands accordingly.
Large real world clocks do turn their hands from the middle, or more specifially, the center of gravity. This keeps the hands from slowing the mechanism on the way up, or rushing it on the way down. The trick is to make the hands look visually asymmetric but keep the weight symmetric. Here's a solution I came up with earlier that does something like this with turtles as the hands, turning from their centers.
Finally, here's a rewrite of the example #AlexJoslin provided to use realtime accuracy, potentially updating hand positions multiple times within a second:
from turtle import Screen, Turtle
from time import localtime as time
def tick():
second.setheading(6 * time().tm_sec)
second.clear()
second.forward(150)
second.backward(150)
screen.update()
screen.ontimer(tick)
screen = Screen()
screen.mode('logo')
screen.tracer(False)
second = Turtle()
second.hideturtle()
second.pensize(2)
tick()
screen.exitonclick()
I'm trying to get the turtle shape to follow the direction of a line.
I have a simple parabola and I want the turtle shape to follow the direction of the line - when the graph goes up, the turtle faces up and when the graph comes down, the turtle faces down.
I am using goto() for the position of the turtle and x=x+1 for the x position on the graph:
t.goto(x,y)
t.right(??) - this?
t.left(??) - this?
t.setheading(??) or this?
What is the best method to achieve this? When I have tried using t.right() in a while loop (I am looping until x is complete), the turtle continues to spin in a circle as it moves, which is not what I want.
Still not getting this. I added the extra code that was suggested - here is the EDIT and the full code for what I am trying to achieve...
I am using the physics formula for trajectory (I used this so I know my values outputted are correct).
http://www.softschools.com/formulas/physics/trajectory_formula/162/
import math
import turtle
import time
w=turtle.Turtle()
i=0
angle=66.4
velocity=45.0
g=9.8
t=math.tan(math.radians(angle))
c=math.cos(math.radians(angle))
turtle.delay(9)
w.shape("turtle")
w.setheading(90)
while i < 150:
start = i * t
middle = g*(i**2)
bottom =(2*(velocity**2)*c**2)
total = start-middle/bottom
print(total)
w.setheading(turtle.towards(i,total))
w.goto(i,total)
i=i+1
turtle.exitonclick()
The orientation of the turtle can be determined from the derivative of your function at the current position.
If you have the function as a sympy function, you can ask Python to do the differentiation. Or you could just do it on your own. If your function is
y = x^2
, then the derivative is
dy = 2 * x
Given that derivative at the current position, its arc tangent gives you the turtle's heading:
t.setheading(math.atan(dy))
Make sure that the angle mode of the turtle is set to radians or convert them to degrees
t.setheading(math.degrees(math.atan(dy)))
I agree with #NicoSchertler that the arc tangent of the derivative is the way to go mathematically. But if it's just for good visuals, there's a simpler way. We can combine turtle's setheading() and towards() methods, constantly setting the turtle's heading towards the next position just before we go there:
from turtle import Screen, Turtle
turtle = Turtle(shape='turtle', visible=False)
turtle.penup()
turtle.goto(-20, -400)
turtle.pendown()
turtle.setheading(90)
turtle.showturtle()
for x in range(-20, 20):
y = -x ** 2
turtle.setheading(turtle.towards(x, y))
turtle.goto(x, y)
screen = Screen()
screen.exitonclick()
I'm creating a python program and one of the methods must allow two different turtles to approach or 'try' to converge at a single location
The dependency of whether the turtles converge or not depends on the random speeds of the turtles.
But my immediate concern is trying to make two different turtles move at different speeds towards the same location.
Or an alternate idea I've had it to try and run two lines of code simultaneously ( the movement for both turtles ) but I'm an intermediate programmer and I'm not too sure if that's even possible.
Thank you for thanking the time to reply to my question
You cannot move two objects simultaneously, you can only simulate it.
This is what I gave my grade 10's as a hint on this same question.
Not perfect, but it shows the concept.
##turtleChase.py
##Randomly place the turtles on the screen
##one turtle will then chase the other as it moves across the screen
##
##input: mouseclick events
##output: graphics on screen, text in Shell
##pseudocode:
##setup your screen
##setup the turtles
##randomly place both turtles
##randomly find a location to move the first turtle to
##turn the first turtle towards the desired location
##in a loop:
##move the first turtle a small distance
##determine the heading to move the second turtle to the first turtle
##move the second turtle a small distance
##is the second turtle at the same position of the first turtle?
##if it is
##quit the loop
##if not
##continue the loop
import turtle, random
random.seed()
# setup the output window
picSize = (400,600)
playGround = turtle.Screen()
playGround.screensize(picSize[0], picSize[1])
#setup the turtles
bob = turtle.Turtle()
bob.ht()
bob.color('red')
jeff = turtle.Turtle()
jeff.ht()
jeff.color('blue')
# find random positions for the turtles
# use the picSize variable so that we can change the screensize easily
# without having to change a lot of code.
# if the screen is 600 pixels tall, then the y-coordinates go from
# -300 to +300, just like in math.
jeffx = random.randint(-picSize[0]/2,picSize[0]/2)
jeffy = random.randint(-picSize[1]/2,picSize[1]/2)
bobx = random.randint(-picSize[0]/2,picSize[0]/2)
boby = random.randint(-picSize[1]/2,picSize[1]/2)
# find a point to move bob to
bobNewx = random.randint(-picSize[0]/2,picSize[0]/2)
bobNewy = random.randint(-picSize[1]/2,picSize[1]/2)
newBobPos = (bobNewx,bobNewy)
print(jeffx,jeffy)
print(bobx,boby)
# place the turtles and show them
bob.setpos(bobx,boby)
jeff.setpos(jeffx,jeffy)
jeff.st()
bob.st()
#rotate bob towards its target location
bobTurn = bob.towards(newBobPos)
bob.setheading(bobTurn)
while bob.position() != jeff.position():
bob.fd(1)
jeffTurn = jeff.towards(bob)
jeff.setheading(jeffTurn)
jeff.fd(1.5)
So if the location is predetermined, and the speed of the turtles is something calculated ahead of time, you can have one loop that simply moves both turtles (at the same time, in the same frame) towards that point, where how far they move would be dependent upon their speed.
Another way to make turtles move simultaneously at different speeds is to use timer events. Here I revise #dougc905's fun example to use timers instead:
from turtle import Turtle, Screen
from random import seed, randint
seed()
DELAY = 100 # milliseconds
# setup the output window
picSize = (400, 600)
playGround = Screen()
playGround.screensize(*picSize)
# setup the turtles
bob = Turtle(shape='turtle', visible=False)
bob.penup()
bob.color('red')
bob.speed('slow')
jeff = Turtle(shape='turtle', visible=False)
jeff.penup()
jeff.color('blue')
jeff.speed('normal')
x_quadrant = -picSize[0] // 2, picSize[0] // 2
y_quadrant = -picSize[1] // 2, picSize[1] // 2
# find random positions for the turtles
jeff_xy = randint(*x_quadrant), randint(*y_quadrant)
bob_xy = randint(*x_quadrant), randint(*y_quadrant)
# find a point to move bob to and rotate towards its target location
bobNew_xy = randint(*x_quadrant), randint(*y_quadrant)
bob.setheading(bob.towards(bobNew_xy))
# place the turtles and show them
jeff.setpos(jeff_xy)
jeff.showturtle()
jeff.pendown()
bob.setpos(bob_xy)
bob.showturtle()
bob.pendown()
# bob's motion is in a straight line
def moveStraight():
bob.fd(bob.speed())
playGround.ontimer(moveStraight, DELAY)
# jeff's motion is towards bob
def moveToward():
if bob.position() != jeff.position():
jeff.setheading(jeff.towards(bob))
jeff.fd(jeff.speed())
playGround.ontimer(moveToward, DELAY)
moveStraight()
moveToward()
playGround.exitonclick()