Python simple turtle progam - python

I am having trouble trying to finish a python turtle program. When I attempt to input x and y coordinates as well as a radius value for the function like
t.drawSnowman(x = 25,y = 25,radius = 25) the program misbehaves when I input values.but if I leave out the parameters above and instead just use t.drawSnowman() the program works as intended but I am not able to create various instances of the snowman.
I would really like help trying to figure out how to input the parameters and still have the program function.
here's my code
import turtle
class MyTurtle(turtle.Turtle):
""""""
def __init__(self):
"""Turtle Constructor"""
turtle.Turtle.__init__(self, shape="turtle")
def drawNose(self, x=0, y=0, radius = 15, circle_color = "black"):
'''draw nose '''
self.pendown()
self.goto(-(radius) * (0.25),(radius * 6)+(radius * 4)+(radius))
self.goto(0,(radius * 6)+(radius * 4)+(radius)+(radius * (0.25)))
self.goto((radius) * (0.25),(radius * 6)+(radius * 4)+(radius))
self.goto(0,(radius * 6)+(radius * 4)+(radius))
self.penup()
def leftEye(self, x=0, y=0, radius = 15, circle_color = "black"):
'''draw left eye'''
self.pendown()
self.circle(radius*(.25))
self.penup()
def rightEye(self, x=0, y=0, radius = 15, circle_color = "black"):
'''draw right eye'''
self.pendown()
self.circle(radius*(.25))
self.penup()
def bottomOfHat(self, x=0, y=0, radius = 15, circle_color = "black"):
''' draw the long part of the hat at the bottom '''
self.goto(0,(radius * 6)+(radius * 4)+(radius * 2))
self.pendown()
self.goto(-(radius),(radius * 6)+(radius * 4)+(radius * 2))
self.goto(-(radius),(radius * 6)+(radius * 4)+(radius * 2)+(radius * (0.5)))
self.goto(radius,(radius * 6)+(radius * 4)+(radius * 2)+(radius * (0.5)))
self.goto(radius,(radius * 6)+(radius * 4)+(radius * 2))
self.goto(0,(radius * 6)+(radius * 4)+(radius * 2))
self.penup()
def topOfHat(self, x=0, y=0, radius = 15, circle_color = "black"):
'''draw the top bigger part of the hat'''
self.goto(radius*(.75),(radius * 6)+(radius * 4)+(radius * 2)+(radius * (0.5)))
self.pendown()
self.goto(radius*(.75),(radius * 6)+(radius * 4)+(radius * 2)+(radius * 2))
self.goto(-(radius)*(.75),(radius * 6)+(radius * 4)+(radius * 2)+(radius * 2))
self.goto(-(radius)*(.75),(radius * 6)+(radius * 4)+(radius * 2)+(radius * (0.5)))
def bottomCircle(self, x=0, y=0, radius = 15, circle_color = "black"):
'''draws the bottom circle'''
self.pendown()
self.circle(radius * 3)
self.penup()
def middleCircle(self, x=0, y=0, radius = 15, circle_color = "black"):
'''draw the middle circle'''
self.pendown()
self.circle(radius * 2)
self.penup()
def topCircle(self, x=0, y=0, radius = 15, circle_color = "black"):
'''draw the top circle'''
self.pendown()
self.circle(radius)
self.penup()
def drawSnowman(self, x=0, y=0, radius = 15, circle_color = "black"):
self.bottomCircle()
self.goto(0,radius * 6)
self.middleCircle()
self.goto(0,(radius * 6)+(radius * 4))
self.topCircle()
self.goto(-(radius) * (0.5),(radius * 6)+(radius * 4)+(radius))
self.leftEye()
self.goto((radius) * (0.5),(radius * 6)+(radius * 4)+(radius))
self.rightEye()
self.goto(0,(radius * 6)+(radius * 4)+(radius))
self.drawNose()
self.bottomOfHat()
self.topOfHat()
t = MyTurtle()
t.hideturtle()
radius = 15
t.drawSnowman(x = 25,y = 25,radius = 25)
this is a picture of the snowman when I use the parameters
t.drawsnowman(x = 25 y=25 radius = 25)
this is the snowman when I inuput no parameters t.drawsnowman()

Try going step-by-step and work out what your code actually does (or use a debugger).
If you call t.drawSnowman(), radius will 15.
You call bottomCircle() which will draw a circle with a radius of radius * 3 = 45
You move radius * 6 = 90 on the y axis (you're now "on top" of the circle)
You call middleCircle() which will a circle with a radius of radius * 2 = 30
...
Now, see what happens if you call your function with parameters:
If you call t.drawSnowman(x = 25,y = 25,radius = 25), radius will 25.
You call bottomCircle() which will draw a circle with a radius of radius * 3 = 45. Note how the local variable radius is 15, since it's the default value of that parameter, and you don't pass the value you passed to drawSnowman down to the bottomCircle method.
You move radius * 6 = 150 on the y axis (you're now far off of the circle)
You call middleCircle() which will a circle with a radius of radius * 2 = 30. Note how the local variable radius is 15, too.
...
So, you problem is that you pass in a value for radius, but you use that value only for moving the turtle in drawSnowman, not further down in any of the other functions.

Related

There is a code drawing a heart. How to insert a photo inside this figure so that the remaining background does not change?

There is a code drawing a heart. How to insert a photo inside this figure so that the remaining background does not change?
import time
import math
import turtle
def xt(t):
return 16 * math.sin(t) ** 3
def yt(t):
return 13 * math.cos(t) - 5 * \
math.cos(2 * t) - 2 * \
math.cos(3 * t) - \
math.cos(4 * t)
t = turtle.Turtle()
turtle.Screen().screensize(1040, 1080)
t.speed(1500)
turtle.colormode(255)
turtle.Screen().bgcolor(0, 0, 0)
time.sleep(2)
for i in range(300):
t.goto((xt(i) * 20, yt(i) * 20))
t.pencolor((255 - i) % 255, i % 255, (255 + i) // 2 % 255)
t.goto(0, 0)
t.hideturtle()
turtle.update()
turtle.mainloop()
We can use the combination of register_shape() and stamp() to place an image atop the drawing. Below is an example of doing this as well as some tweaks of your original code:
from math import sin, cos
from turtle import Screen, Turtle
def xt(t):
return 16 * sin(t) ** 3
def yt(t):
return 13 * \
cos(1 * t) - 5 * \
cos(2 * t) - 2 * \
cos(3 * t) - \
cos(4 * t)
screen = Screen()
screen.setup(1040, 1080)
screen.bgcolor('black')
screen.colormode(255)
screen.register_shape("picture.gif")
turtle = Turtle()
turtle.hideturtle()
turtle.speed('fastest')
for i in range(300):
turtle.goto((xt(i) * 20, yt(i) * 20))
turtle.pencolor((255 - i) % 255, i % 255, (255 + i) // 2 % 255)
turtle.home()
turtle.shape("picture.gif")
turtle.stamp()
screen.mainloop()

Stellar chart with Python

I came across this article. I wonder if it is possible to make a stellar chart with Python? (see picture).
I have had a look at the matplotlib and seaborn galleries, but apparently they do not have any built in function to create such a chart (neither radar charts).
Is there any way to draw a chart like this easily using Python?
Following is a rendition of a StellarChart, as per your specifications.
It is derived from a SpiderChart (a RadarChart) build with tkinter to answer an earlier question
You can see them both side by side hereunder:
It takes a list of tuples('label', score), with the score expressed as a percentage (value in the interval [0, 100]).
The number of data points adjusts to the data provided.
The scale of the chart can be adjusted.
import math
import tkinter as tk
class SpiderChart(tk.Canvas):
"""a canvas that displays datapoints as a SpiderChart
"""
width=500
height=500
def __init__(self, master, datapoints, concentrics=10, scale=200):
super().__init__(master, width=self.width, height=self.height)
self.scale = scale
self.center = self.width // 2, self.height // 2
self.labels = tuple(d[0] for d in datapoints)
self.values = tuple(d[1] for d in datapoints)
self.num_pts = len(self.labels)
self.concentrics = [n/(concentrics) for n in range(1, concentrics + 1)]
self.draw()
def position(self, x, y):
"""use +Y pointing up, and origin at center
"""
cx, cy = self.center
return x + cx, cy - y
def draw_circle_from_radius_center(self, radius):
rad = radius * self.scale
x0, y0 = self.position(-rad, rad)
x1, y1 = self.position(rad, -rad)
return self.create_oval(x0, y0, x1, y1, dash=(1, 3))
def draw_label(self, idx, label):
angle = idx * (2 * math.pi) / self.num_pts
d = self.concentrics[-1] * self.scale
x, y = d * math.cos(angle), d * math.sin(angle)
self.create_line(*self.center, *self.position(x, y), dash=(1, 3))
d *= 1.1
x, y = d * math.cos(angle), d * math.sin(angle)
self.create_text(*self.position(x, y), text=label)
def draw_polygon(self):
points = []
for idx, val in enumerate(self.values):
d = (val / 100) * self.scale
angle = idx * (2 * math.pi) / self.num_pts
x, y = d * math.cos(angle), d * math.sin(angle)
points.append(self.position(x, y))
self.create_polygon(points, fill='cyan')
def draw(self):
self.draw_polygon()
for concentric in self.concentrics:
self.draw_circle_from_radius_center(concentric)
for idx, label in enumerate(self.labels):
self.draw_label(idx, label)
class StellarChart(SpiderChart):
"""a canvas that displays datapoints as a StellarChart
"""
def draw_polygon(self):
points = []
da = math.pi / self.num_pts
b = .05 * self.scale
for idx, val in enumerate(self.values):
d = (val / 100) * self.scale
angle = idx * (2 * math.pi) / self.num_pts
x, y = d * math.cos(angle), d * math.sin(angle)
points.append(self.position(x, y))
xb, yb = b * math.cos(angle + da), b * math.sin(angle+da)
points.append(self.position(xb, yb))
self.create_polygon(points, width=3, outline='red', fill='pink', join=tk.ROUND)
data = [('stamina', 70), ('python-skill', 100), ('strength', 80), ('break-dance', 66), ('speed', 45), ('health', 72), ('healing', 90), ('energy', 12), ('libido', 100)]
root = tk.Tk()
stellar = StellarChart(root, data)
stellar.pack(side=tk.LEFT)
spider = SpiderChart(root, data)
spider.pack(side=tk.LEFT)
root.mainloop()
The Plotly library includes a starchart: https://plotly.com/python/radar-chart/

I am creating a class to calculate a cylinder and a method is giving me a issue

I have been creating a program to calculate a bunch of geometric shapes and I got this error while running the code bellow it:
def surface_area(self):
^
SyntaxError: invalid syntax
here is the code:
class Cylinder():
def __init__(self, radius, height):
self.radius = radius
self.height = height
def volume(self):
return pi * (self.radius ** 2) * self.height
def diameter(self):
volume = pi * (self.radius ** 2) * self.height
return 2 * sqrt(self.volume / (pi * self.height)
def surface_area(self):
return (2 * pi * self.radius * self.height) + (2 * pi * (self.radius ** 2))
def base_area(self):
return pi * self.radius ** 2
def lateral_surface_area(self):
return 2 * pi * self.radius * self.height
if someone can help that will be amazing.
There are a missing bracket in your code
def diameter(self):
volume = pi * (self.radius ** 2) * self.height
return 2 * sqrt(self.volume / (pi * self.height)
# ^ ^ ^ ^
# | open 2 close 2 |
# open open never closed
This is a simple mistake, in your diameter function the last line is missing a bracket, see return 2 * sqrt(self.volume / (pi * self.height), should be this return 2 * sqrt(self.volume / (pi * self.height)).
Notice the second bracket at the end.
You forgot a closing bracket here at line 11
return 2 * sqrt(self.volume / (pi * self.height)
class cylinder:
pi = 3.14
def __init__(self, height, radius):
self.radius = radius
self.height = height
def volume(self):
volume = self.height*3.14*self.radius**2
print('Volume of the cylinder is {}'. format(volume))
def surface_area(self):
area = 2*3.14*(self.radius)*(self.height)
print('Surface area of the cylinder is {}'. format(area))
c = cylinder(2,3)
c.surface_area()

How do I reset the screen in python turtle so that I can animate an object?

I am trying to draw a turtle picture that has a forest, mountains, and a cloud floating across the top of the screen.
I cannot import any modules that need to be downloaded, it must be native.
To animate an object on top of a background in python turtle, I need to draw the object, then redraw the background, and then redraw the object in a new position. The problem is, the code that I use to draw the background causes the trees and mountains to be in randomized positions (to look more natural). My setup() functions draw a random background. What I want to know is how do I redraw that exact same background in my main()?
Here is the code that I am using:
# Elan Shetreat-Klein, 4/9/2019, Project 4
# A program to draw a landscape
from shapes import *
import random
import time
def background():
s.bgcolor('#87ceeb')
turtle.pencolor('#402905')
draw_rectangle(-500, -350, 1000, 200, c='#402905')
def tree(x, scale, leaf_color, trunk_color):
y = -350 + 200 * scale
draw_rectangle(x, y, 30 * scale, 200 * scale, c=trunk_color)
draw_tri(x + 15 * scale, y + 25 * scale, 175 * scale, c=leaf_color)
draw_tri(x + 15 * scale, y + 100 * scale, 150 * scale, c=leaf_color)
draw_tri(x + 15 * scale, y + 175 * scale, 100 * scale, c=leaf_color)
def forest():
dark_greens = ['#006400', '#008000', '#556B2F', '#00611C', '#003300', '#004F00']
light_greens = ['#397D02', '#476A34', '#308014', '#3D8B37', '#00CD00', '#0AC92B']
tree_locations = 3 * [x for x in range(-500, 600, 100)]
random.shuffle(tree_locations)
draw_rectangle(-500, -150, 1000, 200, c='#3B5323')
for xPos in tree_locations:
Xvary = random.randrange(-50, 50)
Svary = random.randrange(60, 80) / 100
tree(xPos + Xvary, Svary, dark_greens[random.randrange(0, 5)], '#603311')
for xPos in tree_locations:
Xvary = random.randrange(-40, 40)
Svary = random.randrange(70, 90) / 100
tree(xPos + Xvary, Svary, light_greens[random.randrange(0, 5)], '#734A12')
def mountain_range():
mountX = [x for x in range(-450, 550, 150)]
random.shuffle(mountX)
mountain_colors = ['#6F4242', '#856363', '#8B6969']
for xPos in mountX:
Xvary = random.randrange(-25, 25)
Svary = random.randrange(90, 110) / 100
x = xPos + Xvary
side = 600 * Svary
y = -350 + (sqrt((3 * side ** 2) / 4)) // 2
draw_tri(x, y, side, c=mountain_colors[mountX.index(xPos) % 3])
def create_cloud():
global cloud
cloud = {}
for i in range(20):
x2, y2 = random.randrange(-90, 90), random.randrange(-25, 25)
cloud[x2] = y2
print(cloud)
def draw_cloud(x, y):
turtle.pu()
turtle.goto(x, y)
turtle.dot(100, 'white')
for x2, y2 in cloud.items():
turtle.goto(x2 + x, y2 + y)
size = abs((1 - (turtle.distance(x, y)//100)) * 100)
turtle.dot(size, 'white')
turtle.speed(0)
s = turtle.getscreen()
def setup():
turtle.tracer(0, 0)
s.title("Forest with mountains in the backround")
s.bgcolor('white')
background()
mountain_range()
forest()
def main():
create_cloud()
for xPos in range(-500, 500, 1):
setup()
draw_cloud(xPos, 300)
turtle.update()
time.sleep(0.0001)
main()
turtle.done()
The randomization is fairly simple, it just changes the size and X Position a little bit for each tree and mountain. I already figured out how to keep the same cloud, that's not the problem.
In the code, a new random background is redrawn upon itself, and it starts to slow down. When I used turtle.clear() or turtle.reset(), the screen kept on blinking blue, so I'm not sure what to do about that.
Any help is appreciated!
The difficulty you're in is due to using a single turtle. This can be done without completely redrawing the entire scene every time with some tricky monitoring of the undo buffer size -- undoing the drawing of just the cloud before redrawing it.
Or, it can be done more simply by allocating a second turtle just for drawing the cloud, and using clear() and draw_cloud() on that one turtle between updates, leaving the rest of the scenery intact. Below is your code reworked along these lines with other tweaks as well:
from shapes import *
from random import choice, randrange, shuffle
MOUNTAIN_COLORS = ['#6F4242', '#856363', '#8B6969']
DARK_GREENS = ['#006400', '#008000', '#556B2F', '#00611C', '#003300', '#004F00']
LIGHT_GREENS = ['#397D02', '#476A34', '#308014', '#3D8B37', '#00CD00', '#0AC92B']
def background():
screen.bgcolor('#87ceeb')
default_turtle.pencolor('#402905')
draw_rectangle(-500, -350, 1000, 200, c='#402905')
def tree(x, scale, leaf_color, trunk_color):
y = -350 + 200 * scale
draw_rectangle(x, y, 30 * scale, 200 * scale, c=trunk_color)
draw_tri(x + 15 * scale, y + 25 * scale, 175 * scale, c=leaf_color)
draw_tri(x + 15 * scale, y + 100 * scale, 150 * scale, c=leaf_color)
draw_tri(x + 15 * scale, y + 175 * scale, 100 * scale, c=leaf_color)
def forest():
tree_locations = 3 * [x for x in range(-500, 600, 100)]
shuffle(tree_locations)
draw_rectangle(-500, -150, 1000, 200, c='#3B5323')
for xPos in tree_locations:
Xvary = randrange(-50, 50)
Svary = randrange(60, 80) / 100
tree(xPos + Xvary, Svary, choice(DARK_GREENS), '#603311')
for xPos in tree_locations:
Xvary = randrange(-40, 40)
Svary = randrange(70, 90) / 100
tree(xPos + Xvary, Svary, choice(LIGHT_GREENS), '#734A12')
def mountain_range():
mountX = [x for x in range(-450, 550, 150)]
shuffle(mountX)
for xPos in mountX:
Xvary = randrange(-25, 25)
Svary = randrange(90, 110) / 100
x = xPos + Xvary
side = 600 * Svary
y = -350 + (sqrt((3 * side ** 2) / 4)) // 2
draw_tri(x, y, side, c=choice(MOUNTAIN_COLORS))
def create_cloud():
positions = []
for _ in range(20):
x, y = randrange(-90, 90), randrange(-25, 25)
positions.append((x, y))
return positions
def draw_cloud(x, y):
cloud_turtle.clear()
cloud_turtle.penup()
cloud_turtle.goto(x, y)
cloud_turtle.dot(100, 'white')
for x2, y2 in cloud:
cloud_turtle.goto(x2 + x, y2 + y)
size = abs((1 - (cloud_turtle.distance(x, y) // 100)) * 100)
cloud_turtle.dot(size, 'white')
def setup():
screen.title("Forest with mountains in the background")
background()
mountain_range()
forest()
def animate(xPos=-500):
draw_cloud(xPos, 300)
screen.update()
if xPos < 625: # have draw_cloud() return cloud width & replace this number
screen.ontimer(lambda x=xPos + 1: animate(x), 100)
else:
screen.tracer(True) # stop animation
screen = turtle.Screen()
screen.tracer(False)
default_turtle = turtle.getturtle()
default_turtle.hideturtle()
cloud_turtle = turtle.Turtle()
cloud_turtle.hideturtle()
cloud = create_cloud()
setup()
screen.update()
animate()
screen.exitonclick()
I changed the way your cloud is stored from a dictionary to a list of tuple positions as a dictionary isn't appropriate for this purpose.
There are several options: You could either make the random decisions before drawing and save all those decisions for redrawing or make the output of your random module deterministic by providing a seed. The second is the more hacky solution but requires less changes to your code.
Change the second line to: import random as really_random
Then, in your main loop, right before the call to setup() add a line like: random = really_random.Random(0). You may need this line also before create_cloud() so you have a reference to random.
If you want to change your background every time you execute the program, change the 0 to some other random seed. For example, your main could look like this:
def main():
my_random_seed = really_random.randint(0,10000000)
random = really_random.Random(my_random_seed)
create_cloud()
for xPos in range(-500, 500, 1):
random = really_random.Random(my_random_seed)
setup()
draw_cloud(xPos, 300)
turtle.update()
time.sleep(0.0001)

How to find the area and volume of Sphere and cylinder in same program in python

Task is to find the area and volume of the shapes. Consider the following shapes while designing the code: Sphere and Cylinder.
The class should have only one constructor. Also we should create a class called as Shape
Below is code i wrote and returning outputs, but how to use new class for shapes and inherit into test or the other way.
import math
#class Shapes
class Test:
def __init__(self, *args):
self.radius = args[0]
if (len(args) == 2):
self.height = args[1]
self.area = 0
self.volume = 0
return super().__init__()
def Area(self,val):
radius = self.radius
if (val == "Sphere"):
area = 4 * 3.14 * radius ** 2
elif (val =="Cylinder"):
height = self.height
area = ((2 * 3.14 * radius) * (radius + height))
else:
area = 0
return area
def Volume(self,val):
radius = self.radius
if (val == "Sphere"):
volume = (4/3) * (3.14 * radius ** 2)
elif (val == "Cylinder"):
height = self.height
volume = 3.14 * radius * radius * height
else:
volume = 0
return volume
def main():
cylinder=Test(2,4)
print('Cylinder area:',cylinder.Area(enter code here'Cylinder'))
print('Cylinder volume:',cylinder.Volume('Cylinder'))
sphere=Test(3)
print('Sphere area:',sphere.Area('Sphere'))
print('Sphere volume:',sphere.Volume('Sphere'))
if __name__=='__main__':
main()
as specified in the question:
Create a class Shape.
Derive a class Sphere and a class Cylinder from this class Shape.
Implement the calculation of volume and area for each shape.
Then, in order to use the shapes,
You need to first create a shape.
Then call the methods get_surface, or get_volume, on the shapes created. You do this with "dot" notation
The example here under does that.
import math
class Shape:
"""abstract class for shapes"""
def __init__(self, radius):
self.radius = radius
def get_surface(self):
raise NotImplementedError
def get_volume(self):
raise NotImplementedError
class Sphere(Shape): # <-- inherits from Shape
def __init__(self, radius):
Shape.__init__(self, radius) # <-- can also use super().__init__(radius)
def get_surface(self):
return 4 * math.pi * self.radius**2 # <-- use math.pi constant i/o hard coding the value of pi
def get_volume(self):
return math.pi * self.radius**3 * 4/3
class Cylinder(Shape): # <-- inherits from Shape
def __init__(self, radius, height):
Shape.__init__(self, radius) # <-- can also use super().__init__(radius)
self.height = height
def get_surface(self):
return 2 * math.pi * self.radius * self.height + 2 * math.pi * self.radius**2
def get_volume(self):
return math.pi * self.radius**2 * self.height
def main():
cyl = Cylinder(2, 4)
print('Cylinder area:', cyl.get_surface()) # <-- call the methods on the object
print('Cylinder volume:', cyl.get_volume())
sph = Sphere(5)
print('Sphere area:',sph.get_surface())
print('Sphere volume:',sph.get_volume())
if __name__=='__main__':
main()
output:
Cylinder area: 75.3982236862
Cylinder volume: 50.2654824574
Sphere area: 314.159265359
Sphere volume: 523.598775598

Categories