I'm new to this, but I'm trying to create a program that goes on a Random Walk in turtle and I have no idea what I'm doing.This is the program that I need to create Requirements, and this is what I have so far Code. I'm starting to get a little lost, and am wondering if I 'm headed towards the right direction or if i need to scrap it and start all over again
Thanks,
import turtle
import random
import math
def start():
myS = turtle.Screen()
myS.title("Random Walk")
border = 50
myWin.setworldcoordinates(-border, -border, border, border)
def go(heading, step_size):
turtle.setheading(heading)
turtle.forward(step_size)
def random_walk(step_size, steps):
angle = random.random() * 2 * math.pi
x = 0
y = 0
x = x + math.cos(angle)
y = y + math.sin(angle)
coord = (x, y)
for _ in range(steps):
go(random.choice(coord), step_size)
if __name__ == '__main__':
turtle.hideturtle()
turtle.speed('fastest')
random_walk(15, 1000)
Your random_walk function does way to many things; I think it grew over your head a little. What it should do for every step:
Calculate a random angle between 0 and 2*math.pi
Calculate x and y with the given formulas
Call turtle.goto(x,y) to go to these coordinates
Also there was a little typo in start.
import turtle
import random
import math
def start():
myS = turtle.Screen()
myS.title("Random Walk")
border = 50
myS.setworldcoordinates(-border, -border, border, border)
def go(heading, step_size):
turtle.setheading(heading)
turtle.forward(step_size)
def random_walk(steps):
x = 0
y = 0
for i in range(steps):
angle = random.random()*2*math.pi
x = x + math.cos(angle)
y = y + math.sin(angle)
turtle.goto(x,y)
if __name__=="__main__":
start()
random_walk(100)
Because this looks like a homework assignment I don't want to just fix your errors but instead give you pointers to the right solution. I will also hide hints behind spoilers...
if you run random_walk() with e.g. parameters random_walk(1, 1) your will notice that the direction of the walk will not appear random. Use some form of debugging to find out why that is
your go() functions expects an angle, look at what random.choice() produces
if you fix the issue number 1. you will see that the turtle will not draw a random line at all again
looks like the angle does not change every step. find a solution that updates the angle before each step!
units of angles: find out what unit setheading() expects: hint
your requirements mention the output of straight line distance and distance travelled. This somehow sounds like you need some form of tally variable (one or several). hint: if you read the turtle documentation carefully you might find a funtion that maybe makes this task easier
read the documentation for turtle.position().
Related
I've written this script to use the turtle module to replicate the Chaos Game I saw on Numberphile's channel. There are a large amount of dots being drawn to actually make it work well in a larger scale. I assume the large amount of dots is what causes the program to begin running slower after a bit and I was wondering if anyone could help me come up with a workaround for this.
I'm open for any kind of solution, as long as the controls remain the same and the number of vertexes can be any number above 3.
If someone doesn't know what the Chaos Game is, it's a game where you have polygon with any amount of vertexes. At first you place a dot inside the polygon, randomly choose one of the vertexes and draw a new dot halfway in-between the dot you just placed earlier and the randomly chosen vertex. You keep repeating this process and each time you'll use the newly drawn dot.
In this script I've also included a rule to make sure it doesn't choose the same vertex two times in a row to form nice fractals with more than 3 vertexes. 3 vertexes actually forms the Sierpinski triangle.
Here's a link to Numberphile's video: https://www.youtube.com/watch?v=kbKtFN71Lfs
As you can probably tell, I'm somewhat new to Python and coding in general.
Full code:
import turtle as t
import tkinter as tk
from tkinter import ttk
from random import randint
wn = t.Screen()
wn.colormode(255)
t.pu();t.ht();t.speed(0)
plist = []
l = 0
val = 0
pb=ttk.Progressbar(orient="horizontal",length=wn.window_width(),mode="determinate")
pb.pack(side=tk.BOTTOM)
pb["value"]=0
def Clear():
t.clear()
plist = []
def Dot(x, y):
t.goto(x, y)
t.dot(5, (0, 0, 255))
plist.append(t.pos())
def Run(x, y):
wn.onscreenclick(None)
wn.tracer(0, 0)
l = len(plist)
pb["maximum"]=l*1000
xyc = randint(0, l-1)
xyc_old = 0
for _ in range(l*10):
xyc = randint(0, l-1)
for i in range(100):
xyc = randint(0, l-1);
if l >= 4:
while xyc == xyc_old:
xyc = randint(0, l-1);
xyc_old = xyc;
t.goto((t.pos()[0]+plist[xyc][0])/2, (t.pos()[1]+plist[xyc][1])/2);
t.dot(2, (255, 0, 0));
pb["value"]+=1;
pb.update()
wn.update()
plist.clear()
wn.onscreenclick(Dot, btn=1)
wn.onscreenclick(Run, btn=3)
wn.onscreenclick(Dot, btn=1)
wn.onscreenclick(Run, btn=3)
wn.onkey(Clear, "c")
wn.listen()
wn.mainloop()
I feel like my coding style is very different from a lot of the people on here, but I hope that isn't an issue.
Thank you!
I assume the large amount of dots is what causes the program to begin
running slower after a bit and I was wondering if anyone could help me
come up with a workaround for this.
Surprisingly, no. It's your own instrumentation (progress bar) slowing you down. Comment out:
pb.update()
and watch what happens.
I feel like my coding style is very different from a lot of the people
on here, but I hope that isn't an issue.
It's an issue where it overlaps with bad coding style. E.g. lack of white space, use of semicolons, effective no-ops in the code, etc. My rework of your code:
from turtle import Screen, Turtle
import tkinter as tk
from tkinter import ttk
from random import randrange
def clear():
turtle.clear()
plist.clear()
def dot(x, y):
turtle.goto(x, y)
turtle.dot(5, 'blue')
plist.append(turtle.position())
def run(x, y):
screen.onscreenclick(None, btn=1)
screen.onscreenclick(None, btn=3)
screen.onkey(None, 'c')
length = len(plist)
flag = length >= 4
pb['maximum'] = length * 1000
xyc_old = 0
for _ in range(length * 100):
for _ in range(10):
xyc = randrange(length)
if flag:
while xyc == xyc_old:
xyc = randrange(length)
xyc_old = xyc
x, y = turtle.position()
dx, dy = plist[xyc]
turtle.goto((x + dx) / 2, (y + dy) / 2)
turtle.dot(2)
pb['value'] += 10
pb.update()
plist.clear()
pb['value'] = 0
screen.onscreenclick(dot, btn=1)
screen.onscreenclick(run, btn=3)
screen.onkey(clear, 'c')
plist = []
screen = Screen()
screen.tracer(False)
turtle = Turtle()
turtle.hideturtle()
turtle.setundobuffer(None)
turtle.color('red')
turtle.penup()
pb = ttk.Progressbar(orient='horizontal', length=screen.window_width(), mode='determinate')
pb.pack(side=tk.BOTTOM)
pb['value'] = 0
screen.onscreenclick(dot, btn=1)
screen.onscreenclick(run, btn=3)
screen.onkey(clear, 'c')
screen.listen()
screen.mainloop()
Other changes include:
The plist = [] in Clear() won't work without a global plist. Use plist.clear() instead.
You also need to disable (and reenable) wn.onkey(Clear, "c") during Run otherwise your user can break the program. You also need to disable the two mouse buttons independently.
You really want randrange(), not randint().
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'm interested in creating a new function, which let's the python turtle look at an object. So I just need a formula, which calculates the angle that are needed to let the turtle do that. (0 = look to right) Example:
coords of turtle: 100,0
coords of point to look at: 0,0
result: 180
But how to calculate that?
Thank you for hopefully coming answers
Assuming you have some point class already (I'm not familiar with Turtle but I assume you do) like so
class pt():
def __init__(self, x, y):
self.x = x
self.y = y
We can make two points
>>> ptA = pt(10, 10)
>>> ptB = pt(0, 0)
Then you can simply use inverse tangent with some geometry to find the angle between those points
def findAngle(pt1, pt2):
import math
dy = pt2.y - pt1.y
dx = pt2.x - pt1.x
if dx == 0:
return 180.0
else:
return math.atan2(dy, dx) * 180.0 / math.pi
Testing
>>> findAngle(ptB, ptA)
45.0
>>> findAngle(ptA, ptB)
-135.0
Now as far as your question is concerned: The amount your turtle has to turn will depend on which way he was originally facing. The above method can find the orientation from the first point to the second, but you'll need to know the turtle's current orientation to know which way they need to turn to get there.
I'm using Python Turtles to draw a circle using forward() and right().
I have a for loop counting from 0 to 359, and each time it triggers, it moves the turtle forward 1 and right 1.
But the problem is I need specific diameters. I am nearly 100% sure I'll need to use trig, but I've tried to no avail.
I can't figure out the math how to do it. We're supposed to use forward() and right(), NOT circle().
Thanks!
Here is a working example:
import turtle
import math
def circle(radius):
turtle.up()
# go to (0, radius)
turtle.goto(0,radius)
turtle.down()
turtle.color("black")
# number of times the y axis has been crossed
times_crossed_y = 0
x_sign = 1.0
while times_crossed_y <= 1:
# move by 1/360 circumference
turtle.forward(2*math.pi*radius/360.0)
# rotate by one degree (there will be
# approx. 360 such rotations)
turtle.right(1.0)
# we use the copysign function to get the sign
# of turtle's x coordinate
x_sign_new = math.copysign(1, turtle.xcor())
if(x_sign_new != x_sign):
times_crossed_y += 1
x_sign = x_sign_new
return
circle(100)
print('finished')
turtle.done()
Well, a complete circle is 360°, and you are planning on turning 360 times, so each turn should be:
right( 360 ° / 360 ), or
right(1)
The distance traveled will be one circumference, or π * diameter, so your forward might be:
forward( diameter * π / 360 )
I haven't tested this yet -- give it a try and see how it works.
This is one of the exercises in "Think Python," in chapter 4. It really is a horrible exercise to have this early in the book, especially with the "hint" given. I'm using forward and left here, but you can switch left with right.
You should have the polygon function:
def polygon(t, length, n):
for i in range(n):
bob.fd(length)
bob.lt(360 / n)
Then you create a circle function:
def circle(t):
polygon(t, 1, 360)
That will draw a circle, no radius needed. The turtle goes forward 1, then left 1 (360 / 360), 360 times.
Then, if you want to make the circle bigger, you calculate the circumference of the circle. The hint says:
Hint: figure out the circumference of the circle and make sure that
length * n = circumference.
Ok, so the formula for circumference = 2 * pi * radius. And the hint says length * n = circumference. n = 360 (number of sides/degrees). We have circumference, so we need to solve for length.
So:
def circle(t, r):
circumference = 2 * 3.14 * r
length = circumference / 360
polygon(t, length, 360)
Now, call the function with whatever radius you want:
circle(bob, 200)
I was looking at the wikipedia page for the Koch Snowflake (here) and was bothered by the all the examples all being in the logo/turtle style. So i set out to make my own that returned a list or coordinates.
My implementation is in python and i basically ripped off the python turtle implementation but replaced the turtle specific stuff with basic trig. It resulted in some ugly code. My challenge for you is to either improve my code or come up with a more elligant solution of your own. It can be in python, or your favorite language.
My Code:
from math import sin, cos, radians
def grow(steps, length = 200, startPos = (0,0)):
angle = 0
try:
jump = float(length) / (3 ** steps)
except:
jump = length
set="F"
for i in xrange(steps): set=set.replace("F", "FLFRFLF")
coords = [startPos]
for move in set:
if move is "F":
coords.append(
(coords[-1][0] + jump * cos(angle),
coords[-1][1] + jump * sin(angle)))
if move is "L":
angle += radians(60)
if move is "R":
angle -= radians(120)
return coords
EDIT: due to lazy copying, i forgot the import
I don't see it as particularly ugly and I'd only refactor it incrementally, e.g. as a first step (I've removed the try/except because I don't know what you're trying to ward against... if it needs to get back in it should be a bit more explicit, IMHO):
import math
angles = [math.radians(60*x) for x in range(6)]
sines = [math.sin(x) for x in angles]
cosin = [math.cos(x) for x in angles]
def L(angle, coords, jump):
return (angle + 1) % 6
def R(angle, coords, jump):
return (angle + 4) % 6
def F(angle, coords, jump):
coords.append(
(coords[-1][0] + jump * cosin[angle],
coords[-1][1] + jump * sines[angle]))
return angle
decode = dict(L=L, R=R, F=F)
def grow(steps, length=200, startPos=(0,0)):
pathcodes="F"
for i in xrange(steps):
pathcodes = pathcodes.replace("F", "FLFRFLF")
jump = float(length) / (3 ** steps)
coords = [startPos]
angle = 0
for move in pathcodes:
angle = decode[move](angle, coords, jump)
return coords
If a second step was warranted I'd probably roll this functionality up into a class, but I'm not sure that would make things substantially better (or, better at all, in fact;-).
I liked your question so much that I posted an answer to it as a new question, so that other people could improve it:
https://stackoverflow.com/questions/7420248
I used no Logo/Turtle stuff, neither trigonometry.
Congrats for being the first one bringing this problem to StackOverflow!
Mathematica is superior when it comes to math stuff:
points = {{0.0, 1.0}};
koch[pts_] := Join[
pts/3,
(RotationMatrix[60 Degree].#/3 + {1/3, 0}) & /# pts,
(RotationMatrix[-60 Degree].#/3 + {1/2, 1/Sqrt[12]}) & /# pts,
(#/3 + {2/3, 0}) & /# pts
];
Graphics[Line[Nest[koch, points, 5]], PlotRange -> {{0, 1}, {0, 0.3}}] //Print
Something to consider, if not for your implementation then for testing your implementation, is that Python turtle can record what it's doing and give you back the coordinates. You use begin_poly() and end_poly() around the code you want to record and then use get_poly() afterwards to get the points.
In this example, I'll draw the snowflake based on code from this site then register those coordinates back as a new turtle shape that I'll randomly (and quickly) stamp about the screen:
import turtle
from random import random, randrange
def koch_curve(turtle, steps, length):
if steps == 0:
turtle.forward(length)
else:
for angle in [60, -120, 60, 0]:
koch_curve(turtle, steps - 1, length / 3)
turtle.left(angle)
def koch_snowflake(turtle, steps, length):
turtle.begin_poly()
for _ in range(3):
koch_curve(turtle, steps, length)
turtle.right(120)
turtle.end_poly()
return turtle.get_poly()
turtle.speed("fastest")
turtle.register_shape("snowflake", koch_snowflake(turtle.getturtle(), 3, 100))
turtle.reset()
turtle.penup()
turtle.shape("snowflake")
width, height = turtle.window_width() / 2, turtle.window_height() / 2
for _ in range(24):
turtle.color((random(), random(), random()), (random(), random(), random()))
turtle.goto(randrange(-width, width), randrange(-height, height))
turtle.stamp()
turtle.done()
You can have the pen up and turtle hidden during polygon generation if you don't want this step to be seen by the user.