【问题标题】:Using turtle graphics to draw an n-pointed star使用海龟图形绘制 n 角星
【发布时间】:2021-06-19 23:19:45
【问题描述】:

我正在尝试在 Python 中创建一个可以绘制 n 角星的程序。我对有 6、14、22、... 点的星星有问题。我不知道如何解决这种模式。

这是我目前所拥有的:

from turtle import *

# Settings 
speed(5)
width(1)
color('red', 'yellow') # outline, fill

x=int(input('Enter the number of points you want the star to have.')) 

begin_fill()

# If a star has even number of points, then it needs to be drawn differently 
if x%4 == 0:
    for i in range(x):
        y=180-360/x
        right(y)
        forward(300)
        y+=360/x

# For special cases such as 10, 18, 26, ...
elif x%2 == 0:
    for i in range(x):
        y=90+180/x
        right(y)
        forward(300)

# For special cases such as 6, 14, 22, ... 
# I need help here (this condition needs to be changed)...
elif x%2 == 0:
    for i in range(x):
        y=2*180/x
        right(y)
        forward(300)

# For stars with odd number of points
else:
    for i in range(x):
        right(180-180/x)
        forward(300)

end_fill()

hideturtle()

exitonclick()

【问题讨论】:

  • 所以你想检查不是4的倍数的偶数?
  • 是的,但实际上是这些数字的一个子集。例如,10,18,26, ... 也不是 4 的倍数,但我找到了一种在该模式组中绘制星星的方法。但是,对于具有 6、14、22、... 点的星星,我似乎无法做到这一点。另外,有没有更优雅的方法来解决这个问题?
  • 首先在纸上绘制并手动计算角度 - 然后在代码中使用这些信息来计算角度。
  • 我认为您无法使用您的方法绘制这些星星 - 您使用单线/多边形绘制它,但星星 6 是由两个分开的三角形/多边形创建的。使用单线/多边形您应该只绘制没有内部元素的外部线。
  • @hilberts_drinking_problem 很好的例子:)

标签: python turtle-graphics python-turtle


【解决方案1】:

另一种通用的方法是计算所有角点的坐标,然后用goto()调用连接它们。请注意,所有相关点都位于两个同心圆上。我recently answered了一个关于如何计算圆上规则间隔点的问题,所以我们可以在这里使用该代码:

from turtle import *
import math


# Settings 
speed(5)
width(1)
color('red', 'yellow') # outline, fill

r_inner = 50   # inner radius
r_outer = 150  # outer radius
n = int(input('Enter the number of points you want the star to have.')) 

# Calculate coordinates of the points on the inner and outer circle
points_x_inner = []
points_y_inner = []
points_x_outer = []
points_y_outer = []

for i in range(n):
    angle = 2 * math.pi * i / n
    points_x_inner.append(r_inner * math.cos(angle))
    points_y_inner.append(r_inner * math.sin(angle))
    angle2 = angle + math.pi / n
    points_x_outer.append(r_outer * math.cos(angle2))
    points_y_outer.append(r_outer * math.sin(angle2))

# Connect the points with lines
penup()
goto([points_x_outer[-1], points_y_outer[-1]])
pendown()
begin_fill()

for x_in, y_in, x_out, y_out in zip(points_x_inner, 
                                    points_y_inner,
                                    points_x_outer,
                                    points_y_outer):
    goto([x_in, y_in])
    goto([x_out, y_out])

end_fill()
hideturtle()
exitonclick()

【讨论】:

  • 非常优雅的解决方案!非常感谢您的贡献。
【解决方案2】:

如果您的问题只是条件,那么也许您应该使用列表/元组

elif x in (10, 18, 26):

elif x in (6, 14, 22):

但这不会检查所有可能的值

因此您将需要更复杂的比较,但我没有看到任何模式可以识别 10,18,266,14,22 - 它们都被 2 划分,因此使用 x % 2 是没用的。

编辑:

我看到了模式

列表6,14,22我明白了

 6 + 8 = 14
14 + 8 = 22 

或其他方式

 6 = 6 + (8*0)
14 = 6 + (8*1)
22 = 6 + (8*2) 

这给出了if (x-6) % 8 == 0: ...或更简单的if x % 8 == 6: ...

对于列表10,18,26 我明白了

10 + 8 = 18
18 + 8 = 26

或其他方式

10 = 10 + (8*0)
18 = 10 + (8*1)
26 = 10 + (8*2)

这给出了if (x-10) % 8 == 0: ...或更简单的if x % 8 == 10: ...


您使用一个多边形(一个for-loop)绘制星星,但星星 6 是由两个分开的三角形(两个多边形)创建的,因此需要不同的绘制方法。

但如果您只想使用一个for-loop 进行绘制,那么您应该只绘制外部线(边框) - 然后您不必检查x % 2

此代码为任何值绘制星号

from turtle import *

# Settings 
speed(5)
width(1)
color('red', 'yellow') # outline, fill

#x = int(input('Enter the number of points you want the star to have.')) 
x = 6

begin_fill()

angle = (360/x)

print(x, angle)

for _ in range(x):
    forward(50)
    left(angle)  
    forward(50)
    right(2*angle)  # double angle

end_fill()

hideturtle()

exitonclick()

star 6

star 14


编辑:

使用for-loop 绘制从 14 到 5 的代码

from turtle import *

# Settings 
speed(5)
width(1)
color('red', 'yellow') # outline, fill

#x = int(input('Enter the number of points you want the star to have.')) 
for x in range(14, 4, -1):

    begin_fill()
    
    angle = (360/x)
    
    print(x, angle)
    
    for _ in range(x):
        forward(50)
        left(angle)  
        forward(50)
        right(2*angle)  # double angle
    
    end_fill()
    
hideturtle()

exitonclick()

结果:

它表明星星有不同的大小,因此代码必须为forward() 计算不同的值,但此时我跳过了这个问题。首先,我必须在纸上计算。


编辑:

我曾经使用两个trianglesredgreen)绘制star 6 的代码

from turtle import *

# --- functions ---

def triangle(width, outline):
    color(outline)

    for _ in range(3):
        forward(width)
        right(180-60)  

# --- main ---

width(2)

w = 150

triangle(w, 'red')

up()
forward(w//2)
left(90)
forward( (w//3 * (3**0.5)) / 2 )  # triangle: h = (a * sqrt(3)) / 2
right(90+(360/6))
down()

triangle(w, 'green')

hideturtle()
exitonclick()

【讨论】:

  • 非常感谢您提供非常详细的回答。为了解决您的第一句话:我知道我需要一种不同的方法来区分这两种模式,因为它们都是偶数(可被 2 整除),这就是为什么我在第二个 elif 语句上方写了一条评论,说下面的代码不正确并且需要改变(不同的方法)。谢谢你的代码!我也知道我只能使用轮廓或两个不同的多边形来绘制它,但我坚持尝试找到可以以与其他方式相同的方式绘制它们的解决方案。我想这是不可能的。
  • 列表6,14,22 是否有更多值?我看到这三个值的模式 - 6 = 6 +(8*0) 14 = 6 + (8*1)22 = 6 + (8*2) 所以他们都给了(x-6) % 8 == 0。对于数字10, 18, 26,我看到了模式(x-10) % 8 == 0
  • 我在答案的第一部分添加了模式 if x % 8 == 6:if x % 8 == 10: ...
【解决方案3】:

首先,不清楚您所说的星级是什么意思。我所说的星是一个几何图形,其线条纵横交错;从一点开始又回到起点,画图的笔在任何时候都不会从纸上抬起来。

关于无法生成 6 分星的说法是正确的。

但是,我能够生成一个 14 分的星和一个 22 分的星。

【讨论】:

    猜你喜欢
    • 2014-12-14
    • 2016-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-04
    相关资源
    最近更新 更多