Skip to content

Commit cf258c2

Browse files
authored
Create Guess-the-Word.py
1 parent 51c7e14 commit cf258c2

1 file changed

Lines changed: 199 additions & 0 deletions

File tree

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
import sys
2+
import os
3+
import random
4+
import tkinter as tk
5+
from tkinter import ttk, messagebox
6+
import sv_ttk
7+
8+
# =========================
9+
# Helpers
10+
# =========================
11+
def resource_path(file_name):
12+
base_path = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))
13+
return os.path.join(base_path, file_name)
14+
15+
def set_status(msg):
16+
status_var.set(msg)
17+
root.update_idletasks()
18+
19+
# =========================
20+
# App Setup
21+
# =========================
22+
root = tk.Tk()
23+
root.title("Animated Hangman Game")
24+
root.geometry("700x850")
25+
sv_ttk.set_theme("light")
26+
27+
# =========================
28+
# Globals
29+
# =========================
30+
dark_mode_var = tk.BooleanVar(value=False)
31+
word_list = ["PYTHON", "HANGMAN", "COMPUTER", "AI", "PROGRAMMING", "DEVELOPER"]
32+
current_word = ""
33+
guessed_letters = set()
34+
wrong_guesses = 0
35+
max_wrong = 6
36+
display_word_var = tk.StringVar()
37+
status_var = tk.StringVar(value="Ready")
38+
lives_var = tk.StringVar(value=f"Lives: {max_wrong}")
39+
40+
# =========================
41+
# Theme Toggle
42+
# =========================
43+
def toggle_theme():
44+
bg = "#2E2E2E" if dark_mode_var.get() else "#FFFFFF"
45+
fg = "white" if dark_mode_var.get() else "black"
46+
root.configure(bg=bg)
47+
for w in ["TFrame", "TLabel", "TLabelframe", "TLabelframe.Label", "TCheckbutton"]:
48+
style.configure(w, background=bg, foreground=fg)
49+
guess_entry.configure(background=bg, foreground=fg)
50+
hangman_canvas.configure(bg=bg)
51+
52+
# =========================
53+
# Game Logic
54+
# =========================
55+
def start_new_game():
56+
global current_word, guessed_letters, wrong_guesses
57+
current_word = random.choice(word_list).upper()
58+
guessed_letters = set()
59+
wrong_guesses = 0
60+
update_display_word()
61+
lives_var.set(f"Lives: {max_wrong - wrong_guesses}")
62+
draw_hangman(animated=False)
63+
set_status("New game started! Guess a letter.")
64+
65+
def update_display_word():
66+
display = " ".join([c if c in guessed_letters else "_" for c in current_word])
67+
display_word_var.set(display)
68+
if "_" not in display:
69+
set_status("Congratulations! You guessed the word!")
70+
messagebox.showinfo("Winner!", f"You correctly guessed: {current_word}")
71+
72+
def guess_letter():
73+
global wrong_guesses
74+
letter = guess_var.get().strip().upper()
75+
guess_var.set("")
76+
if not letter or len(letter) != 1 or not letter.isalpha():
77+
set_status("Please enter a single letter.")
78+
return
79+
if letter in guessed_letters:
80+
set_status(f"You already guessed '{letter}'.")
81+
return
82+
guessed_letters.add(letter)
83+
if letter not in current_word:
84+
wrong_guesses += 1
85+
lives_var.set(f"Lives: {max_wrong - wrong_guesses}")
86+
set_status(f"Wrong guess! {max_wrong - wrong_guesses} tries left.")
87+
draw_hangman(animated=True)
88+
if wrong_guesses >= max_wrong:
89+
messagebox.showinfo("Game Over", f"You lost! The word was: {current_word}")
90+
start_new_game()
91+
return
92+
update_display_word()
93+
94+
# =========================
95+
# Hangman Drawing with Animation
96+
# =========================
97+
def draw_hangman(animated=True):
98+
hangman_canvas.delete("all")
99+
# Base
100+
hangman_canvas.create_line(50, 350, 250, 350, width=3)
101+
# Pole
102+
hangman_canvas.create_line(150, 350, 150, 50, width=3)
103+
hangman_canvas.create_line(150, 50, 300, 50, width=3)
104+
hangman_canvas.create_line(300, 50, 300, 100, width=3)
105+
106+
parts = []
107+
if wrong_guesses >= 1: # Head
108+
parts.append(("oval", 275, 100, 325, 150))
109+
if wrong_guesses >= 2: # Body
110+
parts.append(("line", 300, 150, 300, 250))
111+
if wrong_guesses >= 3: # Left Arm
112+
parts.append(("line", 300, 170, 250, 200))
113+
if wrong_guesses >= 4: # Right Arm
114+
parts.append(("line", 300, 170, 350, 200))
115+
if wrong_guesses >= 5: # Left Leg
116+
parts.append(("line", 300, 250, 250, 300))
117+
if wrong_guesses >= 6: # Right Leg
118+
parts.append(("line", 300, 250, 350, 300))
119+
120+
if animated:
121+
animate_parts(parts)
122+
else:
123+
for p in parts:
124+
if p[0] == "oval":
125+
hangman_canvas.create_oval(*p[1:], width=3)
126+
elif p[0] == "line":
127+
hangman_canvas.create_line(*p[1:], width=3)
128+
129+
def animate_parts(parts, idx=0):
130+
if idx >= len(parts):
131+
return
132+
p = parts[idx]
133+
if p[0] == "oval":
134+
# Animate head as growing circle
135+
x1, y1, x2, y2 = p[1:]
136+
for i in range(0, 101, 5):
137+
hangman_canvas.after(i, lambda x1=x1, y1=y1, x2=x2, y2=y2: hangman_canvas.create_oval(x1, y1, x2, y2, width=3))
138+
elif p[0] == "line":
139+
# Animate line drawing in steps
140+
x1, y1, x2, y2 = p[1:]
141+
steps = 20
142+
dx = (x2 - x1) / steps
143+
dy = (y2 - y1) / steps
144+
for i in range(1, steps + 1):
145+
hangman_canvas.after(i * 20, lambda i=i, x1=x1, y1=y1, dx=dx, dy=dy: hangman_canvas.create_line(x1, y1, x1 + dx * i, y1 + dy * i, width=3))
146+
hangman_canvas.after(400, lambda: animate_parts(parts, idx + 1))
147+
148+
# =========================
149+
# Styles
150+
# =========================
151+
style = ttk.Style()
152+
style.theme_use("clam")
153+
style.configure("Action.TButton", font=("Segoe UI", 11, "bold"), padding=8)
154+
155+
# =========================
156+
# UI Layout
157+
# =========================
158+
main = ttk.Frame(root, padding=20)
159+
main.pack(expand=True, fill="both")
160+
main.columnconfigure(0, weight=1)
161+
162+
ttk.Label(main, text="Animated Hangman Game", font=("Segoe UI", 22, "bold")).grid(row=0, column=0, sticky="ew", pady=(0,10))
163+
164+
# Hangman Canvas
165+
hangman_canvas = tk.Canvas(main, width=400, height=400, bg="white")
166+
hangman_canvas.grid(row=1, column=0, pady=10)
167+
168+
# Word display
169+
ttk.Label(main, textvariable=display_word_var, font=("Segoe UI", 28)).grid(row=2, column=0, pady=20)
170+
171+
# Lives display
172+
ttk.Label(main, textvariable=lives_var, font=("Segoe UI", 16, "bold")).grid(row=3, column=0, pady=5)
173+
174+
# Letter input
175+
input_frame = ttk.Frame(main)
176+
input_frame.grid(row=4, column=0, pady=10)
177+
guess_var = tk.StringVar()
178+
guess_entry = ttk.Entry(input_frame, textvariable=guess_var, font=("Segoe UI", 16), width=5)
179+
guess_entry.pack(side="left", padx=(0,10))
180+
ttk.Button(input_frame, text="Guess", command=guess_letter, style="Action.TButton").pack(side="left")
181+
182+
# Controls
183+
controls = ttk.Frame(main)
184+
controls.grid(row=5, column=0, pady=10, sticky="ew")
185+
ttk.Button(controls, text="New Game", command=start_new_game, style="Action.TButton").pack(side="left")
186+
187+
# Options
188+
options_frame = ttk.Frame(main)
189+
options_frame.grid(row=6, column=0, sticky="w", pady=6)
190+
ttk.Checkbutton(options_frame, text="Dark Mode", variable=dark_mode_var, command=toggle_theme).pack(side="left")
191+
192+
# Status Bar
193+
ttk.Label(root, textvariable=status_var, anchor="w").pack(side=tk.BOTTOM, fill="x")
194+
195+
# =========================
196+
# Run App
197+
# =========================
198+
start_new_game()
199+
root.mainloop()

0 commit comments

Comments
 (0)