I made a program to explore the symmetries of an equilateral triangle using Python and Turtle Graphics. It's formatted using Black Playground.
As usual, my goal is to be writing "code that doesn't suck." What do I need to to to achieve that goal is this instance please?
I'm guessing some repetition could be avoided, and I know globals are evil, but are they as evil as passing parameters to a tkinter
callback?
Would the code benefit from refactoring to be entirely OOP, or would that be overkill for something so relatively simple?
import turtle
import tkinter as tk
screen = turtle.Screen()
class Label(turtle.Turtle):
def __init__(self, coordinates=[0, 0], screen=screen):
turtle.Turtle.__init__(self)
self.text = ""
self.color("white")
self.coordinates = coordinates
self.hideturtle()
self.penup()
self.screen = screen
def show(self, message, alignment="center", size=18):
self.screen.tracer(0)
self.clear()
self.goto(self.coordinates)
self.write(
message, font=("Arial", size), align=alignment
)
self.screen.tracer(1)
def show_labels(vertices):
global label1, label2, label3
label1.show(vertices[0])
label2.show(vertices[1])
label3.show(vertices[2])
def clear_labels():
global label1, label2, label3
label1.clear()
label2.clear()
label3.clear()
def reset():
global vertices, triangle
vertices = ["A", "B", "C"]
show_labels(vertices)
def rotate_clockwise():
global vertices, triangle
temp = vertices[-1]
for i in range(len(vertices) - 1, 0, -1):
vertices[i] = vertices[i - 1]
vertices[0] = temp
clear_labels()
triangle.right(120)
show_labels(vertices)
def rotate_anticlockwise():
global vertices, triangle
temp = vertices[0]
for i in range(len(vertices) - 1):
vertices[i] = vertices[i + 1]
vertices[-1] = temp
update_rotation()
def reflect_A():
global vertices
b_pos = vertices.index("B")
c_pos = vertices.index("C")
vertices[b_pos], vertices[c_pos] = (
vertices[c_pos],
vertices[b_pos],
)
update_reflection()
def reflect_B():
global vertices
a_pos = vertices.index("A")
c_pos = vertices.index("C")
vertices[a_pos], vertices[c_pos] = (
vertices[c_pos],
vertices[a_pos],
)
update_reflection()
def reflect_C():
global vertices
a_pos = vertices.index("A")
b_pos = vertices.index("B")
vertices[a_pos], vertices[b_pos] = (
vertices[b_pos],
vertices[a_pos],
)
update_reflection()
def update_rotation():
global triangle
clear_labels()
triangle.left(120)
show_labels(vertices)
def update_reflection():
global triangle
clear_labels()
show_labels(vertices)
def show_labels(vertices):
global label1, label2, label3
label1.show(vertices[0])
label2.show(vertices[1])
label3.show(vertices[2])
def clear_labels():
global label1, label2, label3
label1.clear()
label2.clear()
label3.clear()
canvas = screen.getcanvas()
font = ("Helvetica", 12)
reset_button = tk.Button(
canvas.master,
font=font,
text="Reset",
background="hotpink",
foreground="white",
bd=0,
command=reset,
)
canvas.create_window(0, -250, window=reset_button)
rotate_clockwise_button = tk.Button(
canvas.master,
font=font,
text="Rotate 120° clockwise",
background="hotpink",
foreground="white",
bd=0,
command=rotate_clockwise,
)
canvas.create_window(
0, -150, window=rotate_clockwise_button
)
rotate_anticlockwise_button = tk.Button(
canvas.master,
font=font,
text="Rotate 120° anticlockwise",
background="hotpink",
foreground="white",
bd=0,
command=rotate_anticlockwise,
)
canvas.create_window(
0, -200, window=rotate_anticlockwise_button
)
reflect_A_button = tk.Button(
canvas.master,
font=font,
text="Reflect about perp. bisector of BC",
background="hotpink",
foreground="white",
bd=0,
command=reflect_A,
)
canvas.create_window(0, 100, window=reflect_A_button)
reflect_B_button = tk.Button(
canvas.master,
font=font,
text="Reflect about perp. bisector of AC",
background="hotpink",
foreground="white",
bd=0,
command=reflect_B,
)
canvas.create_window(0, 150, window=reflect_B_button)
reflect_C_button = tk.Button(
canvas.master,
font=font,
text="Reflect about perp. bisector of AB",
background="hotpink",
foreground="white",
bd=0,
command=reflect_C,
)
canvas.create_window(0, 200, window=reflect_C_button)
screen.setup(500, 600)
screen.title("Symmetries of an Equilateral Triangle")
screen.bgcolor("blue")
label1 = Label([-85, -55])
label2 = Label([0, 75])
label3 = Label([85, -55])
triangle = turtle.Turtle("triangle")
triangle.shapesize(120 / 20)
triangle.color("hotpink")
triangle.right(30)
vertices = ["A", "B", "C"]
show_labels(vertices)
turtle.done()