4
\$\begingroup\$

I have an homework as follows:

Write a program where you enter from the keyboard a number n. Then n stars are drawn onto the screen, circling around the center of your screen. You can assume that 1 < n < 20.

The solution I came up with is below.

import turtle

window=turtle.Screen()
window.screensize(1200,1200)

draw=turtle.Turtle()
draw.pensize(2)

draw.speed('fastest')

angle = [36,144,144,144,144]

GetNumber = int(input("Enter a number: "))

while GetNumber <= 1 or GetNumber >= 20:
    print("Enter a number between from 2 to 19")
    GetNumber = int(input("Enter a number: "))

for shape in range(GetNumber):
    for i in angle:
        draw.left(i)
        draw.forward(180)
    draw.penup()
    draw.forward(60)
    draw.pendown()
    draw.left(170)

Is there any way to improve this code? I think my code is OK, but I believe there are perhaps more concise or better solutions (working faster perhaps?)

Perhaps angle (currently 170) should be changed or perhaps an dynamic angle changer code can be implemented for the sake of improving the solutions. What do you think?

\$\endgroup\$
1
  • \$\begingroup\$ Circling around the screen? What does that actually mean? I would put them all at the same distance from the center (and thus, if there are a lot of stars, I'd guess they would have a limited size so we can fit them all) or is it supposed to create some kind of spiral? [I'm working on my own implementation, I'll give comments about how to improve your code, the good habits to have, etc] \$\endgroup\$
    – jeromej
    May 18, 2014 at 21:32

3 Answers 3

6
\$\begingroup\$

It would be user friendly and make testing easier if the program accepted the input number as a command line argument too, for example:

import sys


def main():
    if sys.argv[1:]:
        num = int(sys.argv[1])
        if not is_valid_number(num):
            warn_invalid_number()
            sys.exit(1)
    else:
        num = prompt_valid_number()

    draw_stars_in_a_spiral(num)

if __name__ == '__main__':
    main()

While doing this, to avoid code duplication, I split the original functionality to multiple functions, which is a good practice in general anyway.

For validating the number, the N < var < M operator of Python is very handy:

def is_valid_number(num):
    return 1 < num < 20

Then the warning and prompting functions:

def warn_invalid_number():
    print("Number must between 2 to 19 (inclusive)")    


def prompt_number():
    return int(input("Enter a number: "))

When prompting the user until he gives a valid number, change to a while True loop to avoid the duplication when asking for a number:

def prompt_valid_number():
    while True:
        num = prompt_number()
        if is_valid_number(num):
            return num
        warn_invalid_number()

Finally, the main method to draw the stars:

def draw_stars_in_a_spiral(num):
    window = turtle.Screen()
    window.screensize(1200, 1200)

    draw = turtle.Turtle()
    draw.pensize(2)

    draw.speed('fastest')

    for _ in range(num):
        for angle in angles:
            draw.left(angle)
            draw.forward(180)
        draw.penup()
        draw.forward(60)
        draw.pendown()
        draw.left(170)

Some points to note:

  • I moved all the drawing operations here. If validation fails when invoking with command line parameters, there's no need to open a window and draw anything.
  • I replaced the unused shape variable in for shape in range(num) with _
  • I replaced the angle array with angles to be more intuitive, and the loop variable i with the more intuitive name angle
\$\endgroup\$
2
  • 1
    \$\begingroup\$ I would suggest using the argparse module instead of manually writing your own command-line parsing code \$\endgroup\$
    – mleyfman
    Aug 17, 2014 at 7:27
  • 1
    \$\begingroup\$ I agree, but that would be really taking it to a next level, and he didn't ask for command line parsing at all, not sure if he's interested at all \$\endgroup\$
    – janos
    Aug 17, 2014 at 9:06
2
\$\begingroup\$

I would extract the code which draws a single star in its own function. Also I think it is important that such function will draw a star centered in the current position and leaves the turtle in the same position it has found it.

Otherwise I think that the stars you are drawing are not centered exactly around the center of the screen... or at least it is not clear to me why they should.

\$\endgroup\$
1
\$\begingroup\$

is using turtle a requirement? otherwise you could use plotting libraries such as matplotlib:

import numpy as np
import matplotlib.pyplot as plt

plt.figure( figsize=(8, 8) ).patch.set_alpha( 0 )

theta = np.linspace( 0, 2 * np.pi, 16, endpoint=False)
x, y = np.cos( theta ), np.sin( theta )

plt.scatter( x, y, marker='*', s=1e3, edgecolors='Yellow' )
plt.axis( 'off' )
plt.show( )

output for n=16

\$\endgroup\$
1
  • \$\begingroup\$ Yes. The assignment was about Turtle. However, thank you so much for informing me about this possibility! \$\endgroup\$
    – Rakanoth
    Dec 8, 2013 at 0:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.