3
\$\begingroup\$

I'm very new to python and programming in general. For a school assignment, I made this Memory Game and would love to receive feedback from you guys.

import tkinter as tk # imports tkinter as tk
from tkinter import font as tkfont # imports font as tkfont
import random # imports random
import string # imports string
import sys # imports sys
import time # imports time
import pygame # imports pygame (enables me to use its functions)
pygame.mixer.pre_init(44100, 16, 2, 4096) # Enables me to use music in pygame
pygame.init() # Enables me to use music in pygame
button_click = pygame.mixer.Sound('151022__bubaproducer__laser-shot-silenced.wav')
# Loads '151022__bubaproducer__laser-shot-silenced.wav' file
button_click2 = pygame.mixer.Sound('Mario Coin.wav') # Makes button_click2 play 'Mario Coin.wav' file
 pygame.mixer.music.load('merge_from_ofoct.mp3') # Loads my music file
 pygame.mixer.music.play(-1) # -1 plays the song infinitely
 pygame.mixer.music.set_volume(0.8) # Sets the volume of the music
def logout_logout(): # Defines logout_logout
 entUsername.delete(0, tk.END) # Deletes past entry's in the Username entry box
 entPassword.delete(0, tk.END) # Deletes past entry's in the Password entry box
 entUsername.focus_set() # Makes it so the Username entry box is targeted
def play_music1(): # Defines play_music1
 pygame.mixer.music.load('merge_from_ofoct.mp3') # Loads 'merge_from_ofoct.mp3' file
 pygame.mixer.music.play(-1) # Makes the song play infinitely
 pygame.mixer.music.set_volume(0.8) # Sets the volume (volume can be adjusted from 0-1)
def play_music2(): # Defines play_music2
 pygame.mixer.music.load('251461__joshuaempyre__arcade-music-loop.wav')
 # Loads '251461__joshuaempyre__arcade-music-loop.wav3' file
 pygame.mixer.music.play(-1) # Makes the song play infinitely
 pygame.mixer.music.set_volume(0.8) # Sets the volume (volume can be adjusted from 0-1)
def play_music3(): # Defines play_music3
 pygame.mixer.music.load('Off Limits.wav') # Loads 'Off Limits.wav') file
 pygame.mixer.music.play(-1) # Makes the song play infinitely
 pygame.mixer.music.set_volume(0.8) # Sets the volume (volume can be adjusted from 0-1)
def play_music4(): # Defines play_music4
 pygame.mixer.music.load('Pim Poy.wav') # Loads 'Pim Poy.wav') file
 pygame.mixer.music.play(-1) # Makes the song play infinitely
 pygame.mixer.music.set_volume(0.8) # Sets the volume (volume can be adjusted from 0-1)
def play_music5(): # Defines play_music5
 pygame.mixer.music.load('Puzzle-Game.mp3') # Loads 'Puzzle-Game.mp3') file
 pygame.mixer.music.play(-1) # Makes the song play infinitely
 pygame.mixer.music.set_volume(0.8) # Sets the volume (volume can be adjusted from 0-1)
def return_to_main_menu2(): # Defines return_to_main_menu2
 pygame.mixer.Sound.play(button_click2).set_volume(0.8) # Plays button_click2/sets the volume of the song
def return_to_main_menu(): # Defines return_to_main_menu
 pygame.mixer.Sound.play(button_click).set_volume(0.6) # Plays button_click/sets the volume of the sound
def random_char(y): # Defines random_char
 return ''.join(random.choice(string.ascii_letters) for x in range(y))
x = (random_char(6)) # Spawns 6 random characters
word = x # Makes word=x

Class #1

class SampleApp(tk.Tk): # Class - Basically my Main hub
def __init__(self, *args, **kwargs): # Arguments is controller and kwargs are keyword arguments
 tk.Tk.__init__(self, *args, **kwargs) # Arguments is controller and kwargs are keyword arguments
 self.geometry("1920x1080") # Size of the window when the programs run
 self.title("Memory Mania") # Puts "Memory Mania" in the top left of the window
 self.title_font = tkfont.Font(family='verdana', size=45, weight="bold", slant="italic")
 # Whenever i use use "font=controller.title_font", this font will be used
 container = tk.Frame(self) # Defines it
 container.pack(side="top", fill="both", expand=True) # Packs it
 container.grid_rowconfigure(0, weight=1) # Changes the size
 container.grid_columnconfigure(0, weight=1) # Changes the size
 self.frames = {} # Below this is all my classes, if the class isn't listed here it wont show
 for F in (Login, MainMenu, Tutorial, Tutorial2, Difficulty, Settings, Music, EasyDifficulty, MediumDifficulty,
 HardDifficulty, InsaneDifficulty, EnterCharacterScreen, CorrectScreen, IncorrectScreen, Level2,
 WinGameScreen):
 page_name = F.__name__ # Makes page_name = F._name_
 frame = F(parent=container, controller=self) # frame = F(parent=container, controller=self)
 self.frames[page_name] = frame # self.frame(page_name) = frame
 frame.grid(row=0, column=0, sticky="nsew") # the frames grid size
 self.show_frame("Login") # Shows the Login screen as the first screen
def show_frame(self, page_name): # Shows a frame for the given page name
 frame = self.frames[page_name] # Makes frame = self.frames(page_name)
 frame.tkraise() # Raises the frame

Class #2

class Login(tk.Frame): # Class - My Login screen
def __init__(self, parent, controller): # Defines the window
 tk.Frame.__init__(self, parent, bg="#2699C3") # Sets the background as that colour
 self.controller = controller # Makes self.controller = controller
 background_image = tk.PhotoImage(file="9a4a50632b464e426a71c800f80ad778.png")
 background_label = tk.Label(self, image=background_image)
 background_label.place(x=0, y=0, relwidth=1, relheight=1)
 background_label.image = background_image
 def login_button(): # Defines login_button
 controller.show_frame("MainMenu"), return_to_main_menu2()
 your_username = entUsername.get()
 username_label.configure(text=your_username)
 # Shows MainMenu and uses return_to_main_menu2 function
 def login_button2(event): # Defines login_button2 and marks it as an event
 controller.show_frame("MainMenu"), return_to_main_menu2()
 your_username = entUsername.get()
 username_label.configure(text=your_username)
 # Shows MainMenu and uses return_to_main_menu2 function
 lbl1 = tk.Label(self, text=" ", fg="white", bg="black") # Bg="#2699C3" is another form of blue
 # These labels are used to create blank spaces to centre my program
 lbl1.pack() # Packs the label wherever there's space
 lbl2 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl2.pack() # Packs the label wherever there's space
 lbl3 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl3.pack() # Packs the label wherever there's space
 lbl4 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl4.pack() # Packs the label wherever there's space
 lbl5 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl5.pack() # Packs the label wherever there's space
 lbl6 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl6.pack() # Packs the label wherever there's space
 lbl7 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl7.pack() # Packs the label wherever there's space
 lbl8 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl8.pack() # Packs the label wherever there's space
 lblUsername = tk.Label(self, text="Username:", fg="white", bg="black") # Makes the Label display Username
 lblUsername.place(anchor="center") # Centers the label
 global entUsername # Changes entUsername to a global variable (global variables can be used in all classes)
 entUsername = tk.Entry(self, justify="center") # Centers the entry box
 lblUsername.pack() # Packs it wherever there's space
 lblUsername.config(font=("Courier", 32)) # Changes the font/size
 entUsername.pack() # Packs it wherever there's space
 entUsername.config(font=("Courier", 32)) # Changes the font/size
 lblPassword = tk.Label(self, text="Password:", fg="white", bg="black") # Makes the Label display Password
 lblPassword.place(anchor="center") # Centers the label
 global entPassword # Changes entPassword to a global variable
 entPassword = tk.Entry(self, justify="center") # Centers the entry box
 lblPassword.pack() # Packs it wherever there's space
 lblPassword.config(font=("Courier", 32)) # Changes the font/size
 entPassword.pack() # Packs it wherever there's space
 entPassword.config(font=("Courier", 32)) # Changes the font/size
 entUsername.focus_set()
 entPassword.bind("<Return>", login_button2)
 btn = tk.Button(self, text="Login", fg="black", bg="lawn green", width=6, height=1, # Changes colour
 command=login_button) # Uses login_button function
 btn.pack(pady=10) # How many pixels to pad widget, vertically

Class #3

class MainMenu(tk.Frame): # Class - My Main Menu screen
def __init__(self, parent, controller): # Defines the window
 tk.Frame.__init__(self, parent, bg="#2699C3") # Sets the background as that colour
 self.controller = controller # Makes self.controller = controller
 label = tk.Label(self, text="Memory Mania", font=controller.title_font, bg="#2699C3")
 # Puts Memory Mania as a large Label
 label.pack(side="top", fill="x", pady=10) # Packs the label at the top of the program
 global username_label # Makes username_label a global variable
 label1 = tk.Label(self, text="Logged in as:", bg="#2699C3") # Changes colour
 label1.pack() # Packs the label wherever there's space
 username_label = tk.Label(self, text=" ", bg="#2699C3") # Users username is posted here
 username_label.pack() # Packs the label wherever there's space
 def get_answer2(event):
 if entry_characters.get() == word: # Tells program that if the entry of characters = the correct/incorrect
 controller.show_frame("CorrectScreen") # Show correct screen (if answer is correct)
 else:
 controller.show_frame("IncorrectScreen") # Show incorrect screen (if answer is wrong)
 def start_game():
 pygame.mixer.Sound.play(button_click).set_volume(0.6)
 controller.show_frame("Difficulty")
 entry_characters.bind("<Return>", get_answer2) # Makes you able to click enter
 button1 = tk.Button(self, text="Play", bg="#76EE00", fg="black", height=4, width=20, # Changes colour/size
 command=start_game)
 # Makes this button take me to the Difficulty screen and uses the 'return_to_main_menu' function
 button2 = tk.Button(self, text="Tutorial", bg="yellow", fg="black", height=4, width=20, # Changes colour/size
 command=lambda: [controller.show_frame("Tutorial"), return_to_main_menu()])
 # Makes this button take me to the Tutorial screen and uses the 'return_to_main_menu function'
 button3 = tk.Button(self, text="Settings", bg="#00EEEE", fg="black", height=4, width=20, # Changes colour/size
 command=lambda: [controller.show_frame("Settings"), return_to_main_menu()])
 # Makes this button take me to the Settings screen and uses the 'return_to_main_menu function'
 button4 = tk.Button(self, text="Logout", bg="orange", fg="black", height=4, width=20, # Changes colour/size
 command=lambda: [controller.show_frame("Login"), logout_logout()])
 # Makes this button take me to the Login screen and uses the 'logout_logout' function
 button5 = tk.Button(self, text="Quit", bg="red", fg="black", height=4, width=20, cursor="pirate",
 # Changes colour/size/cursor
 command=sys.exit)
 # Makes this button Quit the program
 button1.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button1.config(font=("System", 10)) # Changes font/size
 button2.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button2.config(font=("System", 10)) # Changes font/size
 button3.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button3.config(font=("System", 10)) # Changes font/size
 button4.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button4.config(font=("System", 10)) # Changes font/size
 button5.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button5.config(font=("System", 10)) # Changes font/size

Class #4

class Tutorial(tk.Frame): # Class - My Tutorial screen
def __init__(self, parent, controller): # Defines the window
 tk.Frame.__init__(self, parent, bg="#2699C3") # Sets the background as that colour
 self.controller = controller # Makes self.controller = controller
 # These labels are used to create blank spaces to centre my program
 lbl1 = tk.Label(self, text=" ", fg="white", bg="#2699C3") # Changes colour of label
 lbl1.pack() # Packs it wherever there's space
 lbl2 = tk.Label(self, text=" ", fg="white", bg="#2699C3") # Changes colour of label
 lbl2.pack() # Packs it wherever there's space
 lbl3 = tk.Label(self, text=" ", fg="white", bg="#2699C3") # Changes colour of label
 lbl3.pack() # Packs it wherever there's space
 label = tk.Label(self, text="Tutorial (1)", font=controller.title_font, bg="#2699C3") # Changes font/colour
 label1 = tk.Label(self, text="Once you click the Play button you will be brought to the Difficulty screen",
 bg="#2699C3") # Changes text/colour
 label2 = tk.Label(self, text="Once you're in the Difficulty screen, you can select 1 of 4 Difficulties",
 bg="#2699C3") # Changes text/colour
 label3 = tk.Label(self, text="Easy, Medium, Hard, Insane, all which have 5 levels",
 bg="#2699C3") # Changes text/colour
 label.pack(side="top", fill="x", pady=10)
 # How many pixels to pad widget, vertically/horizontally and at the top
 label1.pack(side="top", fill="x", pady=10)
 # How many pixels to pad widget, vertically/horizontally
 label2.pack(side="top", fill="x", pady=10)
 # How many pixels to pad widget, vertically/horizontally
 label3.pack(side="top", fill="x", pady=10)
 # How many pixels to pad widget, vertically/horizontally
 label1.config(font=("System", 14)) # Changes font/size
 label2.config(font=("System", 14)) # Changes font/size
 label3.config(font=("System", 14)) # Changes font/size
 button1 = tk.Button(self, text="Next Page", bg="yellow", fg="black", height=4, width=20,
 # Changes colour/size of button
 command=lambda: [controller.show_frame("Tutorial2"), return_to_main_menu()])
 # Makes this button take me to Tutorial2 screen and uses the 'return_to_main_menu' function
 button2 = tk.Button(self, text="Return to Main Menu", bg="yellow", fg="black", height=4, width=20,
 # Changes colour/size of button
 command=lambda: [controller.show_frame("MainMenu"), return_to_main_menu()])
 # Makes this button take me to the Main Menu and uses the 'return_to_main_menu' function
 label4 = tk.Label(self, text="Note: Lowercase and Capital letters matter!", bg="#2699C3") # Changes colour
 label4.config(font=("System", 10)) # Changes font/size
 label4.pack(side="bottom", fill="x", pady=10) # How many pixels to pad widget, vertically/horizontal
 button1.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button1.config(font=("System", 10)) # Changes font/size
 button2.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button2.config(font=("System", 10)) # Changes font/size

Class #6

class Difficulty(tk.Frame): # Class - My Difficulty screen
def __init__(self, parent, controller): # Defines the window
 tk.Frame.__init__(self, parent, bg="#2699C3") # Sets the background as that colour
 self.controller = controller # Makes self.controller = controller
 label = tk.Label(self, text="Difficulty", font=controller.title_font, bg="#2699C3") # Changes font/colour
 label.pack(side="top", fill="x", pady=10) # How many pixels to pad widget, vertically/horizontally
 def wait_fifteen_seconds(): # Defines "wait_fifteen_seconds"
 label_check.configure(text="Level 1") # Configures the label to the level specified
 global seconds_to_wait # Changes "seconds_to_wait" to a global variable
 # Changes "seconds_to_wait" to a global variable meaning you can use it in all classes
 seconds_to_wait = 15 # Makes the screen change in 15 seconds
 entry_characters.delete(0, tk.END) # Gets rid of the past entry's
 x = (random_char(6)) # Generates 6 random characters
 global word # Changes "word" to a global variable
 word = x # Makes word=x
 label2_easy.configure(text=word) # Configures the label to show the "word" variable
 controller.show_frame("EasyDifficulty"), return_to_main_menu() # Displays the "EasyDifficulty screen"
 entry_characters.pack_forget() # Makes you unable to enter the characters before the screen appears
 app.update() # Updates the program
 time.sleep(seconds_to_wait) # Makes the program wait for however many seconds depending on difficulty
 controller.show_frame("EnterCharacterScreen") # Displays the "EnterCharacterScreen"
 entry_characters.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button_submit.pack(fill=tk.X, padx=80, pady=80, side=tk.BOTTOM)
 # How many pixels to pad widget, vertically/horizontally
 entry_characters.focus_set() # Automatically clicks the entry box
 def wait_ten_seconds(): # Defines "wait_ten_seconds"
 label_check.configure(text="Level 1 ") # Configures the label to the level specified
 global seconds_to_wait # Changes "seconds_to_wait" to a global variable
 # Changes "seconds_to_wait" to a global variable meaning you can use it in all classes
 seconds_to_wait = 10 # Makes the screen change in 10 seconds
 entry_characters.delete(0, tk.END) # Gets rid of the past entry's
 x = (random_char(6)) # Generates 6 random characters
 global word # Changes "word" to a global variable meaning you can use it in all classes
 word = x # Makes word=x
 label2_medium.configure(text=word) # Configures the label to show the "word" variable
 controller.show_frame("MediumDifficulty"), return_to_main_menu() # Displays the "MediumDifficulty screen"
 entry_characters.pack_forget() # Makes you unable to enter the characters before the screen appears
 app.update() # Updates the program
 time.sleep(seconds_to_wait) # Makes the program wait for however many seconds depending on difficulty
 controller.show_frame("EnterCharacterScreen") # Displays the "EnterCharacterScreen"
 entry_characters.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button_submit.pack(fill=tk.X, padx=80, pady=80, side=tk.BOTTOM)
 # How many pixels to pad widget, vertically/horizontally
 entry_characters.focus_set() # Automatically clicks the entry box
 def wait_five_seconds(): # Defines "wait_five_seconds"
 label_check.configure(text="Level 1 ") # Configures the label to the level specified
 global seconds_to_wait # Changes "seconds_to_wait" to a global variable
 # Changes "seconds_to_wait" to a global variable meaning you can use it in all classes
 seconds_to_wait = 5 # Makes the screen change in 5 seconds
 entry_characters.delete(0, tk.END) # Gets rid of the past entry's
 x = (random_char(6)) # Generates 6 random characters
 global word # Changes "word" to a global variable meaning you can use it in all classes
 word = x # Makes word=x
 label2_hard.configure(text=word) # Configures the label to show the "word" variable
 controller.show_frame("HardDifficulty"), return_to_main_menu() # Displays the "HardDifficulty screen"
 entry_characters.pack_forget() # Makes you unable to enter the characters before the screen appears
 app.update() # Updates the program
 time.sleep(seconds_to_wait) # Makes the program wait for however many seconds depending on difficulty
 controller.show_frame("EnterCharacterScreen") # Displays the "EnterCharacterScreen"
 entry_characters.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button_submit.pack(fill=tk.X, padx=80, pady=80, side=tk.BOTTOM)
 # How many pixels to pad widget, vertically/horizontally
 entry_characters.focus_set() # Automatically clicks the entry box
 def wait_two_seconds(): # Defines "wait_two_seconds"
 label_check.configure(text="Level 1") # Configures the label to the level specified
 global seconds_to_wait # Changes "seconds_to_wait" to a global variable
 # Changes "seconds_to_wait" to a global variable meaning you can use it in all classes
 seconds_to_wait = 2 # Makes the screen change in 2 seconds
 entry_characters.delete(0, tk.END) # Gets rid of the past entry's
 x = (random_char(6)) # Generates 6 random characters
 global word # Changes "word" to a global variable meaning you can use it in all classes
 word = x # Makes word=x
 label2_insane.configure(text=word) # Configures the label to show the "word" variable
 controller.show_frame("InsaneDifficulty"), return_to_main_menu() # Displays the "InsaneDifficulty screen"
 entry_characters.pack_forget() # Makes you unable to enter the characters before the screen appears
 app.update() # Updates the program
 time.sleep(seconds_to_wait) # Makes the program wait for however many seconds depending on difficulty
 controller.show_frame("EnterCharacterScreen") # Displays the "EnterCharacterScreen"
 entry_characters.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button_submit.pack(fill=tk.X, padx=80, pady=80, side=tk.BOTTOM)
 # How many pixels to pad widget, vertically/horizontally
 entry_characters.focus_set() # Automatically clicks the entry box
 button = tk.Button(self, text="Easy", bg="yellow", fg="black", height=4, width=20,
 command=wait_fifteen_seconds)
 # Makes button wait fifteen seconds/changes text/colour/size
 button1 = tk.Button(self, text="Medium", bg="#E99B15", fg="black", height=4, width=20, command=wait_ten_seconds)
 # Makes button wait ten seconds/changes text/colour/size
 button2 = tk.Button(self, text="Hard", bg="#C04141", fg="black", height=4, width=20, command=wait_five_seconds)
 # Makes button wait five seconds/changes text/colour/size
 button3 = tk.Button(self, text="Insane", bg="#FC0000", fg="black", height=4, width=20, command=wait_two_seconds)
 # Makes button wait two seconds/changes text/colour/size
 button4 = tk.Button(self, text="Back", bg="green", fg="black", height=4, width=20,
 command=lambda: [controller.show_frame("MainMenu"), return_to_main_menu()])
 # Makes this button take me to the MainMenu and uses the 'return_to_main_menu' function
 button.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button.config(font=("System", 10)) # Changes font/size
 button1.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button1.config(font=("System", 10)) # Changes font/size
 button2.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button2.config(font=("System", 10)) # Changes font/size
 button3.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button3.config(font=("System", 10)) # Changes font/size
 button4.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button4.config(font=("System", 10)) # Changes font/size

Class #7

class Settings(tk.Frame): # Class - My Settings screen
def __init__(self, parent, controller): # Defines the window
 tk.Frame.__init__(self, parent, bg="#2699C3") # Sets the background as that colour
 self.controller = controller # Makes self.controller = controller
 lbl1 = tk.Label(self, text=" ", fg="white", bg="#2699C3")
 lbl1.pack() # Packs the label wherever there's space
 lbl2 = tk.Label(self, text=" ", fg="white", bg="#2699C3") # Changes colour of label
 lbl2.pack() # Packs the label wherever there's space
 lbl3 = tk.Label(self, text=" ", fg="white", bg="#2699C3") # Changes colour of label
 lbl3.pack() # Packs the label wherever there's space
 label = tk.Label(self, text="Settings", font=controller.title_font, bg="#2699C3") # Changes font/colour
 label.pack(side="top", fill="x", pady=10) # How many pixels to pad widget, vertically/horizontally
 button1 = tk.Button(self, text="Pause Music", bg="red", fg="white", height=4, width=20, # Changes colour/size
 command=pygame.mixer.music.pause)
 # Pauses the current song
 button2 = tk.Button(self, text="Resume Music", bg="green", fg="white", height=4, width=20, # Colour/size
 command=pygame.mixer.music.unpause)
 # Resumes the current song
 button3 = tk.Button(self, text="Music", bg="yellow", fg="black",
 height=4, width=20, # Colour/size
 command=lambda: [controller.show_frame("Music"), return_to_main_menu()])
 # Makes this button take me to the Music screen and play the 'return_to_main_menu' function
 button = tk.Button(self, text="Back", bg="#00EEEE", fg="black", height=4, width=20, # Changes colour/size
 command=lambda: [controller.show_frame("MainMenu"), return_to_main_menu()])
 # Makes this button take me to the Main Menu and play the 'return_to_main_menu function
 label1 = tk.Label(self, text="Note: Music takes a few seconds to start up!", bg="#2699C3") # Changes colour
 label1.config(font=("System", 10)) # Changes font/size
 label1.pack(side="bottom", fill="x", pady=10) # How many pixels to pad widget, vertically/horizontally
 button1.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button1.config(font=("System", 10)) # Changes font/size
 button2.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button2.config(font=("System", 10)) # Changes font/size
 button3.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button3.config(font=("System", 10)) # Changes font/size
 button.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button.config(font=("System", 10)) # Changes font/size

Class #8

class Music(tk.Frame): # Class - My Music screen
def __init__(self, parent, controller): # Defines the window
 tk.Frame.__init__(self, parent, bg="#2699C3") # Sets the background as that colour
 self.controller = controller # Makes self.controller = controller
 label = tk.Label(self, text="Music", font=controller.title_font, bg="#2699C3") # Changes font/colour
 label.pack(side="top", fill="x", pady=10) # How many pixels to pad widget, vertically/horizontally
 button1 = tk.Button(self, text="Soundtrack 1", bg="#0000FF", fg="white", height=4, width=20,
 # Changes colour/size
 command=play_music1)
 # plays the function 'play_music1'
 button2 = tk.Button(self, text="Soundtrack 2", bg="#EE3B3B", fg="white", height=4, width=20,
 # Changes colour/size
 command=play_music2)
 # plays the function 'play_music2'
 button3 = tk.Button(self, text="Soundtrack 3", bg="#7AC5CD", fg="white", height=4, width=20,
 # Changes colour/size
 command=play_music3)
 # plays the function 'play_music3'
 button4 = tk.Button(self, text="Soundtrack 4", bg="#00C957", fg="white", height=4, width=20,
 # Changes colour/size
 command=play_music4)
 # plays the function 'play_music4'
 button5 = tk.Button(self, text="Soundtrack 5", bg="#FFB90F", fg="white", height=4, width=20,
 # Changes colour/size
 command=play_music5)
 # plays the function 'play_music5'
 button = tk.Button(self, text="Return", bg="#00EEEE", fg="black", height=4, width=20, # Changes colour/size
 command=lambda: [controller.show_frame("Settings"), return_to_main_menu()])
 button1.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button1.config(font=("System", 10)) # Changes font/size
 button2.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button2.config(font=("System", 10)) # Changes font/size
 button3.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button3.config(font=("System", 10)) # Changes font/size
 button4.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button4.config(font=("System", 10)) # Changes font/size
 button5.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button5.config(font=("System", 10)) # Changes font/size
 button.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button.config(font=("System", 10)) # Changes font/size

Class #9

class EasyDifficulty(tk.Frame): # Class - My EasyDifficulty screen
def __init__(self, parent, controller): # Defines the window
 tk.Frame.__init__(self, parent, bg="#2699C3") # Sets the background as that colour
 self.controller = controller # Makes self.controller = controller
 label_level = tk.Label(self, text="Level 1", bg="#2699C3") # Changes colour
 label_level.pack() # Packs the label wherever there's space
 label = tk.Label(self, text="Remember these characters", font=controller.title_font, bg="#2699C3")
 # Changes font/colour
 label.pack(side="top", fill="x", pady=10) # How many pixels to pad widget, vertically/horizontally
 global label2_easy # Global variable
 label2_easy = tk.Label(self, height=4, width=15, text=word) # Changes size, text = word
 label2_easy.config(font=("Courier", 64)) # Changes font/size
 label2_easy.pack() # Packs the label wherever there's space

Class #10

class MediumDifficulty(tk.Frame): # Class - My MediumDifficulty screen
def __init__(self, parent, controller): # Defines the window
 tk.Frame.__init__(self, parent, bg="#2699C3") # Sets the background as that colour
 self.controller = controller # Makes self.controller = controller
 label_level = tk.Label(self, text="Level 1", bg="#2699C3") # Changes colour
 label_level.pack() # Packs the label wherever there's space
 label = tk.Label(self, text="Remember these characters", font=controller.title_font, bg="#2699C3")
 # Changes font/colour
 label.pack(side="top", fill="x", pady=10) # How many pixels to pad widget, vertically/horizontally
 global label2_medium # Global variable
 label2_medium = tk.Label(self, height=4, width=15, text=word) # Changes size, text = word
 label2_medium.config(font=("Courier", 64)) # Changes font/size
 label2_medium.pack() # Packs the label wherever there's space

Class #11

class HardDifficulty(tk.Frame): # Class - My HardDifficulty screen
def __init__(self, parent, controller): # Defines the window
 tk.Frame.__init__(self, parent, bg="#2699C3") # Sets the background as that colour
 self.controller = controller # Makes self.controller = controller
 label_level = tk.Label(self, text="Level 1", bg="#2699C3") # Changes colour
 label_level.pack() # Packs the label wherever there's space
 label = tk.Label(self, text="Remember these characters", font=controller.title_font, bg="#2699C3")
 # Changes font/colour
 label.pack(side="top", fill="x", pady=10) # How many pixels to pad widget, vertically/horizontally
 global label2_hard # Global variable
 label2_hard = tk.Label(self, height=4, width=15, text=word) # Changes size, text = word
 label2_hard.config(font=("Courier", 64)) # Changes font/size
 label2_hard.pack() # Packs the label wherever there's space

Class #12

class InsaneDifficulty(tk.Frame): # Class - My InsaneDifficulty screen
def __init__(self, parent, controller): # Defines the window
 tk.Frame.__init__(self, parent, bg="#2699C3") # Sets the background as that colour
 self.controller = controller # Makes self.controller = controller
 label_level = tk.Label(self, text="Level 1", bg="#2699C3") # Changes colour
 label_level.pack() # Packs the label wherever there's space
 label = tk.Label(self, text="Remember these characters", font=controller.title_font, bg="#2699C3")
 # Changes font/colour
 label.pack(side="top", fill="x", pady=10) # How many pixels to pad widget, vertically/horizontally
 global label2_insane # Global variable
 label2_insane = tk.Label(self, height=4, width=15, text=word) # Changes size, text = word
 label2_insane.config(font=("Courier", 64)) # Changes font/size
 label2_insane.pack() # Packs the label wherever there's space

Class #13

class EnterCharacterScreen(tk.Frame): # Class - My EnterCharacterScreen
def __init__(self, parent, controller): # Defines the window
 tk.Frame.__init__(self, parent, bg="#2699C3") # Sets the background as that colour
 self.controller = controller # Makes self.controller = controller
 # These labels are used to create blank spaces to centre my program
 lbl1 = tk.Label(self, text=" ", fg="white", bg="#2699C3") # Changes colour of label
 lbl1.pack() # Packs label wherever there's space
 lbl2 = tk.Label(self, text=" ", fg="white", bg="#2699C3") # Changes colour of label
 lbl2.pack() # Packs label wherever there's space
 lbl3 = tk.Label(self, text=" ", fg="white", bg="#2699C3") # Changes colour of label
 lbl3.pack() # Packs label wherever there's space
 lbl4 = tk.Label(self, text=" ", fg="white", bg="#2699C3") # Changes colour of label
 lbl4.pack() # Packs label wherever there's space
 lbl5 = tk.Label(self, text=" ", fg="white", bg="#2699C3") # Changes colour of label
 lbl5.pack() # Packs label wherever there's space
 label = tk.Label(self, text="What were your characters?", font=controller.title_font, bg="#2699C3")
 # Changes font/colour
 label.pack(side="top", fill="x", pady=10) # How many pixels to pad widget, vertically/horizontally
 def get_answer(): # Defines get_answer
 if entry_characters.get() == word: # Tells program that if the entry of characters = the correct/incorrect
 controller.show_frame("CorrectScreen") # Show correct screen (if answer is correct)
 else:
 controller.show_frame("IncorrectScreen") # Show incorrect screen (if answer is wrong)
 def get_answer2(event): # Defines get_answer (event is needed so users can click enter when submitting)
 if entry_characters.get() == word: # Tells program that if the entry of characters = the correct/incorrect
 controller.show_frame("CorrectScreen") # Show correct screen (if answer is correct)
 else:
 controller.show_frame("IncorrectScreen") # Show incorrect screen (if answer is wrong)
 global entry_characters # Global variable
 entry_characters = tk.Entry(self, justify="center") # Centers the entry
 entry_characters.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 entry_characters.config(font=("Courier", 96)) # Changes the font/size
 entry_characters.bind("<Return>", get_answer2) # Makes you able to click enter
 global button_submit # Global variable
 button_submit = tk.Button(self, text="Submit", command=get_answer, height=4, width=20) # Changes size of button
 button_submit.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button_submit.config(font=("System", 10)) # Changes the font/size

Class #14

class CorrectScreen(tk.Frame): # Class - My CorrectScreen
def __init__(self, parent, controller): # Defines the window
 tk.Frame.__init__(self, parent, bg="green") # Sets the background as that colour
 self.controller = controller # Makes self.controller = controller
 # These labels are used to create blank spaces to centre my program
 lbl1 = tk.Label(self, text=" ", fg="white", bg="green") # Changes colour of label
 lbl1.pack() # Packs label wherever there's space
 lbl2 = tk.Label(self, text=" ", fg="white", bg="green") # Changes colour of label
 lbl2.pack() # Packs label wherever there's space
 lbl3 = tk.Label(self, text=" ", fg="white", bg="green") # Changes colour of label
 lbl3.pack() # Packs label wherever there's space
 lbl4 = tk.Label(self, text=" ", fg="white", bg="green") # Changes colour of label
 lbl4.pack() # Packs label wherever there's space
 label = tk.Label(self, text="CORRECT!!:)", font=controller.title_font, bg="green") # Changes font/colour
 label.pack(side="top", fill="x", pady=10) # How many pixels to pad widget, vertically/horizontally
 def next_level_two(): # Defines next_level_two
 label_check.configure(text="Level 2") # Shows Level 2 at the top
 entry_characters.delete(0, tk.END) # Makes it so last entry's are deleted
 x = (random_char(6)) # Displays 6 random characters
 global word # Global variable
 word = x # Word = x
 label2_level2.configure(text=word) # Text=word
 entry_characters.delete(0, tk.END) # Makes it so last entry's are deleted
 controller.show_frame("Level2") # Shows Level 2 screen
 app.update() # Updates program
 time.sleep(float(seconds_to_wait)) # Time program waits before changing to next screen
 controller.show_frame("EnterCharacterScreen") # Shows EnterCharacterScreen
 button_next_screen.configure(command=next_level_three) # Shows Level 3 screen
 button_lose.configure(command=difficulty_change) # Shows Difficulty screen
 button_tutorial_lose.configure(command=tutorial_show) # Shows Tutorial screen
 button_main_lose.configure(command=main_menu) # Shows Main Menu
 def next_level_three(): # Defines next_level_three
 label_check.configure(text="Level 3") # Shows Level 3 at the top
 button_next_screen.configure(command=next_level_four) # Shows Level 4 screen
 entry_characters.delete(0, tk.END) # Makes it so last entry's are deleted
 x = (random_char(6)) # Displays 6 random characters
 global word # Global variable
 word = x # Word = x
 label2_level2.configure(text=word) # Text=word
 entry_characters.delete(0, tk.END) # Makes it so last entry's are deleted
 controller.show_frame("Level2") # Shows Level 2 screen
 app.update() # Updates program
 time.sleep(float(seconds_to_wait)) # Time program waits before changing to next screen
 controller.show_frame("EnterCharacterScreen") # Shows EnterCharacterScreen
 def next_level_four(): # Defines next_level_four
 label_check.configure(text="Level 4") # Shows Level 4 at the top
 button_next_screen.configure(command=next_level_five) # Shows Level 5 screen
 entry_characters.delete(0, tk.END) # Makes it so last entry's are deleted
 x = (random_char(6)) # Displays 6 random characters
 global word # Global variable
 word = x # Word = x
 label2_level2.configure(text=word) # Text=word
 entry_characters.delete(0, tk.END) # Makes it so last entry's are deleted
 controller.show_frame("Level2") # Shows Level 2 screen
 app.update() # Updates program
 time.sleep(float(seconds_to_wait)) # Time program waits before changing to next screen
 controller.show_frame("EnterCharacterScreen") # Shows EnterCharacterScreen
 def next_level_five(): # Defines next_level_five
 entry_characters.bind("<Return>", win_game) # Makes you able to click enter
 label_check.configure(text="Level 5") # Shows Level 5 at the top
 entry_characters.delete(0, tk.END) # Makes it so last entry's are deleted
 x = (random_char(6)) # Displays 6 random characters
 global word # Global variable
 word = x # Word = x
 label2_level2.configure(text=word) # Text=word
 entry_characters.delete(0, tk.END) # Makes it so last entry's are deleted
 controller.show_frame("Level2") # Shows Level 2 screen
 app.update() # Updates program
 time.sleep(float(seconds_to_wait)) # Time program waits before changing to next screen
 controller.show_frame("EnterCharacterScreen") # Shows EnterCharacterScreen
 def get_answer_last_screen(): # Defines get_answer_last_screen
 if entry_characters.get() == word:
 # Tells program that if the entry of characters = the correct/incorrect
 controller.show_frame("WinGameScreen") # if answer is correct, WinGameScreen is shown
 else:
 controller.show_frame("IncorrectScreen") # if answer is incorrect, IncorrectScreen is shown
 button_submit.configure(command=get_answer_last_screen)
 # Upon pressing button will change screen to either WinGameScreen or IncorrectScreen
 global button_next_screen # Global variable
 button_next_screen = tk.Button(self, text="Progress to Next Level", bg="white", fg="black", height=4, width=20,
 # Changes colour/size
 command=next_level_two)
 # Uses the 'next_level_two' function
 def tutorial_show(): # Defines tutorial_show
 button_next_screen.configure(command=next_level_two) # Uses the 'next_level_two' function
 controller.show_frame("Tutorial") # Shows Tutorial screen
 def main_menu(): # Defines main_menu
 entUsername.focus_set() # Makes it so the Username entry box is targeted
 button_next_screen.configure(command=next_level_two) # Uses the 'next_level_two' function
 controller.show_frame("MainMenu") # Shows MainMenu
 def win_game(event): # Activated when user is on level 5
 controller.show_frame("WinGameScreen") # Shows the WinGameScreen
 def difficulty_change(): # Defines difficulty_change
 entUsername.focus_set() # Makes it so the Username entry box is targeted
 button_next_screen.configure(command=next_level_two) # Uses the 'next_level_two' function
 controller.show_frame("Difficulty") # Shows Difficulty screen
 button2 = tk.Button(self, text="Try a different difficulty", bg="white", fg="black", height=4, width=20,
 # Changes colour/size
 command=difficulty_change) 
 # Shows Difficulty screen and uses the 'difficulty_change' function
 button3 = tk.Button(self, text="Return to Main Menu", bg="white", fg="black", height=4, width=20,
 # Changes colour/size
 command=main_menu)
 # Shows Main Menu and uses the 'main_menu' function
 button_next_screen.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button_next_screen.config(font=("System", 10)) # Changes font/size
 button2.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button2.config(font=("System", 10)) # Changes font/size
 button3.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button3.config(font=("System", 10)) # Changes font/size

Class #15

class IncorrectScreen(tk.Frame): # Class - Incorrect Screen
def __init__(self, parent, controller): # Defines the window
 tk.Frame.__init__(self, parent, bg="red") # Sets the background as that colour
 self.controller = controller # Makes self.controller = controller
 # These labels are used to create blank spaces to centre my program
 lbl1 = tk.Label(self, text=" ", fg="white", bg="red") # Changes colour of label
 lbl1.pack() # Packs label wherever there's space
 lbl2 = tk.Label(self, text=" ", fg="white", bg="red") # Changes colour of label
 lbl2.pack() # Packs label wherever there's space
 lbl3 = tk.Label(self, text=" ", fg="white", bg="red") # Changes colour of label
 lbl3.pack() # Packs label wherever there's space
 lbl4 = tk.Label(self, text=" ", fg="white", bg="red") # Changes colour of label
 lbl4.pack() # Packs label wherever there's space
 label = tk.Label(self, text="INCORRECT!!:C", font=controller.title_font, bg="red") # Changes font/colour
 label.pack(side="top", fill="x", pady=10) # How many pixels to pad widget, vertically/horizontally
 def retry_lose(): # Defines retry_lose
 pygame.mixer.Sound.play(button_click).set_volume(0.6) # Sets the volume of 'button_click' function
 controller.show_frame("Difficulty") # Shows Difficulty screen
 entUsername.focus_set() # Makes it so the Username entry box is targeted
 global button_lose # Global variable
 button_lose = tk.Button(self, text="Retry on a different difficulty", bg="white", fg="black", height=4,
 # Changes size/colour
 width=20, command=retry_lose)
 # Shows Difficulty screen and uses the 'retry_lose' function
 def tutorial_lose(): # Defines retry_lose
 pygame.mixer.Sound.play(button_click).set_volume(0.6) # Sets the volume of 'button_click' function
 controller.show_frame("Tutorial") # Shows Tutorial screen
 entUsername.focus_set() # Makes it so the Username entry box is targeted
 global button_tutorial_lose # Global variable
 button_tutorial_lose = tk.Button(self, text="Review How to Play", bg="white", fg="black", height=4, width=20,
 # Changes size/colour
 command=tutorial_lose)
 # Uses the Tutorial screen and uses the 'tutorial_lose' function
 global button_main_lose # Global variable
 def main_lose(): # Defines main_lose
 pygame.mixer.Sound.play(button_click).set_volume(0.6) # Sets the volume of 'button_click' function
 controller.show_frame("MainMenu") # Shows MainMenu
 entUsername.focus_set() # Makes it so the Username entry box is targeted
 button_main_lose = tk.Button(self, text="Return to Main Menu", bg="white", fg="black", height=4, width=20,
 # Changes size/colour
 command=main_lose)
 # Shows MainMenu and uses the 'main_lose' function
 button_lose.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button_lose.config(font=("System", 10)) # Changes font/size
 button_tutorial_lose.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button_tutorial_lose.config(font=("System", 10)) # Changes font/size
 button_main_lose.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button_main_lose.config(font=("System", 10)) # Changes font/size

Class #16

class Level2(tk.Frame): # Class - Level2 Screen
def __init__(self, parent, controller): # Defines the window
 tk.Frame.__init__(self, parent, bg="#2699C3") # Sets the background as that colour
 self.controller = controller # Makes self.controller = controller
 label = tk.Label(self, text="Remember these characters", font=controller.title_font, bg="#2699C3")
 # Changes font/colour
 global label_check # Global variable
 label_check = tk.Label(self, text="Level 1", bg="#2699C3") # Changes colour of label
 label_check.pack() # Packs the label wherever there's space
 label.pack(side="top", fill="x", pady=10) # How many pixels to pad widget, vertically/horizontally
 global label2_level2 # Global variable
 label2_level2 = tk.Label(self, height=4, width=15, text=word) # Changes size, text=word
 label2_level2.config(font=("Courier", 64)) # Changes font/size
 label2_level2.pack() # Packs the label wherever there's space

Class #17

class WinGameScreen(tk.Frame): # Class - WinGameScreen
def __init__(self, parent, controller): # Defines the window
 tk.Frame.__init__(self, parent, bg="#2699C3") # Sets the background as that colour
 self.controller = controller # Makes self.controller = controller
 # These labels are used to create blank spaces to centre my program
 background_image2 = tk.PhotoImage(file="videogame-well-done-4k-a-videogame-screen-with-the-text-well-done-8-bit-retro-style-4k_hv0skuloke_thumbnail-full05.png")
 background_label2 = tk.Label(self, image=background_image2)
 background_label2.place(x=0, y=0, relwidth=1, relheight=1)
 background_label2.image = background_image2
 lbl1 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl1.pack() # Packs the label wherever there's space
 lbl2 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl2.pack() # Packs the label wherever there's space
 lbl3 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl3.pack() # Packs the label wherever there's space
 lbl4 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl4.pack() # Packs the label wherever there's space
 lbl5 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl5.pack() # Packs the label wherever there's space
 lbl6 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl6.pack() # Packs the label wherever there's space
 lbl7 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl7.pack() # Packs the label wherever there's space
 lbl8 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl8.pack() # Packs the label wherever there's space
 lbl9 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl9.pack() # Packs the label wherever there's space
 lbl10 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl10.pack() # Packs the label wherever there's space
 lbl11 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl11.pack() # Packs the label wherever there's space
 lbl12 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl12.pack() # Packs the label wherever there's space
 lbl13 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl13.pack() # Packs the label wherever there's space
 lbl14 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
 lbl14.pack() # Packs the label wherever there's space
 def get_answer_last_screen(): # Defines get_answer_last_screen
 if entry_characters.get() == word:
 # Tells program that if the entry of characters = the correct/incorrect
 controller.show_frame("WinGameScreen") # if answer is correct, WinGameScreen is shown
 else:
 controller.show_frame("IncorrectScreen") # if answer is incorrect, IncorrectScreen is shown
 def get_answer(): # Defines get_answer
 if entry_characters.get() == word: # Tells program that if the entry of characters = the correct/incorrect
 controller.show_frame("CorrectScreen") # Show correct screen (if answer is correct)
 else:
 controller.show_frame("IncorrectScreen") # Show incorrect screen (if answer is wrong)
 def get_answer2(event): # Defines get_answer
 if entry_characters.get() == word: # Tells program that if the entry of characters = the correct/incorrect
 controller.show_frame("CorrectScreen") # Show correct screen (if answer is correct)
 else:
 controller.show_frame("IncorrectScreen") # Show incorrect screen (if answer is wrong)
 def tutorial_show(): # Defines tutorial_show
 button_next_screen.configure(command=next_level_two) # Uses the 'next_level_two' function
 controller.show_frame("Tutorial") # Shows Tutorial screen
 def main_menu(): # Defines main_menu
 button_next_screen.configure(command=next_level_two) # Uses the 'next_level_two' function
 controller.show_frame("MainMenu") # Shows MainMenu
 def difficulty_change(): # Defines difficulty_change
 button_next_screen.configure(command=next_level_two) # Uses the 'next_level_two' function
 controller.show_frame("Difficulty") # Shows Difficulty screen
 def next_level_two(): # Defines next_level_two
 label_check.configure(text="Level 2") # Shows Level 2 at the top
 entry_characters.delete(0, tk.END) # Makes it so last entry's are deleted
 x = (random_char(6)) # Displays 6 random characters
 global word # Global variable
 word = x # Word = x
 label2_level2.configure(text=word) # Text=word
 entry_characters.delete(0, tk.END) # Makes it so last entry's are deleted
 controller.show_frame("Level2") # Shows Level 2 screen
 app.update() # Updates program
 time.sleep(float(seconds_to_wait)) # Time program waits before changing to next screen
 controller.show_frame("EnterCharacterScreen") # Shows EnterCharacterScreen
 button_next_screen.configure(command=next_level_three) # Shows Level 3 screen
 button_lose.configure(command=difficulty_change) # Shows Difficulty screen
 button_tutorial_lose.configure(command=tutorial_show) # Shows Tutorial screen
 button_main_lose.configure(command=main_menu) # Shows Main Menu
 def next_level_three(): # Defines next_level_three
 label_check.configure(text="Level 3") # Shows Level 3 at the top
 button_next_screen.configure(command=next_level_four) # Shows Level 4 screen
 entry_characters.delete(0, tk.END) # Makes it so last entry's are deleted
 x = (random_char(6)) # Displays 6 random characters
 global word # Global variable
 word = x # Word = x
 label2_level2.configure(text=word) # Text=word
 entry_characters.delete(0, tk.END) # Makes it so last entry's are deleted
 controller.show_frame("Level2") # Shows Level 2 screen
 app.update() # Updates program
 time.sleep(float(seconds_to_wait)) # Time program waits before changing to next screen
 controller.show_frame("EnterCharacterScreen") # Shows EnterCharacterScreen
 def next_level_four(): # Defines next_level_four
 label_check.configure(text="Level 4") # Shows Level 4 at the top
 button_next_screen.configure(command=next_level_five) # Shows Level 5 screen
 entry_characters.delete(0, tk.END) # Makes it so last entry's are deleted
 x = (random_char(6)) # Displays 6 random characters
 global word # Global variable
 word = x # Word = x
 label2_level2.configure(text=word) # Text=word
 entry_characters.delete(0, tk.END) # Makes it so last entry's are deleted
 controller.show_frame("Level2") # Shows Level 2 screen
 app.update() # Updates program
 time.sleep(float(seconds_to_wait)) # Time program waits before changing to next screen
 controller.show_frame("EnterCharacterScreen") # Shows EnterCharacterScreen
 def next_level_five(): # Defines next_level_five
 label_check.configure(text="Level 5")
 button_next_screen.configure(command=get_answer_last_screen) # Shows Level 5 at the top
 entry_characters.delete(0, tk.END) # Makes it so last entry's are deleted
 x = (random_char(6)) # Displays 6 random characters
 global word # Global variable
 word = x # Word = x
 label2_level2.configure(text=word) # Text=word
 entry_characters.delete(0, tk.END) # Makes it so last entry's are deleted
 controller.show_frame("Level2") # Shows Level 2 screen
 app.update() # Updates program
 time.sleep(float(seconds_to_wait)) # Time program waits before changing to next screen
 controller.show_frame("EnterCharacterScreen") # Shows EnterCharacterScreen
 def game_finished(): # Defines game_finished
 controller.show_frame("MainMenu"), return_to_main_menu() 
 # Shows MainMenu and uses the 'return_to_main_menu' function
 label_check.configure(text="Level 1") # Shows Level 1 at the top of the screen
 label2_easy.configure(text=word) # Configures the label so text=word for the corresponding difficulty
 label2_medium.configure(text=word) # Configures the label so text=word for the corresponding difficulty
 label2_hard.configure(text=word) # Configures the label so text=word for the corresponding difficulty
 label2_insane.configure(text=word) # Configures the label so text=word for the corresponding difficulty
 button_submit.configure(command=get_answer) # Uses the 'get_answer' function
 button_next_screen.configure(command=next_level_two) # Uses the 'next_level_two function
 button1 = tk.Button(self, text="Return to Main Menu", bg="yellow", fg="black", height=2, width=20,
 # Changes size/colour
 command=game_finished)
 # Shows MainMenu and uses the 'game_finished' function
 button1.pack(pady=10) # How many pixels to pad widget, vertically/horizontally
 button1.config(font=("System", 10)) # Changes font/size
 if __name__ == "__main__": # If _name="main":
 app = SampleApp() # Makes app = SampleApp
 app.mainloop() # Loops the program so it can stay open
asked Aug 9, 2018 at 11:09
\$\endgroup\$
4
  • \$\begingroup\$ There also a class called Tutorial2, which is the second page of it, but due to the limit of characters i was unable to add it in! \$\endgroup\$ Commented Aug 9, 2018 at 11:10
  • \$\begingroup\$ I also plan to add a leaderboards, a timer when each difficulty is selected, and an error message to appear if the user enters more than 6 characters or less than 6 (all of these im not sure how to do) \$\endgroup\$ Commented Aug 9, 2018 at 11:11
  • \$\begingroup\$ Also if you plan to play this game, youll need to download the corresponding music/images but to test it id just advise you to remove them! \$\endgroup\$ Commented Aug 9, 2018 at 11:12
  • 2
    \$\begingroup\$ Please fix your indentation, so that the classes actually contain their methods. Also enumerating your classes is not helpful at all. We all can count. \$\endgroup\$ Commented Aug 9, 2018 at 11:31

1 Answer 1

8
\$\begingroup\$

Most of your inline comments are useless

I see lots of comments like this:

def login_button(): # Defines login_button

That comment adds no information. It just adds visual "noise". I recommend removing all comments that simply state what the code does. Comments should explain why, and only if it's not obvious

Group your layout code separately from widget creation

In my experience, grouping all of your layout code together makes the code much easier to read, visualize, and maintain. For example, instead of this:

lbl1 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
lbl1.pack() # Packs the label wherever there's space
lbl2 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
lbl2.pack() # Packs the label wherever there's space
lbl3 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
lbl3.pack() # Packs the label wherever there's space
lbl4 = tk.Label(self, text=" ", fg="white", bg="black") # Changes colour of label
lbl4.pack() # Packs the label wherever there's space

Do it like this:

lbl1 = tk.Label(self, text=" ", fg="white", bg="black")
lbl2 = tk.Label(self, text=" ", fg="white", bg="black")
lbl3 = tk.Label(self, text=" ", fg="white", bg="black")
lbl4 = tk.Label(self, text=" ", fg="white", bg="black")
lbl1.pack()
lbl2.pack()
lbl3.pack()
lbl4.pack()

Don't repeat identical code

There's one section that creates 14 identical labels, and you have two blocks of 14 identical lines of code. In this case it would be much more efficient to use a loop:

labels = []
for i in range(14):
 label = (tk.Label(self, text=" ", fg="white", bg="black")
 label.pack()
 labels.append(label)

This makes your intention much more clear. Whereas before I had to read every line (well, every other line) to try to determine if the labels are identical or not, with the loop it's immediately obvious that I'm creating fourteen identical labels.

Use explicit options to pack

I see a lot of code like this:

lbl1.pack()

I find it to be much easier to understand your code if you add explicit options rather than relying on defaults. This isn't true in all cases, but for things like grid and pack where the defaults aren't always obvious, I find it good to be explicit. It's also good to explicitly spell out the fill and expand options. That way, as a reviewer I can look at the code and know your intention. When you rely on defaults I'm left wondering if you intended to rely on the defaults or if you forgot to fully configure things.

lbl1.pack(side="top", fill="both", expand=False). 

Never use sleep in the main thread of a GUI

You should never use sleep because it does exactly that: it sleeps the entire application. That includes things like screen updates and the ability to respond to events.

Instead, move the code that you want to run after the sleep into a function, and call that function with after.

For example, instead of something like this:

 time.sleep(seconds_to_wait) # Makes the program wait for however many seconds depending on difficulty
 controller.show_frame("EnterCharacterScreen") # Displays the "EnterCharacterScreen"
 entry_characters.pack(fill=tk.X, padx=10, pady=10) # How many pixels to pad widget, vertically/horizontally
 button_submit.pack(fill=tk.X, padx=80, pady=80, side=tk.BOTTOM)
 # How many pixels to pad widget, vertically/horizontally
 entry_characters.focus_set() # Automatically clicks the entry box

... do something similar to this:

def callback():
 controller.show_frame("EnterCharacterScreen")
 entry_characters.pack(fill=tk.X, padx=10, pady=10)
 button_submit.pack(fill=tk.X, padx=80, pady=80, side=tk.BOTTOM)
 entry_characters.focus_set() # Automatically clicks the entry box
self.after(seconds_to_wait*1000, callback)

Don't repeat code

Consider this block of code:

def play_music3(): # Defines play_music3
 pygame.mixer.music.load('Off Limits.wav') # Loads 'Off Limits.wav') file
 pygame.mixer.music.play(-1) # Makes the song play infinitely
 pygame.mixer.music.set_volume(0.8) # Sets the volume (volume can be adjusted from 0-1)
def play_music4(): # Defines play_music4
 pygame.mixer.music.load('Pim Poy.wav') # Loads 'Pim Poy.wav') file
 pygame.mixer.music.play(-1) # Makes the song play infinitely
 pygame.mixer.music.set_volume(0.8) # Sets the volume (volume can be adjusted from 0-1)

Those two blocks of code (and the others that follow) are virtually identical except for the .wav file to play and the number added to the function name. Sequential numbers on functions are a huge red flag. You should make this function generic, and have it accept a parameter to tell it which sound to play. The parameter can be an integer, but even better would be a string that represents the logical name of the sound (eg: "soundtrack 1", etc).

For example:

soundtracks = {
 1: 'Pim Poy.wav',
 2: 'Off Limits.wav',
}
def play_soundtrack(music_id):
 pygame.mixer.music.load(soundtracks[music_id]) 
 pygame.mixer.music.play(-1) 
 pygame.mixer.music.set_volume(0.8) 

With that, when you need to play a sound it would look like this, which I think is much easier to understand:

play_soundtrack(1)

If the sounds have different settings, you can incorporate all of that into your data structure. For example:

soundtracks = {
 1: {"file": "Pim Poy.wav", "volume": 0.8}
 ...
}
answered Aug 9, 2018 at 13:40
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.