2025-05-30 17:16:18 +08:00

153 lines
4.4 KiB
Python

import tkinter as tk
from tkinter import messagebox, simpledialog
import time
import json
import os
# 排行榜文件名
LEADERBOARD_FILE = "leaderboard.json"
# 读取排行榜数据
def load_leaderboard():
if os.path.exists(LEADERBOARD_FILE):
try:
with open(LEADERBOARD_FILE, "r", encoding="utf-8") as f:
return json.load(f)
except:
return []
return []
# 保存排行榜数据
def save_leaderboard():
with open(LEADERBOARD_FILE, "w", encoding="utf-8") as f:
json.dump(leaderboard, f, ensure_ascii=False, indent=2)
# 获取参赛者姓名
def get_player_name():
name = simpledialog.askstring("参赛者姓名", "请输入您的姓名:")
if not name:
messagebox.showwarning("警告", "姓名不能为空,请重新输入。")
return get_player_name()
return name
# 更新排行榜(同名保留最小误差)
def update_leaderboard(name, error):
found = False
for i, (n, e) in enumerate(leaderboard):
if n == name:
found = True
if abs(error) < e:
leaderboard[i] = (name, abs(error))
break
if not found:
leaderboard.append((name, abs(error)))
leaderboard.sort(key=lambda x: x[1])
save_leaderboard() # 写入文件
# 更新显示
rank_listbox.delete(0, tk.END)
for i, (n, e) in enumerate(leaderboard[:], 1):
rank_listbox.insert(tk.END, f"{i}. {n:<8} 误差: {e:.3f}s")
# 更新时间函数
def update_time():
if flag:
now = time.time()
timex = now - start_time
timex_label.config(text=f"⏱ 时间:{timex:.3f}")
root.after(10, update_time)
def show_win_animation():
anim = tk.Toplevel(root)
anim.geometry("320x200")
anim.title("🎉 胜利动画")
anim.configure(bg="#ffffff")
anim.attributes("-topmost", True) # 置顶显示
label = tk.Label(anim, text="🎉 完美掌控时间!🎉", font=("微软雅黑", 18, "bold"), bg="#ffffff")
label.pack(expand=True)
colors = ["#ff6666", "#66cc66", "#3399ff", "#ffcc00", "#cc66ff"]
sizes = [18, 22, 26, 30, 26, 22, 18]
def animate(i=0):
if i < len(sizes):
label.config(font=("微软雅黑", sizes[i], "bold"), fg=colors[i % len(colors)])
anim.after(150, animate, i + 1)
else:
anim.destroy()
animate()
# 控制开始/停止
def change():
global flag, start_time
if not flag:
flag = True
start_time = time.time()
update_time()
else:
flag = False
end_time = time.time()
timex = end_time - start_time
error = timex - 10
timex_label.config(text=f"✅ 实际时间:{timex:.3f}\n误差:{error:.3f}")
name = get_player_name()
update_leaderboard(name, error)
if abs(error) < 0.01:
show_win_animation()
else:
messagebox.showinfo("结果", "还差一点点,再接再厉吧!")
# ================================
# 主窗口
# ================================
leaderboard = load_leaderboard()
root = tk.Tk()
root.geometry("340x500")
root.title("10秒挑战")
root.configure(bg="#f0faff")
# 标题
title_label = tk.Label(root, text="🎯 10 秒挑战 🎯", font=("微软雅黑", 18, "bold"), fg="#004466", bg="#f0faff")
title_label.pack(pady=15)
# 排行榜框
rank_frame = tk.Frame(root, bg="#ffffff", bd=2, relief="groove")
rank_frame.pack(pady=10)
rank_title = tk.Label(rank_frame, text="🏆 排行榜(误差越小越靠前)", font=("微软雅黑", 10, "bold"), bg="#ffffff", fg="#333333")
rank_title.pack(pady=(5, 0))
rank_listbox = tk.Listbox(rank_frame, font=("Courier", 10), height=5, width=35, bg="#f9f9f9")
rank_listbox.pack(padx=10, pady=5)
# 初始显示排行榜
for i, (n, e) in enumerate(leaderboard[:5], 1):
rank_listbox.insert(tk.END, f"{i}. {n:<8} 误差: {e:.3f}s")
# 时间标签
timex_label = tk.Label(root, text="点击按钮开始挑战", font=("微软雅黑", 12), bg="#f0faff", fg="#333333")
timex_label.pack(pady=20)
# 按钮
start_button = tk.Button(root, text="🎮 开始 / 停止", font=("微软雅黑", 12, "bold"),
bg="#66ccff", fg="white", activebackground="#3399cc",
width=20, height=2, command=change, relief="raised", bd=3)
start_button.pack(pady=30)
# 控制变量
flag = False
start_time = 0
# 启动主循环
root.mainloop()