你已经要求使用 `tkinter` 创建菜单界面,下面我将为你详细展示如何构建一个**基于 Tkinter 的菜单系统**,并结合你的“猜数字游戏”功能需求,实现一个完整的图形化界面版本。
---
## ✅ 使用 Tkinter 实现菜单系统的完整示例
我们将创建一个主窗口,包含以下菜单项:
- **文件**
- 开始新游戏
- 设置范围
- 退出
- **查看**
- 排行榜
- 历史记录
每个菜单项点击后会触发相应的功能操作(弹出对话框、显示排行榜等)。
---
## 🧾 完整代码如下:
```python
import tkinter as tk
from tkinter import messagebox, simpledialog, Menu
import random
import json
DATA_FILE = 'users.json'
# 加载用户数据
def load_data():
try:
with open(DATA_FILE, 'r') as f:
return json.load(f)
except FileNotFoundError:
return {}
# 保存用户数据
def save_data(data):
with open(DATA_FILE, 'w') as f:
json.dump(data, f, indent=4)
# 游戏逻辑
def play_game(mode, low, high, player1, player2=None):
data = load_data()
target = random.randint(low, high)
attempts = 0
while True:
guess_str = simpledialog.askstring("输入", f"{player1} 请输入你的猜测:")
if not guess_str or not guess_str.isdigit():
messagebox.showwarning("无效输入", "请输入有效数字!")
continue
guess = int(guess_str)
attempts += 1
if guess == target:
messagebox.showinfo("恭喜!", f"{player1} 猜对了!总共用了 {attempts} 次。")
break
elif guess < target:
messagebox.showinfo("提示", "太小了!")
else:
messagebox.showinfo("提示", "太大了!")
# 更新用户数据
if player1 not in data:
data[player1] = {"best_attempts": attempts, "history": []}
else:
if attempts < data[player1]["best_attempts"]:
data[player1]["best_attempts"] = attempts
data[player1]["history"].append({
"mode": "AI",
"target": target,
"attempts": attempts,
"result": "win"
})
save_data(data)
# 显示排行榜
def show_ranking():
data = load_data()
sorted_users = sorted(
[(user, info["best_attempts"]) for user, info in data.items()],
key=lambda x: x[1]
)
ranking_text = "\n".join([f"{idx}. {user}: {score} 次" for idx, (user, score) in enumerate(sorted_users, start=1)])
messagebox.showinfo("排行榜", ranking_text)
# 查看历史记录
def view_history():
name = simpledialog.askstring("输入用户名", "请输入用户名查看历史记录:")
data = load_data()
if name in data:
history = "\n\n".join([str(entry) for entry in data[name]["history"]])
messagebox.showinfo(f"{name} 的历史记录", history)
else:
messagebox.showerror("错误", "没有找到该用户的历史记录。")
# 设置范围
def set_range():
global low_val, high_val
low = simpledialog.askinteger("设置范围", "请输入下限:")
high = simpledialog.askinteger("设置范围", "请输入上限:")
if low is not None and high is not None:
if low >= high:
messagebox.showerror("错误", "下限必须小于上限!")
else:
low_val.set(low)
high_val.set(high)
messagebox.showinfo("成功", f"当前范围已设置为:{low} - {high}")
# 开始游戏
def start_game():
low = low_val.get()
high = high_val.get()
if low >= high:
messagebox.showerror("错误", "请先正确设置范围!")
return
mode = messagebox.askquestion("选择模式", "选择模式:\n点击 Yes 进入 AI 模式\nNo 进入 双人模式")
if mode == 'yes':
player = simpledialog.askstring("输入名字", "请输入你的名字:")
if player:
play_game('AI', low, high, player)
else:
p1 = simpledialog.askstring("玩家1", "请输入玩家1的名字:")
p2 = simpledialog.askstring("玩家2", "请输入玩家2的名字:")
if p1 and p2:
messagebox.showinfo("暂未实现", "PVP 模式暂未实现,敬请期待!")
# 创建主窗口
root = tk.Tk()
root.title("🎮 猜数字游戏系统")
root.geometry("400x300")
# 菜单栏
menu_bar = Menu(root)
# 文件菜单
file_menu = Menu(menu_bar, tearoff=0)
file_menu.add_command(label="开始新游戏", command=start_game)
file_menu.add_command(label="设置范围", command=set_range)
file_menu.add_separator()
file_menu.add_command(label="退出", command=root.quit)
menu_bar.add_cascade(label="文件", menu=file_menu)
# 查看菜单
view_menu = Menu(menu_bar, tearoff=0)
view_menu.add_command(label="排行榜", command=show_ranking)
view_menu.add_command(label="历史记录", command=view_history)
menu_bar.add_cascade(label="查看", menu=view_menu)
# 配置菜单到窗口
root.config(menu=menu_bar)
# 初始化范围变量
low_val = tk.IntVar(value=1)
high_val = tk.IntVar(value=100)
# 添加欢迎标签
welcome_label = tk.Label(root, text="欢迎来到猜数字游戏系统", font=("Arial", 16))
welcome_label.pack(pady=50)
# 启动主循环
root.mainloop()
```
---
## 🔍 代码解释
### 1. **Tkinter 主窗口与菜单栏**
我们使用 `Menu` 构建了两个菜单:
- “文件” 包含开始游戏、设置范围和退出;
- “查看” 包含排行榜和历史记录。
```python
menu_bar = Menu(root)
file_menu = Menu(menu_bar, tearoff=0)
file_menu.add_command(label="开始新游戏", command=start_game)
...
root.config(menu=menu_bar)
```
### 2. **全局变量控制范围值**
我们使用 `tk.IntVar()` 来保存当前设置的范围值:
```python
low_val = tk.IntVar(value=1)
high_val = tk.IntVar(value=100)
```
### 3. **simpledialog 和 messagebox**
用于交互式输入和提示信息:
```python
simpledialog.askinteger(...)
messagebox.showinfo(...)
```
### 4. **功能函数对应菜单动作**
例如点击“排行榜”调用 `show_ranking()` 函数,弹出排行榜。
---
##