import tkinter as tk
from tkinter import messagebox, ttk
from PIL import Image, ImageTk
import random
import os
class SplashScreen([Link]):
def __init__(self, parent, on_close):
super().__init__(parent)
[Link] = parent
self.on_close = on_close
[Link](True)
[Link]("500x200+500+300")
[Link](bg="#2c3e50")
[Link] = [Link](self, text="Welcome to Escape Python
Advanced",
font=("Helvetica", 18, "bold"), fg="white",
bg="#2c3e50")
[Link](pady=30)
[Link] = [Link](self, orient="horizontal", length=400,
mode="determinate")
[Link](pady=20)
self.progress_value = 0
[Link](100, self.update_progress)
def update_progress(self):
if self.progress_value < 100:
self.progress_value += 2
[Link]['value'] = self.progress_value
[Link](60, self.update_progress)
else:
[Link]()
self.on_close()
class InstructionScreen([Link]):
def __init__(self, parent, on_start):
super().__init__(parent)
self.on_start = on_start
[Link]("Escape Python Advanced - How to Play")
[Link]("700x700")
[Link](bg="#000000")
instruction_text = (
"Welcome to the Game - Escape Python Advanced!\n\n"
"In this game, you will go through 3 levels, each based on topics
from your Python Advanced course.\n\n"
"- Each level has 3 questions.\n"
"- Correctly answering a question gives you 2 characters of a 6-
character code.\n"
"- The questions are shuffled — use your logic to arrange the code
in the order of topics taught.\n"
"- Enter the correct code to unlock the next level.\n\n"
"Good luck!"
)
label = [Link](self, text=instruction_text, font=("Arial", 18),
justify="left", wraplength=550,
bg="#000000", fg="#ffffff")
[Link](pady=20)
[Link] = [Link](value="Medium")
diff_label = [Link](self, text="Select Difficulty:", font=("Arial", 20,
"bold"), bg="#000000", fg="white")
diff_label.pack(pady=(10, 5))
options = [("Easy (Unlimited Time)", "Easy"),
("Medium (10 minutes)", "Medium"),
("Hard (5 minutes)", "Hard"),
("Impossible (3 minutes)", "Impossible")]
for text, mode in options:
rb = [Link](self, text=text, variable=[Link],
value=mode,
font=("Arial", 16), bg="#000000", fg="white",
selectcolor="#333333",
activebackground="#222222", activeforeground="white")
[Link](anchor="w", padx=60)
start_btn = [Link](self, text="Start Game", font=("Arial", 20),
bg="#ffffff", fg="#000000",
command=self.start_game)
start_btn.pack(pady=20)
# Admin button
admin_btn = [Link](self, text="Administrator", font=("Arial", 16),
bg="#ffffff", fg="#000000",
command=self.open_admin_screen)
admin_btn.pack(pady=(0, 5))
# Exit button
quit_btn = [Link](self, text="Exit", font=("Arial", 16), bg="#ffffff",
fg="#000000",
command=self.quit_game)
quit_btn.pack(pady=(0, 10))
def open_admin_login(self):
[Link]()
AdminLoginScreen(self)
def open_admin_screen(self):
AdminAccessScreen(self)
def start_game(self):
difficulty = [Link]()
[Link]()
self.on_start(difficulty)
def quit_game(self):
[Link]()
[Link]()
class AdminAccessScreen([Link]):
def __init__(self, parent):
super().__init__(parent)
[Link]("Admin Access")
[Link]("400x300")
[Link](bg="#1a1a1a")
[Link](self, text="Admin Access", font=("Arial", 20, "bold"),
bg="#1a1a1a", fg="white").pack(pady=20)
[Link](self, text="Create Admin Account", font=("Arial", 14),
command=self.create_admin, bg="#ffffff",
fg="#000000").pack(pady=10)
[Link](self, text="Login as Admin", font=("Arial", 14),
command=self.login_admin, bg="#ffffff",
fg="#000000").pack(pady=10)
def create_admin(self):
AdminCreateScreen(self)
def login_admin(self):
AdminLoginScreen(self)
class AdminCreateScreen([Link]):
def __init__(self, parent):
super().__init__(parent)
[Link]("Create Admin Account")
[Link]("400x300")
[Link](bg="#1a1a1a")
[Link](self, text="Create Admin Account", font=("Arial", 18, "bold"),
bg="#1a1a1a", fg="white").pack(pady=20)
[Link](self, text="Username:", font=("Arial", 14), bg="#1a1a1a",
fg="white").pack()
self.username_entry = [Link](self, font=("Arial", 14))
self.username_entry.pack(pady=5)
[Link](self, text="Password:", font=("Arial", 14), bg="#1a1a1a",
fg="white").pack()
self.password_entry = [Link](self, font=("Arial", 14), show="*")
self.password_entry.pack(pady=5)
[Link](self, text="Create", font=("Arial", 14),
command=self.save_credentials, bg="#ffffff",
fg="#000000").pack(pady=15)
[Link](self, text="Back", command=self.go_back, bg="#dc3545",
fg="white").pack(pady=5)
def save_credentials(self):
username = self.username_entry.get().strip()
password = self.password_entry.get().strip()
if not username or not password:
[Link]("Input Error", "Username and password
cannot be empty.")
return
with open("admin_credentials.txt", "w") as f:
[Link](f"{username}:{password}\n")
[Link]("Success", "Admin account created
successfully.")
[Link]()
def go_back(self):
[Link]()
[Link]()
class AdminLoginScreen([Link]):
def __init__(self, parent):
super().__init__(parent)
[Link]("Admin Login")
[Link]("400x250")
[Link](bg="#1a1a1a")
[Link](self, text="Admin Login", font=("Arial", 18, "bold"),
bg="#1a1a1a", fg="white").pack(pady=20)
[Link](self, text="Username:", font=("Arial", 14), bg="#1a1a1a",
fg="white").pack()
self.username_entry = [Link](self, font=("Arial", 14))
self.username_entry.pack(pady=5)
[Link](self, text="Password:", font=("Arial", 14), bg="#1a1a1a",
fg="white").pack()
self.password_entry = [Link](self, font=("Arial", 14), show="*")
self.password_entry.pack(pady=5)
[Link](self, text="Login", font=("Arial", 14),
command=self.verify_credentials, bg="#ffffff",
fg="#000000").pack(pady=15)
[Link](self, text="Back", command=self.go_back, bg="#dc3545",
fg="white").pack(pady=10)
def verify_credentials(self):
username = self.username_entry.get().strip()
password = self.password_entry.get().strip()
try:
with open("admin_credentials.txt", "r") as f:
stored = [Link]().strip()
if stored == f"{username}:{password}":
[Link]("Login Successful", "Welcome,
Admin!")
[Link]()
AdminPanel([Link])
else:
[Link]("Login Failed", "Incorrect
credentials.")
except FileNotFoundError:
[Link]("Error", "No admin credentials found.
Please create one.")
def open_create_screen(self):
[Link]()
AdminCreateScreen(self)
def go_back(self):
[Link]()
[Link]()
class AdminPanel([Link]):
def __init__(self, parent):
super().__init__(parent)
[Link]("Admin Panel")
[Link]("500x400")
[Link](bg="#1a1a1a")
[Link](self, text="Admin Panel - Question Manager", font=("Arial",
16, "bold"),
bg="#1a1a1a", fg="white").pack(pady=20)
[Link](self, text="Add Question", font=("Arial", 14),
command=self.add_question).pack(pady=10)
[Link](self, text="Delete Question", font=("Arial", 14),
command=self.delete_question).pack(pady=10)
[Link](self, text="Modify Question", font=("Arial", 14),
command=self.modify_question).pack(pady=10)
[Link](self, text="Logout", width=20, bg="#dc3545", fg="white",
command=[Link]).pack(pady=30)
def add_question(self):
QuestionEditor(self, mode="add")
def delete_question(self):
QuestionEditor(self, mode="delete")
def modify_question(self):
selection_window = [Link](self)
selection_window.title("Select Question to Modify")
selection_window.geometry("500x400")
selection_window.configure(bg="#1a1a1a")
[Link](selection_window, text="Select a Question", font=("Arial",
16), bg="#1a1a1a", fg="white").pack(pady=10)
# Load questions from the .docx or your question source
try:
from docx import Document
doc = Document("[Link]")
questions = [[Link] for para in [Link] if
[Link]()]
except:
questions = []
listbox = [Link](selection_window, font=("Arial", 12), width=60)
for i, q in enumerate(questions):
[Link]([Link], f"{i + 1}. {q[:80]}...") # Short preview
[Link](pady=10)
def open_editor():
selected_index = [Link]()
if not selected_index:
[Link]("No Selection", "Please select a
question to modify.")
return
QuestionEditor(self, mode="modify",
question_index=selected_index[0])
selection_window.destroy()
[Link](selection_window, text="Edit Selected Question",
command=open_editor, font=("Arial", 12),
bg="#28a745", fg="white").pack(pady=10)
def logout(self):
[Link]()
self.instruction_screen.deiconify()
class QuestionEditor([Link]):
def __init__(self, parent, mode):
super().__init__(parent)
[Link](f"{[Link]()} Question")
[Link]("600x500")
[Link](bg="#1a1a1a")
[Link] = mode
self.level_var = [Link]()
[Link](self, text=f"{[Link]()} Question", font=("Arial", 16,
"bold"),
bg="#1a1a1a", fg="white").pack(pady=10)
level_frame = [Link](self, bg="#1a1a1a")
[Link](level_frame, text="Level:", font=("Arial", 14),
bg="#1a1a1a", fg="white").pack(side=[Link])
level_dropdown = [Link](level_frame,
textvariable=self.level_var, values=["1", "2", "3"], width=5)
level_dropdown.pack(side=[Link], padx=10)
level_dropdown.current(0)
level_frame.pack(pady=10)
if [Link] == "add":
self.create_add_ui()
else:
self.create_modify_delete_ui()
def create_add_ui(self):
[Link](self, text="Question:", bg="#1a1a1a", fg="white",
font=("Arial", 12)).pack()
self.question_text = [Link](self, height=4, width=60)
self.question_text.pack(pady=5)
[Link](self, text="Answer:", bg="#1a1a1a", fg="white",
font=("Arial", 12)).pack()
self.answer_entry = [Link](self, width=60)
self.answer_entry.pack(pady=5)
[Link](self, text="Add Question",
command=self.add_question).pack(pady=15)
def create_modify_delete_ui(self):
self.question_listbox = [Link](self, width=80, height=10)
self.question_listbox.pack(pady=10)
[Link](self, text="Load Questions",
command=self.load_questions).pack()
if [Link] == "delete":
[Link](self, text="Delete Selected",
command=self.delete_selected).pack(pady=10)
elif [Link] == "modify":
[Link](self, text="New Question:", bg="#1a1a1a",
fg="white").pack()
self.new_question_entry = [Link](self, height=4, width=60)
self.new_question_entry.pack()
[Link](self, text="New Answer:", bg="#1a1a1a",
fg="white").pack()
self.new_answer_entry = [Link](self, width=60)
self.new_answer_entry.pack()
[Link](self, text="Modify Selected",
command=self.modify_selected).pack(pady=10)
def load_questions(self):
self.question_listbox.delete(0, [Link])
level = self.level_var.get()
try:
with open("[Link]", "r") as file:
lines = [Link]()
for i in range(0, len(lines), 3):
if lines[i].strip() == f"Level: {level}":
question = lines[i + 1].strip().replace("Question: ", "")
answer = lines[i + 2].strip().replace("Answer: ", "")
self.question_listbox.insert([Link], f"Q: {question} | A:
{answer}")
except FileNotFoundError:
[Link]("Error", "[Link] not found.")
def add_question(self):
level = self.level_var.get()
question = self.question_text.get("1.0", [Link]).strip()
answer = self.answer_entry.get().strip()
if not question or not answer:
[Link]("Input Error", "Question and answer
cannot be empty.")
return
with open("[Link]", "a") as file:
[Link](f"Level: {level}\n")
[Link](f"Question: {question}\n")
[Link](f"Answer: {answer}\n")
[Link]("Success", "Question added successfully.")
[Link]()
def delete_selected(self):
selected = self.question_listbox.curselection()
if not selected:
[Link]("Selection Error", "No question
selected.")
return
to_delete = self.question_listbox.get(selected[0])
level = self.level_var.get()
with open("[Link]", "r") as file:
lines = [Link]()
new_lines = []
i=0
while i < len(lines):
if lines[i].strip() == f"Level: {level}":
question = lines[i + 1].strip().replace("Question: ", "")
answer = lines[i + 2].strip().replace("Answer: ", "")
full = f"Q: {question} | A: {answer}"
if full == to_delete:
i += 3
continue
new_lines.append(lines[i])
i += 1
with open("[Link]", "w") as file:
[Link](new_lines)
[Link]("Success", "Question deleted successfully.")
self.load_questions()
def modify_selected(self):
selected = self.question_listbox.curselection()
if not selected:
[Link]("Selection Error", "No question
selected.")
return
old = self.question_listbox.get(selected[0])
level = self.level_var.get()
new_q = self.new_question_entry.get("1.0", [Link]).strip()
new_a = self.new_answer_entry.get().strip()
if not new_q or not new_a:
[Link]("Input Error", "New question and
answer cannot be empty.")
return
with open("[Link]", "r") as file:
lines = [Link]()
new_lines = []
i=0
while i < len(lines):
if lines[i].strip() == f"Level: {level}":
question = lines[i + 1].strip().replace("Question: ", "")
answer = lines[i + 2].strip().replace("Answer: ", "")
full = f"Q: {question} | A: {answer}"
if full == old:
new_lines.extend([
f"Level: {level}\n",
f"Question: {new_q}\n",
f"Answer: {new_a}\n"
])
i += 3
continue
new_lines.append(lines[i])
i += 1
with open("[Link]", "w") as file:
[Link](new_lines)
[Link]("Success", "Question modified successfully.")
self.load_questions()
def load_questions_from_file(level):
filename = "[Link]"
questions = []
current_level = None
if not [Link](filename):
[Link]("Missing File", f"{filename} not found.")
return []
with open(filename, "r", encoding="utf-8") as f:
lines = [Link]()
question_data = {}
current_key = None
buffer = []
def flush_buffer():
if current_key and buffer:
question_data[current_key]="\n".join(buffer).strip()
for line in lines:
line = [Link]("\n")
if not [Link]():
flush_buffer()
if question_data and current_level == level:
[Link](question_data)
question_data = {}
current_key = None
buffer = []
continue
if [Link]("# Level"):
flush_buffer()
try:
current_level = int([Link]("Level")[1].strip())
except ValueError:
current_level = None
question_data = {}
current_key = None
buffer = []
continue
if current_level == level:
if [Link]("QUESTION:"):
flush_buffer()
current_key = "question"
buffer = [line[len("QUESTION:"):].strip()]
elif [Link]("ANSWER:"):
flush_buffer()
current_key = "answer"
buffer = [line[len("ANSWER:"):].strip()]
elif [Link]("HINT:"):
flush_buffer()
current_key = "hint"
buffer = [line[len("HINT:"):].strip()]
elif [Link]("CODE:"):
flush_buffer()
current_key = "code"
buffer = [line[len("CODE:"):].strip()]
elif [Link]("ORDER:"):
flush_buffer()
current_key = "order"
try:
question_data["order"] = int(line[len("ORDER:"):].strip())
except ValueError:
question_data["order"] = 0
current_key = None
buffer = []
else:
[Link](line)
flush_buffer()
if question_data and current_level == level:
[Link](question_data)
return questions
class Game:
def __init__(self, root, difficulty):
[Link] = root
[Link]("Escape Python Advanced")
[Link]("800x600")
[Link] = 1
[Link]("WM_DELETE_WINDOW", self.cleanup_and_exit)
[Link] = [Link]([Link])
[Link].theme_use('default')
[Link]("[Link]",
foreground="#006400", background="#006400")
if not [Link]("background_fullscreen.png"):
[Link]("Missing File", "Required background
image not found.")
[Link]()
return
self.bg_image = [Link]("background_fullscreen.png")
self.bg_photo = [Link](self.bg_image)
[Link] = [Link]([Link])
[Link](fill="both", expand=True)
[Link].create_image(0, 0, image=self.bg_photo, anchor="nw")
[Link] = None
[Link] = {
1: self.get_level1_questions,
2: self.get_level2_questions,
3: self.get_level3_questions
[Link] = difficulty
self.time_left = self.set_time_for_difficulty(difficulty)
self.timer_id = None
self.timer_label = [Link]([Link], text="", font=("Arial", 16,
"bold"),
bg="#000000", fg="#ffffff")
self.timer_label.place(x=650, y=50)
self.collected_codes = []
self.start_level()
if self.time_left is not None:
self.start_timer()
else:
self.timer_label.config(text="Unlimited Time")
def confirm_quit(self):
answer = [Link]("Quit Game", "Are you sure you
want to quit?")
if answer:
[Link]()
def add_quit_button(self):
quit_btn = [Link]([Link], text="Quit", font=("Arial", 14),
command=self.confirm_quit, bg="#ff4d4d", fg="white")
quit_btn.place(x=720, y=550) # Adjust position as needed
def set_time_for_difficulty(self, difficulty):
return {
"Easy": None,
"Medium": 10 * 60,
"Hard": 5 * 60,
"Impossible": 3 * 60
}.get(difficulty, None)
def clear_window(self):
if [Link] is not None:
[Link]()
def start_level(self):
self.clear_window()
self.collected_codes = []
[Link] = [Link][[Link]]()
self.shuffled_questions = [Link]()
[Link](self.shuffled_questions)
[Link] = self.shuffled_questions
self.current_question = 0
self.hint_count = 0
self.max_hints = 3
self.hint_window = None
self.show_question()
self.add_quit_button()
def show_question(self):
self.clear_window()
[Link] = [Link]([Link], bg="#000000", bd=0)
[Link](x=20, y=40)
self.progress_bar = [Link]([Link], orient="horizontal",
length=760,
mode="determinate",
style="[Link]")
self.progress_bar.place(x=20, y=20)
self.progress_bar["maximum"] = len([Link])
self.progress_bar["value"] = self.current_question
if self.current_question < len([Link]):
q = [Link][self.current_question]
[Link]([Link], text=f"Level {[Link]} - Question
{self.current_question + 1}",
font=("Arial", 20, "bold"), bg="#000000",
fg="#0000ff").pack(anchor="w", pady=(0, 5))
[Link]([Link], text=q['question'], wraplength=1000,
justify="left",
font=("Arial", 18), bg="#000000",
fg="#ffffff").pack(anchor="w", pady=(0, 10))
self.answer_entry = [Link]([Link], width=30, font=("Arial",
16))
self.answer_entry.pack(anchor="w", pady=(0, 10))
[Link]([Link], text="Submit", command=self.check_answer,
font=("Arial", 16)).pack(anchor="w", pady=(0, 5))
self.hint_btn = [Link]([Link], text="Hint",
command=self.show_hint,
font=("Arial", 16))
self.hint_btn.pack(anchor="w")
self.hint_counter_label = [Link]([Link],
text=f"Hints used:
{self.hint_count}/{self.max_hints}",
font=("Arial", 14), bg="#000000",
fg="#ffcc00")
self.hint_counter_label.pack(anchor="w", pady=(5, 0))
else:
self.prompt_code_entry()
def check_answer(self):
user_answer = self.answer_entry.get().strip()
correct_answer = [Link][self.current_question]["answer"]
if user_answer.lower() == correct_answer.lower():
[Link]("Correct!", f"Code segment received: "
f"{[Link][self.current_question]
['code']}")
self.collected_codes.append({
'code': [Link][self.current_question]['code'],
'order': [Link][self.current_question]['order']
})
self.current_question += 1
self.progress_bar["value"] = self.current_question
self.show_question()
else:
[Link]("Try Again", "Incorrect answer. Please
try again.")
def show_hint(self):
if self.hint_count >= self.max_hints:
[Link]("Hint Limit Reached", "You have used all
your hints for this level.")
return
if self.hint_window and self.hint_window.winfo_exists():
return
self.hint_count += 1
hint = [Link][self.current_question]["hint"]
self.hint_window = [Link]([Link])
self.hint_window.title("Hint")
self.hint_window.geometry("400x250") # Increased from 300x200
self.hint_window.configure(bg="#000000")
[Link](self.hint_window, text=f"HINT
({self.hint_count}/{self.max_hints})",
font=("Arial", 18, "bold"), bg="#000000",
fg="white").pack(pady=(20, 10))
[Link](self.hint_window, text=hint, wraplength=350,
justify="center",
font=("Arial", 16), bg="#000000", fg="white").pack(pady=(0,
20))
[Link](self.hint_window, text="Got it",
command=self.hint_window.destroy,
font=("Arial", 16), bg="white", fg="black").pack()
self.hint_counter_label.config(text=f"Hints used:
{self.hint_count}/{self.max_hints}")
def prompt_code_entry(self):
if self.timer_id:
[Link].after_cancel(self.timer_id)
self.clear_window()
[Link] = [Link]([Link], bg="#000000", bd=0)
[Link](x=20, y=40)
[Link]([Link], text=f"Level {[Link]} Complete!\n\n"
f"Enter the 6-character access code to continue:",
font=("Arial", 20), bg="#000000",
fg="#ffffff").pack(anchor="w", pady=(0, 10))
self.code_entry = [Link]([Link], width=20, font=("Arial", 18))
self.code_entry.pack(anchor="w", pady=(0, 10))
[Link]([Link], text="Enter Code", command=self.verify_code,
font=("Arial", 18)).pack(anchor="w")
self.add_quit_button()
def verify_code(self):
entered_code = self.code_entry.get().strip()
self.code_segments = [c['code'] for c in sorted(self.collected_codes,
key=lambda x: x['order'])]
correct_code = ''.join(self.code_segments)
if entered_code.lower() == correct_code.lower():
if [Link] == 3:
[Link]("🏁 Game Complete!", "You have escaped
for now!\nYour project is next...")
[Link]()
else:
[Link]("Access Granted", f"Welcome to Level
{[Link] + 1}!")
[Link] += 1
self.start_level()
else:
[Link]("Access Denied", "Incorrect code. Please
try again.")
def start_timer(self):
self.update_timer()
def update_timer(self):
if self.time_left is None:
return
mins, secs = divmod(self.time_left, 60)
self.timer_label.config(text=f"Time left: {mins:02d}:{secs:02d}")
if self.time_left <= 0:
[Link]("Time's Up", "You have run out of time!
Game over.")
[Link]()
return
self.time_left -= 1
self.timer_id = [Link](1000, self.update_timer)
def cleanup_and_exit(self):
if self.timer_id:
[Link].after_cancel(self.timer_id)
[Link]()
# Question methods unchanged...
def get_level1_questions(self):
return load_questions_from_file(1)
def get_level2_questions(self):
return load_questions_from_file(2)
def get_level3_questions(self):
return load_questions_from_file(3)
if __name__ == "__main__":
root = [Link]()
[Link]()
def start_game(difficulty):
[Link]()
Game(root, difficulty)
def show_instructions():
InstructionScreen(root, on_start=start_game)
splash = SplashScreen(root, on_close=show_instructions)
[Link]()