简体   繁体   中英

Using turtle graphics to draw an n-pointed star

I am trying to create a program in Python that will draw n-pointed star. I am having problems with stars that have 6, 14, 22, ... points. I cannot figure out how to solve for that pattern.

Here is what I have so far:

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

If your problem is only condition then maybe you should use lists/tuples

elif x in (10, 18, 26):

elif x in (6, 14, 22):

but this doesn't check all possible values

So you will need more complex comparition but I don't see any pattern to recognize 10,18,26 or 6,14,22 - all of them are divided by 2 so using x % 2 is useless.

EDIT:

I see patterns

For list 6,14,22 I see

 6 + 8 = 14
14 + 8 = 22 

or in other way

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

and this gives if (x-6) % 8 == 0: ... or simpler if x % 8 == 6: ...

For list 10,18,26 I see

10 + 8 = 18
18 + 8 = 26

or in other way

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

and this gives if (x-10) % 8 == 0: ... or simpler if x % 8 == 10: ...


You draw stars using one polygon (one for -loop) but star 6 is created by two separated triangles (two polygons) so it need different method to draw.

在此处输入图片说明

But if you want to draw using only one for -loop then you should draw only external line (border) - and then you don't have to check x % 2 .

This code draw star for any value

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

在此处输入图片说明


EDIT:

Code which use for -loop to draw from 14 to 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()

Result:

在此处输入图片说明

It shows that stars have differnt sizes so code would have to calculate different values for forward() but at this moment I skip this problem. First I would have to calculate it on paper.


EDIT:

Code which I used to draw star 6 using two triangles ( red and green )

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

Another general approach is to calculate the coordinates of all the corner points and then connect them with goto() calls. Note that all the relevant points lie on two concentric circles. I recently answered a question about how to calculate regularly spaced points on a circle, so we could use that code here:

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

First, it is not clear what you mean by star. What I mean by star is a geometric figure whose lines crisscross; that starts from a point and returns to the starting point, and at no point does the pen drawing the figure lifts up from the paper.

You are correct about not being able to generate a 6-point star.

However, I am able to generate a 14-point star and a 22-point star.

十四点星

二十二尖星

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM