TurtleGraphics Python - 将随机移动的乌龟限制在一个圆圈中?

发布于 2024-08-05 18:16:58 字数 806 浏览 7 评论 0原文

如何才能将随机移动的乌龟限制在半径为 50 的圆内,圆心位于 (0, 0)?因此,如果海龟当前位于位置 (x, y),则它距中心的距离为 math.sqrt(x ** 2 + y ** 2)。当海龟距离中心的距离超过 50 时,让它转身继续。我已经获得了处理屏幕尺寸的代码,但是我应该将 math.sqrt(x ** 2 + y ** 2) 放在哪里才能将其限制在一个圆圈中?这是我到目前为止的代码:

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)

该代码适用于屏幕中的乌龟,但不适用于圆圈中的乌龟。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

难如初 2024-08-12 18:16:58

你在编码的地方:

   if -width/2 <= x <= width/2 and -height/2 <= y <= height/2:

你真正的意思是“如果点(x,y)在允许的区域内”。因此,当“允许的区域”是“以原点为中心半径为 50 的圆”时,比较距离和半径的平方(这比取平方根更清楚......!-)你会得到:

   if (x*x + y*y) <= 50*50:

留下所有其余的你的代码不变。

编辑:由于OP评论说这对他不起作用,我将 if/else 更改为:

   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)

并将其作为 bounded_random_walk(200, 10, 30) 从Mac OS X 上的 Terminal.App,以便显示print。结果是我得到了大约 50 到 60 个“弹跳”的打印,并且乌龟显然被限制在所需的圆圈内,正如逻辑和几何学也说的那样。

因此,我希望OP能够沿着这些思路编辑自己的答案(最好是在一个系统上,并且在一个安排中,他可以看到 print 的结果或其他提供输出的方式,并理想地向我们展示它们)这样我就可以帮助他调试他的代码。

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.

神仙妹妹 2024-08-12 18:16:58

关于此代码的建议修复是否有效的不同意见引起了我的兴趣。我用 @AlexMartelli 的更改运行了 @user176073 的代码 1000 步,奇怪的事情确实发生了——为了说明这一点,我添加了一个红色的边界圆,海龟应该(大致)停留在:

在此处输入图像描述

耀斑发生在多次运行中,似乎与海龟离开后试图将其带回圆圈的校正逻辑有关。在乌龟应用了新角度后,它的应用是错误的——导致乌龟离开圆圈的不是原始角度的 180 度,因此它往往会稍微徘徊,直到它回到圆圈内。

我尝试了一个新的实现,进行了一些更改:在校正之后而不是之前应用新的角度更新;使用 Python 3 海龟的撤消功能让海龟回到内部,而不是尝试自己做。这是结果:

在此处输入图像描述

更新后的代码:

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()

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:

enter image description here

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:

enter image description here

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文