【问题标题】:Python turtle graphics repeatedly goes 'out of bounds'Python海龟图形反复“越界”
【发布时间】:2018-09-24 15:28:52
【问题描述】:

我试图让 Turtle 在 python 中随机绘制用户指定数量的三角形。我在将乌龟保持在我定义的范围内时遇到了一些麻烦。例如,乌龟的边界是

border = 300

def drawBorder(border):
    t.pensize(3)
    x = 0
    while x <= 4:
        t.pendown()
        t.forward(border)
        t.left(90)
        t.penup()
        x = x + 1

绘制一个 300x300 的正方形。

下面的函数应该 - 当 X 或 Y 坐标 + 它要绘制的三角形的长度在边界之外 - 对于 前两次迭代尝试将海龟旋转 180 度(面对 相反的方向)并向前移动两倍的距离 最初打算将其向前推进。如果这不能带来乌龟 在边界范围内,乌龟应该回到中间 边界 - 在这种情况下,即 (150,150)。这并不总是 发生。由于一代的“随机”性质,大多数时候 乌龟最终在边界之外,尽管有时它确实绘制 边界内的所有三角形。

 if t.xcor() + lengthOfTriangle > border or t.xcor() + lengthOfTriangle < 0 or \
    t.ycor() + lengthOfTriangle > border or t.ycor() + lengthOfTriangle < 0:
x = 0
while x < 2:
    t.penup()
    t.left(180)
    t.forward(2 * lengthOfTriangle)
    t.pendown()
    x = x + 1
else:
    t.penup()
    if t.xcor() > border:
        t.seth(180)
    if t.xcor() < border:
        t.seth(0)
    t.forward(t.xcor() - (t.xcor() + border/2))
    if t.ycor() > border:
        t.seth(90)
    if t.ycor() < border:
        t.seth(270)
    t.forward(t.ycor() - (t.ycor() + border/2))

print("Turtle was going to be out of bounds. Xcor would be: ", t.xcor() + lengthOfTriangle,
      ". And Ycor would be: ", t.ycor() + lengthOfTriangle)
return drawFigureRec(numTriangles, lengthOfTriangle=random.randint(1, 20),
                     distanceTriangle=random.randint(1, 40),
                     angleTriangle=random.randint(0, 360), sum=sum)

如果您需要函数变量的上下文,我已经链接了一个 pastebin here

这是显示问题的图片。The turtle should stay within the 'bounds' (red square), but goes outside as shown by the console's output

【问题讨论】:

  • 你说的“让我的乌龟在界内有问题”到底是什么意思?
  • @martineau 我在原始帖子中添加了一张图片以进行澄清。
  • 抱歉,不,添加的图像确实没有多大帮助。界内究竟是什么意思?当海龟超出这些界限时应该发生什么,而目前正在发生什么?您还应该在您的问题中发布足够的代码(但只需要最少量的代码)来重现问题。见How to create a Minimal, Complete, and Verifiable Example
  • @martineau 我已经进一步澄清了这个问题。简而言之,当海龟超出绘制边界时,它应该首先尝试返回边界。如果它未能反转到边界,那么它将返回到边界的中间(在本例中为 150,150)。
  • 好的,这在一定程度上澄清了一些事情——至少足以让我看到一个问题......那就是当 drawFigureRec() 在 Turtle 将要出界并通过自身时调用自己时不同随机参数,假设它们会产生不同的结果。事实上,同样的越界情况可能会再次发生,这会导致它不断地一遍又一遍地调用自己。顺便说一句,为了轻松获得可重现的测试结果,我建议您在调用任何random.randint() 之前在脚本开头附近添加一个random.seed(42)(其中42 是一些整数常量)。

标签: python python-3.x recursion turtle-graphics


【解决方案1】:

您的代码存在几个问题。例如,这个边界检查逻辑完全忽略了海龟的当前航向:

   if t.xcor() + lengthOfTriangle > border or ... t.ycor() + lengthOfTriangle > border or ...

即它总是假设 +45 度,所以不能工作。你可以做 三角函数,或者,只需将海龟移动到新位置,然后 测试它是否超出范围。如果超出范围,您可以将其移回, 调整并重试。 turtle.undo() 方法在这里很有帮助。

您的 drawFigure*() 函数有时会显式返回值, 有时不是。一旦函数显式返回一个值,它应该 从所有出口点显式返回一个,而不是隐式返回 None 有时。

你的方形边框有五个边:

   x = 0
   while x <= 4:

由于最后一个重绘了第一个,这在视觉上并不明显。

让我们尝试一个更简单的迭代方法,我们使用turtle.circle() 来绘制我们的三角形,但在确定它是否在边界内时将每个三角形视为一个圆。我们还将使绘图居中,而不仅仅是使用右上象限和正数:

from turtle import Screen, Turtle
from random import randint

NUMBER_TRIANGLES = 80
PEN_SIZE = 3
BORDER = 300

def drawBorder(border):
    turtle.pensize(PEN_SIZE)

    turtle.penup()
    turtle.goto(-border/2, -border/2)
    turtle.pendown()

    for _ in range(4):
        turtle.forward(border)
        turtle.left(90)

    turtle.penup()
    turtle.home()

def drawFigure(numTriangles):
    if not 0 < numTriangles < 500:
        exit("Number of triangles is out of range!")

    for _ in range(numTriangles):

        radius = randint(3, 20)
        distance = randint(2, 60)

        turtle.forward(distance)

        while not(radius - BORDER/2 < turtle.xcor() < BORDER/2 - radius and radius - BORDER/2 < turtle.ycor() < BORDER/2 - radius):
            turtle.undo()  # undo last forward()
            turtle.left(37)  # rotate and try again (relative prime angle)
            distance += 1  # increase distance slightly on failure
            turtle.forward(distance)

        angle = randint(1, 360)
        turtle.setheading(angle)

        turtle.right(90)  # turtle represents center so need to adjust
        turtle.forward(radius)  # as turtle.circle() doesn't think that way
        turtle.left(90)

        turtle.pendown()
        turtle.circle(radius, steps=3)
        turtle.penup()

        turtle.left(90)  # undo adjustment to move turtle back to center
        turtle.forward(radius)
        turtle.right(90)

screen = Screen()
screen.tracer(False)

turtle = Turtle()
turtle.speed('fastest')

drawBorder(BORDER)
drawFigure(NUMBER_TRIANGLES)

turtle.hideturtle()

screen.tracer(True)
screen.mainloop()

我不会包含递归等价物,因为这确实不是递归问题。您可以根据您的任务要求将其强制为一个。

【讨论】:

    猜你喜欢
    • 2014-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    相关资源
    最近更新 更多