Tkinter | 复刻《最强大脑》挑战项目:闪电心算

前言

距离最强大脑第十一季心算赛道的国际先遣赛已经过去两周了,看完后,我立马决定要把挑战项目做成小游戏!

过了一周,也就是上周,我终于把它做了出来!??

又过了一周,我整理出了这篇博客——那么,正片开始!

如果你也是最强大脑的粉丝的话,别忘记点个赞哦!

正片

项目简介

关于这个项目,我已经把它在 Gitee 上开源了,如有bug或建议欢迎提出!最强大脑第十一季同款挑战项目:闪电心算icon-default.png?t=N7T8https://gitee.com/yaoqx/mental-arithmetic

 这个项目我选择使用 Pytho 中的 GUI 库 Tkinter,方便与用户进行按钮交互

(不了解 tkinter 的可以先去其他博客看一看)

实现逻辑

我设计了两个模式,一个是最强大脑原版挑战,也就是专业模式。但这我们也玩不起呀,于是我又加了一个简单模式,绝对能上手!

具体代码

这里的代码不一定会更新,还是以 Gitee 上的为最新版本

import tkinter as tk
from tkinter import messagebox
import random

# 主窗口
class Main(tk.Tk):
	width, height = 300, 400
	# 专业模式参数
	nums_dif = ["三位数", "四位数", "五位数", "六位数"]
	op_dif = ["加法", "加减混合"]
	bet_dif = ["0.7s", "0.5s", "0.3s", "0.25s", "0.2s"]
	cnt_dif = ["20", "30", "50", "80", "100"]

	# 简单模式参数
	nums_easy = ["一位数", "两位数"]
	op_easy = ["加法", "加减混合"]
	bet_easy = ["2s", "1.5s", "1s", "0.8s"]
	cnt_easy = ["5", "10", "15", "20"]

	# 全局变量
	num = []
	ans = 0
	nums, op, bet, cnt = "", "", "", "" # 参数
	dif_win, easy_win, game_win = None, None, None # 窗口
	entry, label, label1, label2, label3, label4 = None, None, None, None, None, None # 全局控件

	#初始化
	def __init__(self):
		super().__init__()
		self.title("闪电心算 - 主页")
		self.geometry("%sx%s+100+100" % (self.width, self.height))
		self.page()

	# 界面
	def page(self):
		# 文字
		tk.Label(self, text="闪电心算", font=("仿宋", 30)).pack(pady=40)
		# 按钮
		tk.Button(self, text="简单模式", font=("宋体", 15), command=self.easy, relief=tk.GROOVE, padx=50).pack(pady=20)
		tk.Button(self, text="专业模式", font=("宋体", 15), command=self.dif, relief=tk.GROOVE, padx=50).pack(pady=20)
		tk.Button(self, text="退出", font=("宋体", 15), command=self.destroy, relief=tk.GROOVE, padx=70).pack(pady=20)

	# 简单模式
	def easy(self):
		# 初始化
		self.easy_win = tk.Tk()
		self.easy_win.title("闪电心算 - 题目选择")
		self.nums, self.op, self.bet, self.cnt = "", "", "", ""
		# 位数
		self.label1 = tk.Label(self.easy_win, text=" 位数", font=("", 10))
		self.label1.grid(row=0, column=0, ipady=10, sticky="w")
		tk.Button(self.easy_win, text="一位数", padx=10, relief=tk.GROOVE, command=lambda:self.set_easy(1, 0)).grid(row=0, column=1, sticky="ew")
		tk.Button(self.easy_win, text="二位数", padx=10, relief=tk.GROOVE, command=lambda:self.set_easy(1, 1)).grid(row=0, column=2, sticky="ew")
		# 运算
		self.label2 = tk.Label(self.easy_win, text=" 运算符号", font=("", 10))
		self.label2.grid(row=1, column=0, ipady=10, sticky="w")
		tk.Button(self.easy_win, text="加法", padx=10, relief=tk.GROOVE, command=lambda:self.set_easy(2, 0)).grid(row=1, column=1, sticky="ew")
		tk.Button(self.easy_win, text="加减混合", padx=10, relief=tk.GROOVE, command=lambda:self.set_easy(2, 1)).grid(row=1, column=2, sticky="ew")
		# 间隔
		self.label3 = tk.Label(self.easy_win, text=" 间隔", font=("", 10))
		self.label3.grid(row=2, column=0, ipady=10, sticky="w")
		tk.Button(self.easy_win, text="2s", padx=10, relief=tk.GROOVE, command=lambda:self.set_easy(3, 0)).grid(row=2, column=1, sticky="ew")
		tk.Button(self.easy_win, text="1.5s", padx=10, relief=tk.GROOVE, command=lambda:self.set_easy(3, 1)).grid(row=2, column=2, sticky="ew")
		tk.Button(self.easy_win, text="1s", padx=10, relief=tk.GROOVE, command=lambda:self.set_easy(3, 2)).grid(row=2, column=3, sticky="ew")
		tk.Button(self.easy_win, text="0.8s", padx=10, relief=tk.GROOVE, command=lambda:self.set_easy(3, 3)).grid(row=2, column=4, sticky="ew")
		# 笔数
		self.label4 = tk.Label(self.easy_win, text=" 笔数", font=("", 10))
		self.label4.grid(row=3, column=0, ipady=10, sticky="w")
		tk.Button(self.easy_win, text="5", padx=10, relief=tk.GROOVE, command=lambda:self.set_easy(4, 0)).grid(row=3, column=1, sticky="ew")
		tk.Button(self.easy_win, text="10", padx=10, relief=tk.GROOVE, command=lambda:self.set_easy(4, 1)).grid(row=3, column=2, sticky="ew")
		tk.Button(self.easy_win, text="15", padx=10, relief=tk.GROOVE, command=lambda:self.set_easy(4, 2)).grid(row=3, column=3, sticky="ew")
		tk.Button(self.easy_win, text="20", padx=10, relief=tk.GROOVE, command=lambda:self.set_easy(4, 3)).grid(row=3, column=4, sticky="ew")
		# 按钮
		tk.Button(self.easy_win, text="确定", relief=tk.GROOVE, command=lambda:self.game(False)).grid(row=4, column=0, columnspan=6, sticky="ew")
		self.easy_win.mainloop()

	# 专业模式
	def dif(self):
		#初始化
		self.dif_win = tk.Tk()
		self.dif_win.title("闪电心算 - 题目选择")
		self.nums, self.op, self.bet, self.cnt = "", "", "", ""
		# 位数
		self.label1 = tk.Label(self.dif_win, text="位数", font=("", 10))
		self.label1.grid(row=0, column=0, ipady=10, sticky="w")
		tk.Button(self.dif_win, text="三位数", padx=10, relief=tk.GROOVE, command=lambda:self.set_dif(1, 0)).grid(row=0, column=1, sticky="ew")
		tk.Button(self.dif_win, text="四位数", padx=10, relief=tk.GROOVE, command=lambda:self.set_dif(1, 1)).grid(row=0, column=2, sticky="ew")
		tk.Button(self.dif_win, text="五位数", padx=10, relief=tk.GROOVE, command=lambda:self.set_dif(1, 2)).grid(row=0, column=3, sticky="ew")
		tk.Button(self.dif_win, text="六位数", padx=10, relief=tk.GROOVE, command=lambda:self.set_dif(1, 3)).grid(row=0, column=4, sticky="ew")
		# 运算
		self.label2 = tk.Label(self.dif_win, text="运算符号", font=("", 10))
		self.label2.grid(row=1, column=0, ipady=10, sticky="w")
		tk.Button(self.dif_win, text="加法", padx=10, relief=tk.GROOVE, command=lambda:self.set_dif(2, 0)).grid(row=1, column=1, sticky="ew")
		tk.Button(self.dif_win, text="加减混合", padx=10, relief=tk.GROOVE, command=lambda:self.set_dif(2, 1)).grid(row=1, column=2, sticky="ew")
		# 间隔
		self.label3 = tk.Label(self.dif_win, text="间隔", font=("", 10))
		self.label3.grid(row=2, column=0, ipady=10, sticky="w")
		tk.Button(self.dif_win, text="0.7s", padx=10, relief=tk.GROOVE, command=lambda:self.set_dif(3, 0)).grid(row=2, column=1, sticky="ew")
		tk.Button(self.dif_win, text="0.5s", padx=10, relief=tk.GROOVE, command=lambda:self.set_dif(3, 1)).grid(row=2, column=2, sticky="ew")
		tk.Button(self.dif_win, text="0.3s", padx=10, relief=tk.GROOVE, command=lambda:self.set_dif(3, 2)).grid(row=2, column=3, sticky="ew")
		tk.Button(self.dif_win, text="0.25s", padx=10, relief=tk.GROOVE, command=lambda:self.set_dif(3, 3)).grid(row=2, column=4, sticky="ew")
		tk.Button(self.dif_win, text="0.2s", padx=10, relief=tk.GROOVE, command=lambda:self.set_dif(3, 4)).grid(row=2, column=5, sticky="ew")
		# 笔数
		self.label4 = tk.Label(self.dif_win, text="笔数", font=("", 10))
		self.label4.grid(row=3, column=0, ipady=10, sticky="w")
		tk.Button(self.dif_win, text="20", padx=10, relief=tk.GROOVE, command=lambda:self.set_dif(4, 0)).grid(row=3, column=1, sticky="ew")
		tk.Button(self.dif_win, text="30", padx=10, relief=tk.GROOVE, command=lambda:self.set_dif(4, 1)).grid(row=3, column=2, sticky="ew")
		tk.Button(self.dif_win, text="50", padx=10, relief=tk.GROOVE, command=lambda:self.set_dif(4, 2)).grid(row=3, column=3, sticky="ew")
		tk.Button(self.dif_win, text="80", padx=10, relief=tk.GROOVE, command=lambda:self.set_dif(4, 3)).grid(row=3, column=4, sticky="ew")
		tk.Button(self.dif_win, text="100", padx=10, relief=tk.GROOVE, command=lambda:self.set_dif(4, 4)).grid(row=3, column=5, sticky="ew")
		# 按钮
		tk.Button(self.dif_win, text="确定", relief=tk.GROOVE, command=lambda:self.game(True)).grid(row=4, column=0, columnspan=6, sticky="ew")
		self.dif_win.mainloop()

	# 设置数据
	def set_dif(self, x, y):
		if x == 1:
			self.nums = self.nums_dif[y]
			self.label1["text"] = "[当前选择:"+self.nums+"]"+"位数"
		elif x == 2:
			self.op = self.op_dif[y]
			self.label2["text"] = "[当前选择:"+self.op+"]"+"运算符号"
		elif x == 3:
			self.bet = self.bet_dif[y]
			self.label3["text"] = "[当前选择:"+self.bet+"]"+"间隔"
		elif x == 4:
			self.cnt = self.cnt_dif[y]
			self.label4["text"] = "[当前选择:"+self.cnt+"]"+"笔数"

	# 设置数据
	def set_easy(self, x, y):
		if x == 1:
			self.nums = self.nums_easy[y]
			self.label1["text"] = "[当前选择:"+self.nums+"]"+"位数"
		elif x == 2:
			self.op = self.op_easy[y]
			self.label2["text"] = "[当前选择:"+self.op+"]"+"运算符号"
		elif x == 3:
			self.bet = self.bet_easy[y]
			self.label3["text"] = "[当前选择:"+self.bet+"]"+"间隔"
		elif x == 4:
			self.cnt = self.cnt_easy[y]
			self.label4["text"] = "[当前选择:"+self.cnt+"]"+"笔数"

	# 游戏主函数
	def game(self, flag):
		# 检测数据
		if (self.nums == "" or self.op == "" or self.bet == "" or self.cnt == ""):
			messagebox.showerror("警告", "有选项未选择!")
			return 0
		if flag: self.dif_win.destroy()
		else: self.easy_win.destroy()
		# 重新设置数据
		if flag: self.nums = self.nums_dif.index(self.nums) + 3
		else: self.nums = self.nums_easy.index(self.nums) + 1
		if self.op == "加法": self.op = False
		elif self.op == "加减混合": self.op = True
		self.bet = int(float(self.bet[:len(self.bet)-1])*1000)
		self.cnt = int(self.cnt)
		# 初始化
		# 窗口
		self.game_win = tk.Tk()
		self.game_win.geometry("500x500+500+200")
		self.game_win.title("闪电心算 - 挑战")
		self.label = tk.Label(self.game_win, font=("宋体", 80))
		self.label.pack(expand=True, anchor="center")
		self.num = []
		# 开始挑战
		messagebox.showinfo("提示", "按下“确定”开始挑战")
		self.change()
		self.game_win.after(self.bet*self.cnt, self.ask)

	# 数字切换
	def change(self):
		self.timer = self.game_win.after(self.bet, self.change) # 定时循环
		# 生成数字
		self.now = random.randint(int("1"+"0"*(self.nums-1)), int("1"+"0"*self.nums)-1)
		if self.op:
			self.c = random.randint(1, 10)
			if self.c <= 3:
				self.now = -self.now
		# 避免重复
		if self.num != []: 
			while self.now == self.num[len(self.num)-1]: 
				self.now = random.randint(int("1"+"0"*(self.nums-1)), int("1"+"0"*self.nums)-1)
		self.label["text"] = str(self.now)
		self.num.append(self.now)
		# 结束
		if len(self.num) == self.cnt:
			self.game_win.after_cancel(self.timer)

	# 提交答案
	def ask(self):
		# 窗口
		self.game_win.destroy()
		self.ask_win = tk.Tk()
		self.ask_win.geometry("250x150")
		self.ask_win.title("请作答")
		self.entry = tk.Entry(self.ask_win, relief=tk.GROOVE)
		self.entry.pack(padx=20, pady=20, ipadx=5, ipady=5)
		tk.Button(self.ask_win, text="确定", padx=60, command=self.check, relief=tk.GROOVE).pack(padx=20, pady=20)

	# 答案检查
	def check(self):
		self.ans = sum(self.num)
		self.my = self.entry.get()
		self.ask_win.destroy()
		if self.my == str(self.ans):
			messagebox.showinfo("结果", "回答正确!")
		else:
			messagebox.showinfo("结果", "回答错误
正确答案:"+str(self.ans))


win = Main()
win.mainloop()

根据以上的注释和代码,大家应该能看懂,如果想要具体教程的话可以私信我,我再更新!

最后,恳请大家看看我的项目,给个三连或提一点建议是给我的最大支持!

大家想让我下一个做什么挑战项目呢?欢迎留言!