I need to create a function called SpinPolygon that will do what the instruction says. I am a noob coder.
SpinPolygon(Turtle, sides, angle, length, repeat): Draws the polygon number of times while turn polygon by the angle on the left each time. Your program needs to ask number of sides, length of the side and number of rotations from the user) Below is a sample image for rotating 5 times.
I have this so far for the rest of my program:`
import turtle
stage = turtle.Screen() # set stage
stage.title("Shapes") # name stage
sides = int(input("Please enter number of sides:"))
length = int(input("Please enter length of side:"))
sfactor = float(input("Please enter the scale factor:"))
copies = int(input("Please enter number of copies:"))
repeat = int(input("Please enter number of times to repeat the shape:"))
def angle(sides):
sum_of_angles = (sides - 2) * 180
exterior_angle = sum_of_angles / sides
angle = 180 - exterior_angle
return angle
def drawShape(turtle, sides, length):
for i in range(sides):
turtle.forward(length)
turtle.left(angle(sides))
def SpinPolygon(Turtle, sides, angle, length, repeat):
print("idk")
def ScalePolygon(turtle, sides, length, sfactor, number):
for i in range(number):
drawShape(turtle, sides, length)
length *= sfactor
turtle.done()
ScalePolygon(turtle, sides, length, sfactor, copies)
Description doesn't mention to ask for sfactor, copies and even for angle.
You ask for too many elements.
Function angle can be reduced to angle = 360 / sides
You should start with SpinPolygon, not ScalePolygon.
And you don't even need ScalePolygon because description doesn't mention sfactor.
import turtle
# --- functions ---
def drawShape(turtle, sides, length):
shape_angle = 360 / sides
for i in range(sides):
turtle.forward(length)
turtle.left(shape_angle)
def SpinPolygon(turtle, sides, angle, length, repeat):
for i in range(repeat):
drawShape(turtle, sides, length)
turtle.left(angle)
# --- main ---
stage = turtle.Screen()
stage.title("Shapes")
sides = 5 #int(input("number of sides: "))
length = 100 #int(input("length of side: "))
repeat = 5 #int(input("number of rotations: "))
angle = 360/repeat
SpinPolygon(turtle, sides, angle, length, repeat)
turtle.done()
Result for sides = 5:
Result for sides = 4:
Result for sides = 8, length = 50, repeat = 15:
EDIT:
Code with extra sfactor
import turtle
# --- functions ---
def drawShape(turtle, sides, length):
shape_angle = 360 / sides
for i in range(sides):
turtle.forward(length)
turtle.left(shape_angle)
def SpinPolygon(Turtle, sides, angle, length, repeat, sfactor):
for i in range(repeat):
drawShape(turtle, sides, length)
turtle.left(angle)
length *= sfactor
# --- main ---
stage = turtle.Screen()
stage.title("Shapes")
sides = 8 #int(input("number of sides: "))
length = 50 #int(input("length of side: "))
repeat = 15 #int(input("number of rotations: "))
sfactor = 0.9 #float(input("sfactor: "))
angle = 360/repeat
SpinPolygon(turtle, sides, angle, length, repeat, sfactor)
turtle.done()
Result for sides = 8, length = 50, repeat = 15 and sfactor = 0.9:
Related
So I need my turtle to draw any regular polygon the user wants where they click on the screen
and also printing out the total length of the polygons they draw.
import turtle
t=turtle.Turtle()
tlength=0
def figure(num, length):
for i in range(num):
t.forward(length)
t.left(360/num)
global tlength
tlength = tlength+length
def drawit(x, y):
shape = int(turtle.textinput("","What Shape?"))
if shape!="0":
length = int(turtle.textinput("","The length of side? "))
t.penup()
t.goto(x, y)
t.pendown()
figure(shape, length)
t.write("total drawn length=", tlength)
s = turtle.Screen()
s.onscreenclick(drawit)
This is what I have so far.. It works well except it wont print out the total length. Any suggestions?
You have some code issues:
t.write("total drawn length=", tlength)
This won't work as write() doesn't take multiple arguments to display but rather just one. Check the documentation.
shape = int(...)
if shape != "0":
You just forced shape to be an int but then test if it's not a string -- this will always be true. Also, the int() call will fail if the user hits "Cancel" and textinput() returns None.
tlength=0
This only gets initialized once, so any subsequent polygons will add the perimeters of the previous polygons to their total length.
Here's rework of your program that fixes most of the above issues and basically works:
from turtle import Screen, Turtle
def figure(sides, length):
perimeter = 0
for _ in range(sides):
turtle.forward(length)
perimeter += length
turtle.left(360 / sides)
return perimeter
def drawit(x, y):
shape = screen.textinput("", "How many sides?")
if not shape:
return
length = screen.textinput("", "The length of one side?")
if not length:
return
turtle.penup()
turtle.goto(x, y)
turtle.pendown()
total_length = figure(int(shape), int(length))
turtle.write("Total drawn length = " + str(total_length))
turtle = Turtle()
turtle.hideturtle()
screen = Screen()
screen.onscreenclick(drawit)
screen.mainloop()
This is a question that i had to solve, but have been banging my head against a wall for the past 5 days. There must be something really simple that i am missing, or misunderstanding, as the logic seems 100% correct in my head, but it just won't work.
I need to draw "scattered" houses, that do not over lap, 100 of them.
I have to use turtle to draw them, so i have X and Y coordinates.
And X and Y list for verification purposes, to see if a house is already in that place.
What i am doing is drawing a "house" (square with a triangle on top) on the randomized coordinates,
I loop while the number of houses is less than 100.
On each loop i randomize the x and y coordinates, from where i start drawing each house with turtle.
I check if the value is already in the X and Y verification lists, and also if my new X and Y are +/- the size of the house (treating it as a square)
import turtle
import time
import random
t = turtle.Turtle()
turtle.screensize(1920,1000)
x_verif = []
y_verif = []
t.speed(0)
collision = None
def square():
for s in range(0, 4):
t.forward(90)
t.left(90)
def triangle():
for s in range(0, 2):
t.left(-60)
t.forward(52)
def house():
square()
t.left(90)
t.forward(90)
triangle()
def scatter():
print("a")
house()
x1 = random.randint(-850, 850)
y1 = random.randint(-380, 380)
count = 0
while count < 100:
print("a2")
i = 0
u = 0
collision = False
for tries in range (0, 2):
print("a3")
x_verif.append(x1)
y_verif.append(y1)
while u < 100:
print("a4")
print(x_verif, y_verif, x1, y1)
while i < len(x_verif):
x1 = random.randint(-850, 850)
y1 = random.randint(-380, 380)
print(x1, y1)
if x1 not in x_verif and (x1 > x_verif[i]+91 or x1 < x_verif[i]-91):
if y1 not in y_verif and (y1 > y_verif[i]+142 or y1 < y_verif[i]-142):
collision = False
else:
collision = True
if collision == False:
t.penup()
t.hideturtle()
t.setx(x1)
t.sety(y1)
t.pendown()
house()
x_verif.append(x1)
y_verif.append(y1)
count += 1
i+= 1
u += 1
scatter()
Sorry for the ugly code, and the simplicity behind it. I would love to use list comprehensions for this, but i do not know where my logic fails at the moment. This is like my 100th try, as of this version it only draws the initial house and i think it loops infinitely somewhere....
My problem lies in looping through the whole lists for every new value. Do i need to loop through them every time, or is there some IF condition that I can use? Edit: It keeps on looping through random values, but none of them are accepted by the two IF statements that i'm using.
On a side note: With my current code they also change direction of drawing every time... No idea why is that happening....
Edit: I am very thankful for all the solutions! I'm struggling with the note at the beginning of the question. It says that it should only take a couple more lines to do the last one, compared to the first one..... Are they joking?
This turned out to be a trickier problem than I assumed from the description. My approach was to treat, and store, a house as two polygons, a square and a triangle. I randomly test draw (pen up) a house and compare all the points in its polygons to see if they are inside existing house polygons, and vice versa. If no overlap, draw the house for real. The solution is not efficient, but it allows tight packing of houses than a simple diameter-based approach.
The point in triangle routine is based on one from GeeksForGeeks.org
I have one slight fudge factor in my code that still needs to be polished out. But overall it seems to achieve the objective:
from turtle import Screen, Turtle
from random import randint
HOUSES = 100
HOUSE_SIZE = 90
WINDOW_WIDTH, WINDOW_HEIGHT = 1920, 1000
# assumes roof is an isosceles triangle
ROOF_SIDE = HOUSE_SIZE * 3**0.5 / 3
ROOF_HEIGHT = ROOF_SIDE // 2
FONT_SIZE = HOUSE_SIZE // 3
FONT = ('Arial', FONT_SIZE, 'normal')
def square(turtle, identity=None):
turtle.begin_poly()
for _ in range(3):
turtle.forward(HOUSE_SIZE)
turtle.right(90)
turtle.end_poly()
turtle.forward(HOUSE_SIZE/2 - FONT_SIZE/2) # visually finish square
if identity: # label each house with a number
turtle.penup()
turtle.right(90)
turtle.forward(HOUSE_SIZE/2)
turtle.write(identity, align='center', font=FONT)
turtle.backward(HOUSE_SIZE/2)
turtle.left(90)
turtle.pendown()
turtle.forward(HOUSE_SIZE/2 + FONT_SIZE/2) # visually finish square
turtle.right(90) # return to original orientation
return turtle.get_poly()
def triangle(turtle):
turtle.begin_poly()
turtle.forward(HOUSE_SIZE)
turtle.left(150)
turtle.forward(ROOF_SIDE)
turtle.end_poly()
turtle.left(60)
turtle.forward(ROOF_SIDE) # visually finish triangle
turtle.right(210) # return to original orientation
return turtle.get_poly()
def house(turtle, identity=None):
return (square(turtle, identity), triangle(turtle))
def area_of_triangle(p1, p2, p3):
x1, y1 = p1
x2, y2 = p2
x3, y3 = p3
return abs((x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2))) // 2
def is_inside_triangle(point, triangle):
p1, p2, p3 = triangle
a = area_of_triangle(p1, p2, p3)
b = area_of_triangle(point, p2, p3)
c = area_of_triangle(p1, point, p3)
d = area_of_triangle(p1, p2, point)
return abs(a - (b + c + d)) < 5 # 5 == fudge factor, sigh
def is_inside_square(point, square):
x, y = point
p1, p2, p3, p4 = square
_, y1 = p1
x2, _ = p2
_, y3 = p3
x4, _ = p4
return x4 <= x <= x2 and y3 <= y <= y1
def scatter(turtle):
houses = []
count = 0
while count < HOUSES:
x = randint(-WINDOW_WIDTH/2, WINDOW_WIDTH/2 - HOUSE_SIZE)
y = randint(HOUSE_SIZE - WINDOW_HEIGHT/2, WINDOW_HEIGHT/2 - ROOF_HEIGHT)
turtle.penup()
turtle.goto(x, y)
proposed_square, proposed_triangle = house(turtle) # test draw invisible house
turtle.pendown()
collision = False
for point in proposed_square + proposed_triangle: # does proposed house collide with houses?
for square, triangle in houses:
if is_inside_square(point, square) or is_inside_triangle(point, triangle):
collision = True
break
if collision:
break
for square, triangle in houses: # do houses collide with proposed house?
for point in square + triangle:
if is_inside_square(point, proposed_square) or is_inside_triangle(point, proposed_triangle):
collision = True
break
if collision:
break
if not collision:
count += 1
houses.append(house(turtle, identity=count)) # actually draw new house
print(count)
screen = Screen()
screen.screensize(WINDOW_WIDTH, WINDOW_HEIGHT)
screen.tracer(False)
turtle = Turtle()
turtle.hideturtle()
scatter(turtle)
screen.tracer(True)
screen.exitonclick()
This problem is simplified somewhat by the consistent orientation of houses. If the houses were randomly oriented, compass-wise, the square overlap calculations would be more complex.
The solution could be made more efficient by doing triangle overlap with triangle, square overlap with triangle, etc. tests instead of simply "point inside". We could also push the collision logic down into the square() and triangle() routines to throw an error as soon as there's a collsion, rather than completing a house and then testing.
Given the size of the screen area, size of a house, the number of houses, and the random scattering, I believe it may be possible for an idividual run of the program to stall trying to place a house where there may not be available space:
Defo no the best way to do it but
import turtle
import time
import random
t = turtle.Turtle()
turtle.screensize(1920,1000)
x_verif = []
y_verif = []
t.speed(0)
collision = None
def square():
for s in range(0, 4):
t.forward(90)
t.left(90)
def triangle():
for s in range(0, 2):
t.left(-60)
t.forward(52)
def house():
square()
t.left(90)
t.forward(90)
triangle()
t.left(30) #returning to 90 degrres
def scatter():
beenAt = [] #this will hold every place that there is a house
for i in range(100):
t.penup()
loop = True
while loop == True:
area = random.randint(-850, 850)
for i in range(91): #looping for the size of the house
if area+i in beenAt: #if the number chosen plus i is in beenAt stop because we cant use that place
break
if i == 90: #if at the finial part of our loop then draw house
t.goto(area, 0)
t.pendown()
for i in range(area, area + 91):
beenAt.append(i) #add to been at list every place we have drawn
house()
loop = False
scatter()
For my assignment, I'm trying to make a 5 x 5 checkerboard with the user choice in color and square size. I got how to make square sizes and colors based on the user input and am having some trouble with how to start a loop or how to create a 5 x 5 checkerboard. I'm just not sure what I could do to move the turtle to make a 5x5 board. I have this much done so far, if anyone could help me get started, i would really appreciate it!
import turtle
def main():
length = int(input("Enter a desired length (from 1-150.)"))
keepGoing = 'y'
while keepGoing == 'y':
print("What color would you like to draw?")
print(" Enter 1 for Black")
print(" 2 for Blue")
print(" 3 for Red")
print(" 4 for Green")
choice = int(input(" Your choice?"))
if choice == 1:
square(0,0,length,'black')
elif choice == 2:
square(0,0,length,'blue')
elif choice == 3:
square(0,0,length,'red')
elif choice == 4:
square(0,0,length,'green')
else:
print("ERROR: only enter 1-4.")
def square(x, y, width, color):
turtle.clear()
turtle.penup() # Raise the pen
turtle.goto(x, y) # Move to (X,Y)
turtle.fillcolor(color) # Set the fill color
turtle.pendown() # Lower the pen
turtle.begin_fill() # Start filling
for count in range(4): # Draw a square
turtle.forward(width)
turtle.left(90)
turtle.end_fill()
#calling main function
main()
First, you developed your user interface without having anything to interface to -- you might start the other way around next time. Second, don't reinvent booleans (e.g. while keepGoing == 'y'). Third, for the amount of code it took you to draw one square, we can stamp the entire grid:
from turtle import Turtle, Screen
COLORS = ["Black", "Blue", "Red", "Green"]
GRID = 5
STAMP_UNIT = 20
def main():
length = int(input("Enter a desired length (from 1-150): "))
keepGoing = True
while keepGoing:
print("What color would you like to draw?")
for i, color in enumerate(COLORS, start=1):
print(" Enter {} for {}".format(i, color))
choice = int(input(" Your choice? "))
if 1 <= choice <= len(COLORS):
grid(-length * GRID // 2, -length * GRID // 2, length, COLORS[choice - 1])
keepGoing = False
else:
print("ERROR: only enter 1-{}.".format(len(COLORS)))
def grid(x, y, width, color):
tortoise = Turtle('square', visible=False)
tortoise.shapesize(width / STAMP_UNIT)
tortoise.color(color)
tortoise.penup()
for dy in range(0, GRID):
tortoise.goto(x, y + width * dy)
for dx in range(dy % 2, GRID, 2):
tortoise.setx(x + width * dx)
tortoise.stamp()
screen = Screen()
main()
screen.exitonclick()
USAGE
> python3 test.py
Enter a desired length (from 1-150): 30
What color would you like to draw?
Enter 1 for Black
Enter 2 for Blue
Enter 3 for Red
Enter 4 for Green
Your choice? 2
OUTPUT
This is a perfect example of where stamping can make things simpler and faster than drawing.
I'm making a game like 'angry bird'.
There are two input:power and angle.
I apply those inputs to parabolic curve.
My turtle flies, making a parabolic curve. and my turtle have to hit the target,
but my turtle draws strange curve when angle is greater than 46, angle is 30, 40 etc...
I don't know where is problem....here is my code:
import turtle
import random
import math
g=9.80665
origin_x=-480
origin_y=-180
flag=False
def create_target():
x=random.randint(0,500)
y=random.randint(-200,0)
target=turtle.Turtle()
target.hideturtle()
target.penup()
target.goto(x,y)
target.shape('square')
target.color('red')
target.showturtle()
return target
def create_turtle():
homework=turtle.Turtle()
homework.hideturtle()
homework.penup()
homework.speed(0)
homework.goto(origin_x,origin_y)
homework.pendown()
homework.shape('turtle')
homework.color('blue')
homework.left(45)
homework.showturtle()
return homework
def setting():
'''drawing back ground lines'''
setting=turtle.Turtle()
setting.hideturtle()
setting.speed(0)
turtle.colormode(255)
setting.pencolor(214,214,214)
for y in range(100,-101,-100):
setting.penup()
setting.goto(-500,y)
setting.pendown()
setting.goto(500,y)
for x in range(-375,500,125):
setting.penup()
setting.goto(x,200)
setting.pendown()
setting.goto(x,-200)
def throw_turtle(turtle,target):
angle=int(input("Enter Angle:"))
power=int(input("Enter Power:"))
'''
parabola fomula:
x coordinate: speed(in here, that is power) * cos(anlge)*time
y coordinate: speed*sin(angle)*time - (gravity speed*time**2)/2
'''
for time in range(1,20):
# the origin fomula is for the situation that starts from (0,0). so I think
# I should compensate it, but is it right?
x=power*math.cos(angle)*time + origin_x
y=power*math.sin(angle)*time - (((time**2)*g)/2) + origin_y
if x<origin_x: # I think it has problem...
x-=origin_x
turtle.goto(x,y)
turtle.stamp() #this is for testing
if (x==target.xcor()) and (y==target.ycor()):
print("******Target is HIT!!! ******")
print("End of Game")
flag=True
break
else:
print("You missed...")
turtle.setup(1000,400)
windo=turtle.Screen()
windo.title('Angry Turtle')
setting()
#__main
my_turtle=create_turtle()
while flag==False:
target=create_target()
my_turtle=create_turtle()
my_turtle.speed(6)
throw_turtle(my_turtle,target)
my_turtle.hideturtle()
target.hideturtle()
I think create_target() and create_turtle(), and setting() don't have problem...
Below, I reduce your code to a MVCE (minimal, complete, and verifiable example) to examine the parabolic curve drawing code. The problem I found with it is the usual one of the difference between degrees and radians. The Python math library thinks in radians but provides a conversion function for degrees. The Python turtle library thinks in degress, by default, but can switch to radians using turtle.radians(). Either way is fine but the usage has to be consistent:
from turtle import Turtle, Screen
import math
import random
G = 9.80665
origin_x = -480
origin_y = -180
def create_turtle():
homework = Turtle(shape='turtle')
homework.hideturtle()
homework.penup()
homework.goto(origin_x, origin_y)
homework.pendown()
homework.speed(0)
homework.left(45)
homework.showturtle()
return homework
def throw_turtle(turtle):
angle = int(input("Enter Angle (in degrees): "))
power = int(input("Enter Power: "))
# parabola formula:
# x coordinate: speed(in here, that is power) * cos(angle)*time
# y coordinate: speed*sin(angle)*time - (gravity speed * time**2)/2
for time in range(1, 20):
x = power * math.cos(math.radians(angle)) * time + origin_x
y = power * math.sin(math.radians(angle)) * time - (((time ** 2) * G) / 2) + origin_y
turtle.goto(x, y)
turtle.stamp() # this is for testing
window = Screen()
window.setup(1000, 400)
for _ in range(3):
my_turtle = create_turtle()
my_turtle.color(random.choice(['red', 'green', 'blue', 'purple', 'black']))
throw_turtle(my_turtle)
window.exitonclick()
EXAMPLE
> python3 test.py
Enter Angle (in degrees): 30
Enter Power: 120
Enter Angle (in degrees): 45
Enter Power: 90
Enter Angle (in degrees): 60
Enter Power: 90
>
Now, what more do you want it to do parabolic curve-wise?
Oh Thanks thanks really thanks.......!!!!
but, i have one more problem. that is, the 'if' sentence in throw_turtle function.
my intention for using that 'if' sentence is for check and end the game. but in fact, the user can not exactly correct coordinate of target. so it is impossible that end the game. so the game is endless....
to avoid that, i re-write like this.
def throw_turtle(turtle,target):
angle=int(input("Enter Angle:"))
power=int(input("Enter Power:"))
'''
parabola fomula: x coordinate: speed(in here, that is power) * cos(anlge)*time
y coordinate: speed*sin(angle)*time - (gravity speed*time**2)/2'''
for time in range(1,20):
x=power*math.cos(math.radians(angle))*time + origin_x #the origin fomula is for the situation that starts from (0,0). so i think i should compensate it. but.. is it right?
y=power*math.sin(math.radians(angle))*time - (((time**2)*g)/2) + origin_y
turtle.goto(x,y)
turtle.stamp() #this is for testing min_target_x=target.xcor()-1
max_target_x=target.xcor()+1 #the '1' means target's size
min_target_y=target.ycor()-1
max_target_y=target.ycor()+1
min_target_y=target.ycor()-1
if ((turtle.xcor()>=min_target_x) or (turtle.xcor()<=max_target_x)) and ((turtle.ycor()>=min_target_y) or (turtle.ycor()<=max_target_y)):
print("******Target is HIT!!! ******")
print("End of Game")
flag=True
break
else:
print("You missed...")
I am trying to make a table in python that asks a user for a side length of a polygon and then gives the area of that polygon when it's number of sides is between 3-9. My problem is that, in the report function, I have to give a different area for each polygon with a different number of sides but when i run it, the area is always the same even when the number of sides of the polygon has changed.
import math
def main():
side_length = get_side_length()
report(side_length)
def get_side_length():
length = int(input('Enter a side length: '))
return length
def report(a):
num_sides = 2
each_area = polygon_area(a)
print('side length\t'+ 'number of sides\t'+ 'area')
while num_sides < 9:
num_sides += 1
print(a, num_sides, each_area, sep='\t\t', end='\n')
def polygon_area(sl):
for num_sides in range(3, 10):
area = (num_sides * sl * sl) / (4 * math.tan(math.pi / num_sides))
return area
main()