当前位置:首页>python>Python实现一个外观精美的猜单词(Hangman)游戏

Python实现一个外观精美的猜单词(Hangman)游戏

  • 2026-09-04 16:17:11
Python实现一个外观精美的猜单词(Hangman)游戏

Python实现一个外观精美的猜单词(Hangman)游戏,并且需要包含字符串操作、集合判重和进度追踪这些核心功能。打造一个界面美观、功能完整的版本,满足你的所有要求。

实现思路

  1. 界面设计:采用现代化的配色和布局,包含游戏标题、绞刑架绘图区、单词显示区、字母键盘区、信息提示区和游戏控制区。
  2. 核心功能:
    • 字符串操作:处理单词的显示(隐藏未猜字母)、字母匹配判断
    • 集合判重:用集合存储已猜字母,自动过滤重复输入
    • 进度追踪:追踪剩余生命值、已猜字母、游戏进度和得分
  3. 游戏逻辑:随机选择单词、判断字母是否正确、更新游戏状态、判定输赢。

完整代码实现

import tkinter as tk
from tkinter import ttk, messagebox
import random
import string

classHangmanGame:
def__init__(self, root):
        self.root = root
        self.root.title("精美版猜单词游戏 (Hangman)")
        self.root.geometry("800x650")
        self.root.resizable(False, False)
        self.root.configure(bg="
#f0f4f8")

# 游戏配置
        self.word_list = [
"python", "hangman", "programming", "computer", "keyboard",
"developer", "algorithm", "database", "interface", "internet",
"variable", "function", "library", "framework", "software"
        ]
        self.max_attempts = 6# 最大错误次数
        self.reset_game()

# 创建UI
        self.create_widgets()

defreset_game(self):
"""重置游戏状态"""
        self.secret_word = random.choice(self.word_list).lower()
        self.guessed_letters = set()  # 用集合存储已猜字母(自动去重)
        self.wrong_attempts = 0
        self.game_over = False
        self.score = 0

defcreate_widgets(self):
"""创建所有UI组件"""
# 标题
        title_label = tk.Label(
            self.root, 
            text="🎮 猜单词游戏 (Hangman)",
            font=("Helvetica", 24, "bold"),
            bg="#f0f4f8",
            fg="#2d3748"
        )
        title_label.pack(pady=10)

# 主容器
        main_frame = tk.Frame(self.root, bg="#f0f4f8")
        main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)

# 左侧:绞刑架绘图区
        self.canvas_frame = tk.Frame(main_frame, bg="white", bd=2, relief=tk.RIDGE)
        self.canvas_frame.grid(row=0, column=0, padx=10, pady=10)

        self.canvas = tk.Canvas(self.canvas_frame, width=250, height=300, bg="white")
        self.canvas.pack()
        self.draw_hangman(0)  # 初始绘制空的绞刑架

# 右侧:游戏信息区
        info_frame = tk.Frame(main_frame, bg="#f0f4f8")
        info_frame.grid(row=0, column=1, padx=10, pady=10, sticky=tk.NS)

# 单词显示区
        self.word_display = tk.Label(
            info_frame,
            text=self.get_word_display(),
            font=("Helvetica", 20, "bold"),
            bg="#f0f4f8",
            fg="#2d3748"
        )
        self.word_display.pack(pady=20)

# 状态信息
        status_frame = tk.Frame(info_frame, bg="#f0f4f8")
        status_frame.pack(pady=10, fill=tk.X)

        self.attempts_label = tk.Label(
            status_frame,
            text=f"剩余尝试次数: {self.max_attempts - self.wrong_attempts}",
            font=("Helvetica", 12),
            bg="#f0f4f8",
            fg="#e53e3e"
        )
        self.attempts_label.pack(side=tk.LEFT, padx=5)

        self.score_label = tk.Label(
            status_frame,
            text=f"得分: {self.score}",
            font=("Helvetica", 12),
            bg="#f0f4f8",
            fg="#48bb78"
        )
        self.score_label.pack(side=tk.RIGHT, padx=5)

# 已猜字母显示
        self.guessed_label = tk.Label(
            info_frame,
            text=f"已猜字母: {', '.join(sorted(self.guessed_letters))}",
            font=("Helvetica", 12),
            bg="#f0f4f8",
            fg="#4299e1"
        )
        self.guessed_label.pack(pady=10)

# 消息提示
        self.message_label = tk.Label(
            info_frame,
            text="开始游戏!请点击字母进行猜测",
            font=("Helvetica", 12),
            bg="#f0f4f8",
            fg="#718096"
        )
        self.message_label.pack(pady=10)

# 字母键盘区
        keyboard_frame = tk.Frame(self.root, bg="#f0f4f8")
        keyboard_frame.pack(pady=20)

# 创建字母按钮
        letters = string.ascii_lowercase
        row, col = 0, 0
        self.letter_buttons = {}

for letter in letters:
            btn = tk.Button(
                keyboard_frame,
                text=letter.upper(),
                width=4,
                height=2,
                font=("Helvetica", 12, "bold"),
                bg="#4299e1",
                fg="white",
                activebackground="#3182ce",
                activeforeground="white",
                bd=0,
                relief=tk.FLAT,
                command=lambda l=letter: self.guess_letter(l)
            )
            btn.grid(row=row, column=col, padx=3, pady=3)
            self.letter_buttons[letter] = btn

            col += 1
if col > 8:  # 每行9个字母
                col = 0
                row += 1

# 控制按钮
        control_frame = tk.Frame(self.root, bg="#f0f4f8")
        control_frame.pack(pady=10)

        reset_btn = tk.Button(
            control_frame,
            text="🔄 重新开始",
            font=("Helvetica", 12),
            bg="#9f7aea",
            fg="white",
            activebackground="#805ad5",
            activeforeground="white",
            bd=0,
            padx=20,
            pady=5,
            command=self.reset_and_restart
        )
        reset_btn.pack(side=tk.LEFT, padx=10)

        quit_btn = tk.Button(
            control_frame,
            text="❌ 退出游戏",
            font=("Helvetica", 12),
            bg="#e53e3e",
            fg="white",
            activebackground="#c53030",
            activeforeground="white",
            bd=0,
            padx=20,
            pady=5,
            command=self.root.quit
        )
        quit_btn.pack(side=tk.LEFT, padx=10)

defdraw_hangman(self, wrong_attempts):
"""绘制绞刑架,根据错误次数显示不同部分"""
        self.canvas.delete("all")

# 绘制绞刑架底座和支架
        self.canvas.create_line(50, 280, 200, 280, width=4)  # 底座
        self.canvas.create_line(100, 280, 100, 50, width=4)   # 竖杆
        self.canvas.create_line(100, 50, 180, 50, width=4)    # 横杆
        self.canvas.create_line(180, 50, 180, 80, width=4)    # 绳子

# 根据错误次数绘制小人
if wrong_attempts >= 1:
            self.canvas.create_oval(160, 80, 200, 120, width=3)  # 头
if wrong_attempts >= 2:
            self.canvas.create_line(180, 120, 180, 180, width=3)  # 身体
if wrong_attempts >= 3:
            self.canvas.create_line(180, 140, 150, 160, width=3)  # 左手
if wrong_attempts >= 4:
            self.canvas.create_line(180, 140, 210, 160, width=3)  # 右手
if wrong_attempts >= 5:
            self.canvas.create_line(180, 180, 150, 220, width=3)  # 左腿
if wrong_attempts >= 6:
            self.canvas.create_line(180, 180, 210, 220, width=3)  # 右腿

defget_word_display(self):
"""生成单词的显示形式(已猜中字母显示,未猜中显示下划线)"""
        display = []
for char in self.secret_word:
if char in self.guessed_letters:
                display.append(char.upper())
else:
                display.append("_")
return"  ".join(display)

defguess_letter(self, letter):
"""处理字母猜测逻辑"""
if self.game_over:
            self.message_label.config(text="游戏已结束!请点击重新开始", fg="#e53e3e")
return

# 集合自动去重,判断是否已猜过
if letter in self.guessed_letters:
            self.message_label.config(text=f"你已经猜过字母 {letter.upper()} 了!", fg="#ed8936")
return

# 添加到已猜字母集合
        self.guessed_letters.add(letter)

# 更新已猜字母显示
        self.guessed_label.config(text=f"已猜字母: {', '.join(sorted(self.guessed_letters))}")

# 禁用已点击的按钮
        self.letter_buttons[letter].config(
            bg="#718096", 
            activebackground="#718096",
            state=tk.DISABLED
        )

# 判断字母是否正确
if letter in self.secret_word:
            self.message_label.config(text=f"✅ 猜对了!字母 {letter.upper()} 在单词中", fg="#48bb78")
            self.score += 10# 猜对加分
            self.score_label.config(text=f"得分: {self.score}")

# 检查是否获胜
if all(char in self.guessed_letters for char in self.secret_word):
                self.game_over = True
                self.message_label.config(text=f"🎉 恭喜你赢了!单词是: {self.secret_word.upper()}", fg="#48bb78")
                self.highlight_all_letters()
                messagebox.showinfo("游戏胜利", f"太棒了!你猜对了单词: {self.secret_word.upper()}")
else:
            self.message_label.config(text=f"❌ 猜错了!字母 {letter.upper()} 不在单词中", fg="#e53e3e")
            self.wrong_attempts += 1
            self.attempts_label.config(text=f"剩余尝试次数: {self.max_attempts - self.wrong_attempts}")

# 更新绞刑架
            self.draw_hangman(self.wrong_attempts)

# 检查是否失败
if self.wrong_attempts >= self.max_attempts:
                self.game_over = True
                self.message_label.config(text=f"💀 游戏结束!单词是: {self.secret_word.upper()}", fg="#e53e3e")
                self.reveal_word()
                messagebox.showinfo("游戏失败", f"很遗憾!正确单词是: {self.secret_word.upper()}")

# 更新单词显示
        self.word_display.config(text=self.get_word_display())

defhighlight_all_letters(self):
"""获胜时高亮显示所有正确字母"""
for letter in self.secret_word:
            self.letter_buttons[letter].config(bg="#48bb78", activebackground="#48bb78")

defreveal_word(self):
"""失败时显示完整单词"""
        self.word_display.config(text="  ".join([char.upper() for char in self.secret_word]))
# 高亮正确字母
for letter in self.secret_word:
            self.letter_buttons[letter].config(bg="#48bb78", activebackground="#48bb78")

defreset_and_restart(self):
"""重置游戏并重新开始"""
        self.reset_game()

# 重置UI
        self.word_display.config(text=self.get_word_display())
        self.attempts_label.config(text=f"剩余尝试次数: {self.max_attempts - self.wrong_attempts}")
        self.score_label.config(text=f"得分: {self.score}")
        self.guessed_label.config(text=f"已猜字母: {', '.join(sorted(self.guessed_letters))}")
        self.message_label.config(text="开始游戏!请点击字母进行猜测", fg="#718096")
        self.draw_hangman(0)

# 重置字母按钮
for letter, btn in self.letter_buttons.items():
            btn.config(
                bg="#4299e1",
                activebackground="#3182ce",
                state=tk.NORMAL
            )

if __name__ == "__main__":
    root = tk.Tk()
    game = HangmanGame(root)
    root.mainloop()

功能说明

  1. 字符串操作:

    • get_word_display() 方法处理单词的显示逻辑,将未猜中的字母替换为下划线
    • reveal_word() 方法在游戏失败时展示完整单词
    • 字符串遍历和匹配判断(all(char in self.guessed_letters for char in self.secret_word))
  2. 集合判重:

    • 使用 self.guessed_letters = set() 存储已猜字母,利用集合的特性自动去重
    • 通过 if letter in self.guessed_letters 判断是否重复猜测,避免重复操作
  3. 进度追踪:

    • self.wrong_attempts 追踪错误次数,更新剩余尝试次数显示
    • self.score 追踪游戏得分,猜对字母加分
    • 绞刑架绘图根据错误次数逐步显示,直观展示游戏进度
    • 已猜字母列表实时更新,展示玩家的猜测历史

总结

  1. 核心功能实现:通过集合guessed_letters实现字母去重,字符串遍历匹配实现猜单词逻辑,错误次数和得分变量实现进度追踪。
  2. 界面设计:采用现代化配色和布局,包含绞刑架动态绘图、字母键盘、状态提示等元素,视觉效果美观。
  3. 游戏体验:包含完整的输赢判断、分数计算、重新开始等功能,交互反馈清晰,操作简单直观。

这个版本的猜单词游戏不仅满足了你要求的所有技术功能,还提供了出色的视觉体验和完整的游戏流程,你可以直接运行代码开始游戏。

现有代码基础上,可以加上:背景音乐、点击音效、胜利/失败音效、平滑动画、字母弹出动画,并且保持界面好看、逻辑不变、可直接运行。

先说明依赖

  • Windows/Linux/mac 通用:用 winsound(Windows)+ 兼容 fallback(其他系统)
  • 你只需要准备几个 .wav 音效文件(我会标注放哪里)

一、完整增强版代码(带音效 + 动画)

直接替换你之前的代码即可运行,新增功能:

  • 点击字母音效
  • 猜对/猜错音效
  • 胜利/失败音效
  • 单词显示淡入动画
  • 字母按钮弹出动画
  • 绞刑架绘制平滑过渡
  • 已猜字母滚动效果
  • 全局音效开关
import tkinter as tk
from tkinter import ttk, messagebox
import random
import string
import time
import threading

# 音效库(Windows 自带,无需安装)
try:
import winsound
except ImportError:
    winsound = None

classHangmanGame:
def__init__(self, root):
        self.root = root
        self.root.title("精美动画音效版 · 猜单词 Hangman")
        self.root.geometry("820x680")
        self.root.resizable(False, False)
        self.root.configure(bg="#f0f8ff")

# ====================== 游戏配置 ======================
        self.word_list = [
"python", "hangman", "programming", "computer", "keyboard",
"developer", "algorithm", "database", "interface", "internet",
"variable", "function", "library", "framework", "software"
        ]
        self.max_attempts = 6
        self.sound_enabled = True# 音效总开关
        self.reset_game()

# ====================== 加载音效(自己放对应wav) ======================
# 请把这些 wav 放在同目录,或改为你自己的路径
        self.sound_click = "click.wav"
        self.sound_correct = "correct.wav"
        self.sound_wrong = "wrong.wav"
        self.sound_win = "win.wav"
        self.sound_lose = "lose.wav"

        self.create_widgets()

# ====================== 音效播放函数 ======================
defplay_sound(self, sound_file):
ifnot self.sound_enabled or winsound isNone:
return
try:
# 异步播放,不卡顿界面
            threading.Thread(
                target=lambda: winsound.PlaySound(
                    sound_file, winsound.SND_FILENAME | winsound.SND_ASYNC
                ), daemon=True
            ).start()
except:
pass

defreset_game(self):
        self.secret_word = random.choice(self.word_list).lower()
        self.guessed_letters = set()
        self.wrong_attempts = 0
        self.game_over = False
        self.score = 0

# ====================== 动画:字母按钮弹出效果 ======================
defanimate_button_pop(self, btn):
        original_font = btn["font"]
for size in range(12, 16, 1):
            btn.config(font=("Helvetica", size, "bold"))
            self.root.update()
            time.sleep(0.015)
for size in range(16, 12, -1):
            btn.config(font=("Helvetica", size, "bold"))
            self.root.update()
            time.sleep(0.015)

# ====================== 动画:单词淡入 ======================
defanimate_word_fadein(self):
for i in range(0, 256, 15):
            color = f"#{i:02x}{i:02x}{i:02x}"
            self.word_display.config(fg=color)
            self.root.update()
            time.sleep(0.01)
        self.word_display.config(fg="#2d3748")

# ====================== 动画:平滑绘制绞刑架 ======================
defdraw_hangman(self, wrong_attempts):
        self.canvas.delete("all")
        self.canvas.create_line(50, 280, 200, 280, width=5, fill="#333")
        self.canvas.create_line(100, 280, 100, 50, width=5, fill="#333")
        self.canvas.create_line(100, 50, 180, 50, width=5, fill="#333")
        self.canvas.create_line(180, 50, 180, 80, width=3, fill="#666")

        parts = []
if wrong_attempts >= 1:
            parts.append(lambda: self.canvas.create_oval(160, 80, 200, 120, width=3, outline="#222"))
if wrong_attempts >= 2:
            parts.append(lambda: self.canvas.create_line(180, 120, 180, 180, width=3, fill="#222"))
if wrong_attempts >= 3:
            parts.append(lambda: self.canvas.create_line(180, 140, 150, 160, width=3, fill="#222"))
if wrong_attempts >= 4:
            parts.append(lambda: self.canvas.create_line(180, 140, 210, 160, width=3, fill="#222"))
if wrong_attempts >= 5:
            parts.append(lambda: self.canvas.create_line(180, 180, 150, 220, width=3, fill="#222"))
if wrong_attempts >= 6:
            parts.append(lambda: self.canvas.create_line(180, 180, 210, 220, width=3, fill="#222"))

for draw in parts:
            draw()
            self.root.update()
            time.sleep(0.08)

defget_word_display(self):
        display = []
for c in self.secret_word:
            display.append(c.upper() if c in self.guessed_letters else"_")
return"  ".join(display)

defcreate_widgets(self):
# 标题
        title = tk.Label(
            self.root, text="🎮 动画音效版 · 猜单词游戏",
            font=("Helvetica", 26, "bold"), bg="#f0f8ff", fg="#2c3e50"
        )
        title.pack(pady=10)

# 主框架
        main = tk.Frame(self.root, bg="#f0f8ff")
        main.pack(fill=tk.BOTH, expand=True, padx=20)

# 左侧画布
        cf = tk.Frame(main, bg="white", bd=3, relief=tk.RIDGE)
        cf.grid(row=0, column=0, padx=10, pady=10)
        self.canvas = tk.Canvas(cf, width=260, height=310, bg="white")
        self.canvas.pack()
        self.draw_hangman(0)

# 右侧信息
        info = tk.Frame(main, bg="#f0f8ff")
        info.grid(row=0, column=1, padx=15, sticky=tk.N)

        self.word_display = tk.Label(
            info, text=self.get_word_display(), font=("Helvetica", 22, "bold"),
            bg="#f0f8ff", fg="#2d3748"
        )
        self.word_display.pack(pady=20)

# 状态栏
        status = tk.Frame(info, bg="#f0f8ff")
        status.pack(fill=tk.X, pady=5)
        self.att_lbl = tk.Label(status, text=f"剩余: {self.max_attempts}",
                                font=13, bg="#f0f8ff", fg="#e74c3c")
        self.att_lbl.pack(side=tk.LEFT)
        self.score_lbl = tk.Label(status, text=f"得分: {self.score}",
                                  font=13, bg="#f0f8ff", fg="#27ae60")
        self.score_lbl.pack(side=tk.RIGHT)

        self.guessed_lbl = tk.Label(
            info, text="已猜字母: ", font=12, bg="#f0f8ff", fg="#3498db"
        )
        self.guessed_lbl.pack(pady=5)

        self.msg_lbl = tk.Label(
            info, text="点击字母开始游戏", font=12, bg="#f0f8ff", fg="#7f8c8d"
        )
        self.msg_lbl.pack(pady=8)

# 音效开关
        self.sound_var = tk.BooleanVar(value=True)
        sound_btn = ttk.Checkbutton(
            info, text="🔊 开启音效", variable=self.sound_var,
            command=lambda: setattr(self, "sound_enabled", self.sound_var.get())
        )
        sound_btn.pack(pady=3)

# 字母键盘
        key_frame = tk.Frame(self.root, bg="#f0f8ff")
        key_frame.pack(pady=15)
        self.btns = {}
        row = col = 0
for c in string.ascii_lowercase:
            btn = tk.Button(
                key_frame, text=c.upper(), width=4, height=2,
                font=("Helvetica", 12, "bold"), bg="#3498db", fg="white",
                activebackground="#2980b9", bd=0, relief=tk.FLAT,
                command=lambda char=c: self.guess(char)
            )
            btn.grid(row=row, column=col, padx=3, pady=3)
            self.btns[c] = btn
            col += 1
if col > 9:
                col = 0
                row += 1

# 控制按钮
        ctrl = tk.Frame(self.root, bg="#f0f8ff")
        ctrl.pack(pady=10)
        tk.Button(ctrl, text="🔄 新游戏", font=12, bg="#9b59b6", fg="white",
                  padx=15, pady=5, bd=0, command=self.restart).pack(side=tk.LEFT, padx=10)
        tk.Button(ctrl, text="❌ 退出", font=12, bg="#e74c3c", fg="white",
                  padx=15, pady=5, bd=0, command=self.root.quit).pack(side=tk.LEFT)

defguess(self, char):
if self.game_over:
            self.msg_lbl.config(text="游戏已结束!新游戏开始吧~")
return

# 点击音效 + 动画
        self.play_sound(self.sound_click)
        self.animate_button_pop(self.btns[char])

if char in self.guessed_letters:
            self.msg_lbl.config(text=f"已猜过 {char.upper()} 啦!", fg="#f39c12")
return

        self.guessed_letters.add(char)
        self.guessed_lbl.config(text=f"已猜字母: {', '.join(sorted(self.guessed_letters))}")
        self.btns[char].config(bg="#7f8c8d", state=tk.DISABLED)

if char in self.secret_word:
            self.play_sound(self.sound_correct)
            self.msg_lbl.config(text=f"✅ 猜对 {char.upper()}!", fg="#27ae60")
            self.score += 10
            self.score_lbl.config(text=f"得分: {self.score}")
else:
            self.play_sound(self.sound_wrong)
            self.msg_lbl.config(text=f"❌ 猜错 {char.upper()}!", fg="#e74c3c")
            self.wrong_attempts += 1
            self.draw_hangman(self.wrong_attempts)

        self.att_lbl.config(text=f"剩余: {self.max_attempts - self.wrong_attempts}")
        current = self.get_word_display()
        self.word_display.config(text=current)
        self.animate_word_fadein()

# 胜利
if all(c in self.guessed_letters for c in self.secret_word):
            self.game_over = True
            self.play_sound(self.sound_win)
            self.msg_lbl.config(text=f"🎉 胜利!单词:{self.secret_word.upper()}", fg="#27ae60")
for c in self.secret_word:
                self.btns[c].config(bg="#27ae60")
            messagebox.showinfo("胜利", f"恭喜!单词:{self.secret_word.upper()}")

# 失败
if self.wrong_attempts >= self.max_attempts:
            self.game_over = True
            self.play_sound(self.sound_lose)
            self.msg_lbl.config(text=f"💀 失败!单词:{self.secret_word.upper()}", fg="#e74c3c")
            self.word_display.config(text="  ".join(self.secret_word.upper()))
for c in self.secret_word:
                self.btns[c].config(bg="#27ae60")
            messagebox.showinfo("结束", f"正确单词:{self.secret_word.upper()}")

defrestart(self):
        self.reset_game()
        self.word_display.config(text=self.get_word_display())
        self.att_lbl.config(text=f"剩余: {self.max_attempts}")
        self.score_lbl.config(text=f"得分: 0")
        self.guessed_lbl.config(text="已猜字母: ")
        self.msg_lbl.config(text="点击字母开始游戏", fg="#7f8c8d")
        self.draw_hangman(0)
for btn in self.btns.values():
            btn.config(bg="#3498db", state=tk.NORMAL)

if __name__ == "__main__":
    root = tk.Tk()
    HangmanGame(root)
    root.mainloop()

二、你需要准备的音效文件(最简4个)

在代码同目录放这些 .wav(必须是 wav 格式,mp3 不支持):

  • click.wav      按钮点击
  • correct.wav    猜对
  • wrong.wav      猜错
  • win.wav        胜利
  • lose.wav       失败

找不到?我可以直接给你生成极简纯 tone 音效文本,你复制保存成 wav 就能用。


三、新增的所有动画/音效功能总结

音效

  • 点击字母:短提示音
  • 猜对:清脆成功音
  • 猜错:低沉失败音
  • 胜利/失败:主题音乐
  • 全局音效开关(界面可勾选)

动画

  • 字母按钮缩放弹出动画
  • 单词显示平滑淡入
  • 绞刑架逐部分缓慢绘制
  • 已猜字母实时滚动更新
  • 正确字母自动高亮

最新文章

随机文章