问题
How would I be able to make a randomly moving turtle be constrained inside a circle with a radius of 50, the circles center being at (0, 0)? So if the turtle is currently at location (x, y), it's distance from the center is math.sqrt(x ** 2 + y ** 2). Whenever the turtle's distance from the center is more than 50, have it turn around and continue. I have gotten the code to work with the screen size, but where do I put math.sqrt(x ** 2 + y ** 2) to get it to be constrained in a circle? Here's the code I have so far:
import turtle, random, math
def bounded_random_walk(num_steps, step_size, max_turn):
turtle.reset()
width = turtle.window_width()
height = turtle.window_height()
for step in range(num_steps):
turtle.forward(step_size)
turn = random.randint(-max_turn, max_turn)
turtle.left(turn)
x, y = turtle.position()
if -width/2 <= x <= width/2 and -height/2 <= y <= height/2:
pass
else: # turn around!
turtle.left(180)
turtle.forward(step_size)
This code works for a turtle in the screen, but not in a circle.
回答1:
Where you're coding:
if -width/2 <= x <= width/2 and -height/2 <= y <= height/2:
you really mean "if point(x, y) is inside the permitted area". So, when "the permitted area" is "a circle with radius 50 centered at origin", comparing the squares of distances and radius (it's clearer than taking square roots...!-) you'd have:
if (x*x + y*y) <= 50*50:
leaving all the rest of your code unchanged.
Edit: since the OP commented that this doesn't work for him I changed the if/else to:
x, y = turtle.position()
# if -width/3 <= x <= width/3 and -height/3 <= y <= height/3:
if (x*x + y*y) <= 50*50:
pass
else: # turn around!
print 'Bounce', step, x, y
turtle.left(180)
turtle.forward(step_size)
and ran it as bounded_random_walk(200, 10, 30)
from a Terminal.App on Mac OS X so the print
would show. The result is I get about 50 to 60 prints of "Bounce" and the turtle clearly IS being bounded inside the desired circle, as logic and geometry also say it must.
So I hope the OP will edit their own answer along these lines (ideally on a system and in an arrangement where he can see the results of print
or some other way of giving output and ideally show them to us) so that I can help him debug his code.
回答2:
The difference in opinion on whether the suggested fix to this code works or not caught my interest. I ran @user176073's code with @AlexMartelli's changes for 1000 steps and odd things did happen -- to illustrate this I added a bounding circle in red that the turtle should stay (roughly) within:
The flare happened on multiple runs and seems to be related to the correction logic that tries to bring the turtle back into the circle once it leaves. It's incorrectly applied after the turtle has had a new angle applied -- it's not a 180 of the original angle that led the turtle out of the circle so it tends to wander a bit until it gets back inside.
I tried a new implementation with a couple of changes: apply the new angle update after the correction, not before; use Python 3 turtle's undo feature to get the turtle back inside rather than trying to do it myself. This is the result:
The updated code:
import turtle
import random
RADIUS = 50
def bounded_random_walk(num_steps, step_size, max_turn):
for _ in range(num_steps):
turtle.forward(step_size)
x, y = turtle.position()
if (x * x + y * y) > RADIUS * RADIUS:
turtle.undo() # undo misstep
turtle.left(180)
turn = random.randint(-max_turn, max_turn)
turtle.left(turn)
bounded_random_walk(1000, 10, 30)
turtle.exitonclick()
来源:https://stackoverflow.com/questions/1452311/turtlegraphics-python-constraining-random-moving-turtle-in-a-circle