猜数字游戏是一款经典的小游戏,玩家需要根据提示猜出一个预设的数字。本文将使用 Python 实现一个具有现代界面的猜数字游戏,涵盖从基础逻辑到图形界面的完整开发过程。通过这个项目,你将学习 Python 编程的核心概念,包括变量、数据类型、控制结构、函数、模块以及图形界面开发。
一、游戏基本原理与流程
猜数字游戏的基本规则如下:
- 计算机随机生成一个 1 到 100 之间的整数
- 玩家输入一个猜测的数字
- 计算机根据玩家的猜测给出提示(猜大了、猜小了或猜对了)
- 玩家继续猜测,直到猜对为止
- 游戏结束后,显示玩家的猜测次数和游戏评价
下面是一个简单的命令行版本实现:
import random
def guess_number():
# 生成1到100之间的随机数
secret_number = random.randint(1, 100)
attempts = 0
print("欢迎来到猜数字游戏!我已经想好了一个1到100之间的数字,你可以开始猜了。")
while True:
try:
# 获取玩家的猜测
guess = int(input("请输入你的猜测:"))
attempts += 1
# 检查猜测结果
if guess < secret_number:
print("猜小了!再大一点。")
elif guess > secret_number:
print("猜大了!再小一点。")
else:
print(f"恭喜你,猜对了!答案就是 {secret_number}。")
print(f"你一共用了 {attempts} 次猜测。")
# 根据猜测次数给出评价
if attempts <= 5:
print("你太厉害了!简直是个天才!")
elif attempts <= 10:
print("不错!继续努力!")
else:
print("还需要加油哦!下次会更好!")
break
except ValueError:
print("请输入有效的整数!")
# 启动游戏
guess_number()
知识点解析:
- 随机数生成:使用
random.randint(1, 100)
生成 1 到 100 之间的随机整数 - 循环结构:使用
while True
创建无限循环,直到猜对为止 - 条件判断:使用
if-elif-else
判断猜测结果并给出相应提示 - 异常处理:使用
try-except
处理非整数输入的情况 - 用户交互:使用
input()
获取用户输入,print()
输出提示信息
二、游戏功能扩展
我们可以对基础版本进行扩展,增加以下功能:
- 游戏难度选择:允许玩家选择不同难度(数字范围不同)
- 游戏次数统计:记录玩家的游戏次数和最佳成绩
- 历史记录:保存每次游戏的结果
- 游戏提示:显示猜测范围的上下限
下面是扩展后的代码:
import random
class GuessNumberGame:
def __init__(self):
self.difficulty_levels = {
"easy": (1, 50),
"medium": (1, 100),
"hard": (1, 200)
}
self.current_difficulty = "medium"
self.game_history = []
self.best_score = float('inf') # 初始化为无穷大
def set_difficulty(self):
"""设置游戏难度"""
print("\n选择游戏难度:")
print("1. 简单 (1-50)")
print("2. 中等 (1-100)")
print("3. 困难 (1-200)")
while True:
choice = input("请选择难度 (1-3): ")
if choice == '1':
self.current_difficulty = "easy"
break
elif choice == '2':
self.current_difficulty = "medium"
break
elif choice == '3':
self.current_difficulty = "hard"
break
else:
print("无效选择,请重新输入!")
def play_game(self):
"""开始一轮游戏"""
# 获取当前难度的数字范围
min_num, max_num = self.difficulty_levels[self.current_difficulty]
secret_number = random.randint(min_num, max_num)
attempts = 0
lower_bound = min_num
upper_bound = max_num
print(f"\n游戏开始!我已经想好了一个{lower_bound}到{upper_bound}之间的数字,你可以开始猜了。")
while True:
try:
guess = int(input(f"请输入你的猜测 ({lower_bound}-{upper_bound}): "))
# 检查猜测是否在有效范围内
if guess < lower_bound or guess > upper_bound:
print(f"请输入{lower_bound}到{upper_bound}之间的数字!")
continue
attempts += 1
if guess < secret_number:
print("猜小了!再大一点。")
lower_bound = max(lower_bound, guess + 1) # 更新下限
elif guess > secret_number:
print("猜大了!再小一点。")
upper_bound = min(upper_bound, guess - 1) # 更新上限
else:
print(f"恭喜你,猜对了!答案就是 {secret_number}。")
print(f"你一共用了 {attempts} 次猜测。")
# 记录游戏结果
result = {
"difficulty": self.current_difficulty,
"attempts": attempts,
"date": f"{time.strftime('%Y-%m-%d %H:%M:%S')}"
}
self.game_history.append(result)
# 更新最佳成绩
if attempts < self.best_score:
self.best_score = attempts
print("恭喜!你创造了新的最佳成绩!")
# 根据猜测次数给出评价
if attempts <= 5:
print("你太厉害了!简直是个天才!")
elif attempts <= 10:
print("不错!继续努力!")
else:
print("还需要加油哦!下次会更好!")
break
except ValueError:
print("请输入有效的整数!")
def show_history(self):
"""显示游戏历史记录"""
if not self.game_history:
print("\n暂无游戏记录。")
return
print("\n=== 游戏历史记录 ===")
for i, game in enumerate(self.game_history, 1):
print(f"{i}. {game['date']} - {game['difficulty'].capitalize()}难度 - {game['attempts']}次猜测")
if self.best_score != float('inf'):
print(f"\n你的最佳成绩: {self.best_score}次猜测")
def run(self):
"""运行游戏主循环"""
print("欢迎来到猜数字游戏!")
while True:
print("\n=== 主菜单 ===")
print("1. 开始新游戏")
print("2. 设置难度")
print("3. 查看历史记录")
print("4. 退出游戏")
choice = input("请选择操作 (1-4): ")
if choice == '1':
self.play_game()
elif choice == '2':
self.set_difficulty()
elif choice == '3':
self.show_history()
elif choice == '4':
print("感谢游玩!再见!")
break
else:
print("无效选择,请重新输入!")
# 启动游戏
if __name__ == "__main__":
import time # 仅在主程序中导入time模块
game = GuessNumberGame()
game.run()
知识点解析:
- 类的设计:使用
GuessNumberGame
类封装游戏的所有功能 - 属性与方法:类包含难度设置、游戏历史、最佳成绩等属性,以及游戏逻辑的各种方法
- 数据结构:使用字典存储难度级别,列表存储游戏历史
- 模块化设计:将不同功能封装为独立的方法,提高代码的可维护性
- 菜单驱动程序:使用循环和条件语句实现游戏主菜单
三、图形界面实现
使用 Tkinter 库创建一个图形界面版本的猜数字游戏:
import tkinter as tk
from tkinter import messagebox, ttk
import random
import time
class GuessNumberGUI:
def __init__(self, root):
self.root = root
self.root.title("猜数字游戏")
self.root.geometry("600x500")
self.root.resizable(False, False)
self.root.configure(bg="#f0f0f0")
# 设置中文字体
self.font = ("SimHei", 12)
# 游戏变量
self.difficulty_levels = {
"简单": (1, 50),
"中等": (1, 100),
"困难": (1, 200)
}
self.current_difficulty = "中等"
self.secret_number = None
self.attempts = 0
self.lower_bound = 1
self.upper_bound = 100
self.game_history = []
self.best_score = float('inf')
# 创建界面
self.create_widgets()
# 开始新游戏
self.start_new_game()
def create_widgets(self):
"""创建游戏界面组件"""
# 标题
title_frame = tk.Frame(self.root, bg="#f0f0f0")
title_frame.pack(pady=20)
title_label = tk.Label(title_frame, text="猜数字游戏", font=("SimHei", 24, "bold"), bg="#f0f0f0", fg="#333")
title_label.pack()
# 游戏信息框架
info_frame = tk.Frame(self.root, bg="#f0f0f0")
info_frame.pack(pady=10)
self.difficulty_label = tk.Label(info_frame, text=f"难度: {self.current_difficulty}", font=self.font, bg="#f0f0f0")
self.difficulty_label.pack(side=tk.LEFT, padx=20)
self.attempts_label = tk.Label(info_frame, text=f"尝试次数: {self.attempts}", font=self.font, bg="#f0f0f0")
self.attempts_label.pack(side=tk.LEFT, padx=20)
self.range_label = tk.Label(info_frame, text=f"范围: {self.lower_bound} - {self.upper_bound}", font=self.font, bg="#f0f0f0")
self.range_label.pack(side=tk.LEFT, padx=20)
# 输入框架
input_frame = tk.Frame(self.root, bg="#f0f0f0")
input_frame.pack(pady=20)
self.guess_label = tk.Label(input_frame, text="请输入你的猜测:", font=self.font, bg="#f0f0f0")
self.guess_label.pack(side=tk.LEFT, padx=10)
self.guess_entry = tk.Entry(input_frame, font=self.font, width=10)
self.guess_entry.pack(side=tk.LEFT, padx=10)
self.guess_entry.bind("<Return>", self.check_guess)
self.guess_button = tk.Button(input_frame, text="猜测", font=self.font, command=self.check_guess, bg="#4CAF50", fg="white", padx=10, pady=5)
self.guess_button.pack(side=tk.LEFT, padx=10)
# 提示框架
self.hint_frame = tk.Frame(self.root, bg="#f0f0f0")
self.hint_frame.pack(pady=20)
self.hint_label = tk.Label(self.hint_frame, text="开始猜测吧!", font=("SimHei", 14, "bold"), bg="#f0f0f0", fg="#333")
self.hint_label.pack()
# 历史记录框架
history_frame = tk.Frame(self.root, bg="#f0f0f0")
history_frame.pack(pady=10, fill=tk.BOTH, expand=True)
history_label = tk.Label(history_frame, text="猜测历史:", font=self.font, bg="#f0f0f0")
history_label.pack(anchor=tk.W)
self.history_text = tk.Text(history_frame, font=self.font, width=60, height=8, bg="white", wrap=tk.WORD)
self.history_text.pack(fill=tk.BOTH, expand=True, padx=10)
self.history_text.config(state=tk.DISABLED)
# 按钮框架
button_frame = tk.Frame(self.root, bg="#f0f0f0")
button_frame.pack(pady=20)
self.new_game_button = tk.Button(button_frame, text="新游戏", font=self.font, command=self.start_new_game, bg="#2196F3", fg="white", padx=10, pady=5)
self.new_game_button.pack(side=tk.LEFT, padx=10)
self.difficulty_button = tk.Button(button_frame, text="设置难度", font=self.font, command=self.set_difficulty, bg="#FF9800", fg="white", padx=10, pady=5)
self.difficulty_button.pack(side=tk.LEFT, padx=10)
self.history_button = tk.Button(button_frame, text="游戏历史", font=self.font, command=self.show_game_history, bg="#9C27B0", fg="white", padx=10, pady=5)
self.history_button.pack(side=tk.LEFT, padx=10)
def start_new_game(self):
"""开始新游戏"""
# 重置游戏状态
self.min_num, self.max_num = self.difficulty_levels[self.current_difficulty]
self.secret_number = random.randint(self.min_num, self.max_num)
self.attempts = 0
self.lower_bound = self.min_num
self.upper_bound = self.max_num
# 更新界面
self.difficulty_label.config(text=f"难度: {self.current_difficulty}")
self.attempts_label.config(text=f"尝试次数: {self.attempts}")
self.range_label.config(text=f"范围: {self.lower_bound} - {self.upper_bound}")
self.hint_label.config(text="开始猜测吧!", fg="#333")
# 清空历史记录
self.history_text.config(state=tk.NORMAL)
self.history_text.delete(1.0, tk.END)
self.history_text.config(state=tk.DISABLED)
# 聚焦到输入框
self.guess_entry.delete(0, tk.END)
self.guess_entry.focus()
def check_guess(self, event=None):
"""检查用户猜测"""
try:
guess = int(self.guess_entry.get())
# 检查猜测是否在有效范围内
if guess < self.lower_bound or guess > self.upper_bound:
self.hint_label.config(text=f"请输入{self.lower_bound}到{self.upper_bound}之间的数字!", fg="red")
return
self.attempts += 1
# 更新历史记录
self.history_text.config(state=tk.NORMAL)
self.history_text.insert(tk.END, f"尝试 {self.attempts}: {guess}\n")
self.history_text.config(state=tk.DISABLED)
self.history_text.see(tk.END) # 滚动到底部
# 检查猜测结果
if guess < self.secret_number:
self.hint_label.config(text="猜小了!再大一点。", fg="blue")
self.lower_bound = max(self.lower_bound, guess + 1) # 更新下限
elif guess > self.secret_number:
self.hint_label.config(text="猜大了!再小一点。", fg="orange")
self.upper_bound = min(self.upper_bound, guess - 1) # 更新上限
else:
self.hint_label.config(text=f"恭喜你,猜对了!答案就是 {self.secret_number}。", fg="green")
# 记录游戏结果
result = {
"difficulty": self.current_difficulty,
"attempts": self.attempts,
"date": time.strftime('%Y-%m-%d %H:%M:%S')
}
self.game_history.append(result)
# 更新最佳成绩
if self.attempts < self.best_score:
self.best_score = self.attempts
messagebox.showinfo("恭喜", f"你创造了新的最佳成绩:{self.attempts}次猜测!")
# 禁用猜测按钮
self.guess_button.config(state=tk.DISABLED)
self.guess_entry.config(state=tk.DISABLED)
# 根据猜测次数给出评价
if self.attempts <= 5:
evaluation = "你太厉害了!简直是个天才!"
elif self.attempts <= 10:
evaluation = "不错!继续努力!"
else:
evaluation = "还需要加油哦!下次会更好!"
# 显示评价
self.history_text.config(state=tk.NORMAL)
self.history_text.insert(tk.END, f"\n游戏结束!你用了 {self.attempts} 次猜测。\n{evaluation}")
self.history_text.config(state=tk.DISABLED)
# 更新界面
self.attempts_label.config(text=f"尝试次数: {self.attempts}")
self.range_label.config(text=f"范围: {self.lower_bound} - {self.upper_bound}")
self.guess_entry.delete(0, tk.END)
self.guess_entry.focus()
except ValueError:
self.hint_label.config(text="请输入有效的整数!", fg="red")
def set_difficulty(self):
"""设置游戏难度"""
# 创建难度选择对话框
difficulty_window = tk.Toplevel(self.root)
difficulty_window.title("设置难度")
difficulty_window.geometry("300x200")
difficulty_window.resizable(False, False)
difficulty_window.configure(bg="#f0f0f0")
difficulty_window.transient(self.root) # 使对话框成为主窗口的子窗口
difficulty_window.grab_set() # 模态对话框
# 设置中文字体
font = ("SimHei", 12)
# 标题
title_label = tk.Label(difficulty_window, text="选择游戏难度", font=("SimHei", 16, "bold"), bg="#f0f0f0", fg="#333")
title_label.pack(pady=15)
# 难度选项
difficulty_var = tk.StringVar(value=self.current_difficulty)
easy_radio = tk.Radiobutton(difficulty_window, text="简单 (1-50)", variable=difficulty_var, value="简单", font=font, bg="#f0f0f0")
easy_radio.pack(anchor=tk.W, padx=40, pady=5)
medium_radio = tk.Radiobutton(difficulty_window, text="中等 (1-100)", variable=difficulty_var, value="中等", font=font, bg="#f0f0f0")
medium_radio.pack(anchor=tk.W, padx=40, pady=5)
hard_radio = tk.Radiobutton(difficulty_window, text="困难 (1-200)", variable=difficulty_var, value="困难", font=font, bg="#f0f0f0")
hard_radio.pack(anchor=tk.W, padx=40, pady=5)
# 确认按钮
def confirm_difficulty():
self.current_difficulty = difficulty_var.get()
difficulty_window.destroy()
self.start_new_game()
confirm_button = tk.Button(difficulty_window, text="确定", font=font, command=confirm_difficulty, bg="#4CAF50", fg="white", padx=10, pady=5)
confirm_button.pack(pady=15)
def show_game_history(self):
"""显示游戏历史记录"""
if not self.game_history:
messagebox.showinfo("游戏历史", "暂无游戏记录。")
return
# 创建历史记录对话框
history_window = tk.Toplevel(self.root)
history_window.title("游戏历史记录")
history_window.geometry("500x400")
history_window.resizable(False, False)
history_window.configure(bg="#f0f0f0")
history_window.transient(self.root) # 使对话框成为主窗口的子窗口
# 设置中文字体
font = ("SimHei", 12)
# 标题
title_label = tk.Label(history_window, text="游戏历史记录", font=("SimHei", 16, "bold"), bg="#f0f0f0", fg="#333")
title_label.pack(pady=15)
# 创建表格
columns = ("序号", "日期", "难度", "尝试次数")
tree = ttk.Treeview(history_window, columns=columns, show="headings", height=10)
# 设置列标题
for col in columns:
tree.heading(col, text=col)
tree.column(col, width=100, anchor=tk.CENTER)
# 添加数据
for i, game in enumerate(self.game_history, 1):
tree.insert("", tk.END, values=(i, game["date"], game["difficulty"], game["attempts"]))
tree.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)
# 最佳成绩
if self.best_score != float('inf'):
best_label = tk.Label(history_window, text=f"你的最佳成绩: {self.best_score}次猜测", font=font, bg="#f0f0f0", fg="#333")
best_label.pack(pady=10)
# 关闭按钮
close_button = tk.Button(history_window, text="关闭", font=font, command=history_window.destroy, bg="#f44336", fg="white", padx=10, pady=5)
close_button.pack(pady=15)
# 启动游戏
if __name__ == "__main__":
root = tk.Tk()
app = GuessNumberGUI(root)
root.mainloop()
知识点解析:
- Tkinter 基础:使用 Tkinter 创建窗口、标签、按钮等界面元素
- 事件处理:通过绑定事件(如按钮点击、回车键)触发相应的函数
- 界面布局:使用
pack()
方法进行界面布局管理 - 对话框:创建模态对话框用于设置难度和显示历史记录
- 数据可视化:使用
Treeview
组件展示游戏历史记录 - 状态管理:在界面上实时更新游戏状态(如尝试次数、猜测范围)
四、游戏优化与扩展
我们可以进一步优化和扩展游戏,例如:
- 添加音效和动画:在猜对或猜错时播放不同的音效,添加动画效果增强用户体验
- 保存游戏数据:使用文件或数据库保存游戏历史记录,实现跨会话的持久化存储
- 网络功能:添加多人对战或联机游戏功能
- 游戏统计:增加更详细的统计数据,如不同难度的胜率、平均猜测次数等
下面是一个添加音效功能的示例:
# 在GuessNumberGUI类中添加以下代码
def __init__(self, root):
# ... 原有代码 ...
self.sound_enabled = True
# 添加音效按钮
self.sound_button = tk.Button(button_frame, text="音效: 开", font=self.font, command=self.toggle_sound, bg="#607D8B", fg="white", padx=10, pady=5)
self.sound_button.pack(side=tk.LEFT, padx=10)
# 尝试导入playsound模块用于播放音效
try:
from playsound import playsound
self.playsound = playsound
except ImportError:
self.playsound = None
self.sound_enabled = False
self.sound_button.config(state=tk.DISABLED, text="音效: 不可用")
def toggle_sound(self):
"""切换音效开关"""
self.sound_enabled = not self.sound_enabled
self.sound_button.config(text=f"音效: {'开' if self.sound_enabled else '关'}")
def play_sound(self, sound_type):
"""播放音效"""
if not self.sound_enabled or self.playsound is None:
return
try:
if sound_type == "correct":
# 播放猜对的音效
self.playsound("correct_sound.mp3")
elif sound_type == "incorrect":
# 播放猜错的音效
self.playsound("incorrect_sound.mp3")
except Exception as e:
print(f"播放音效时出错: {e}")
self.sound_enabled = False
self.sound_button.config(state=tk.DISABLED, text="音效: 出错")
def check_guess(self, event=None):
# ... 原有代码 ...
# 检查猜测结果
if guess < self.secret_number:
self.hint_label.config(text="猜小了!再大一点。", fg="blue")
self.play_sound("incorrect") # 播放猜错音效
elif guess > self.secret_number:
self.hint_label.config(text="猜大了!再小一点。", fg="orange")
self.play_sound("incorrect") # 播放猜错音效
else:
self.hint_label.config(text=f"恭喜你,猜对了!答案就是 {self.secret_number}。", fg="green")
self.play_sound("correct") # 播放猜对音效
# ... 原有代码 ...
总结
通过这个猜数字游戏项目,我们学习了 Python 编程的多个方面:
- 基础语法:变量、数据类型、控制结构、函数等
- 面向对象编程:使用类和对象组织代码,提高代码的可维护性
- 模块化设计:将不同功能封装为独立的模块和方法
- 图形界面开发:使用 Tkinter 创建交互式应用程序
- 用户交互与体验:设计友好的界面和流畅的用户体验
这个项目不仅帮助你掌握了 Python 编程的基础知识,还为你开发更复杂的应用程序打下了坚实的基础。建议你继续扩展这个游戏,添加更多功能,进一步提升自己的编程技能!