需求分析:作为一名小学生的家长,我希望制作一个出题软件,完成100以内的正整数的加减法题./....以减轻我的家庭负担?
这是一个程序,实现简单出题并提供答案就行⑧
(其实给小学生整个电脑软件让做题就挺离谱的,从小盯电脑眼不得看坏了?汗。。其次:现在一年级的学生都玩电脑了吗)
技术难点:
- 制作一个可以互动的GUI
- 随机生成数学题
- GUI设置后,把生成的数学题放到GUI上
- 题做完后提交,要验证答案是否正确,对了多少道题
思考:
①首先这样的一个程序是一个带GUI程序,我想过用Java或者是Python做,如果是Java的话会挺简单的吧毕竟有WindowsBuilder这个插件制作GUI会很简单,Python的话也可以,
自带的Tkinter,但是Tkinter我已经忘了怎么用了,但是我还是想挑战一下,用Tkinter做一下(后来听说有个交Pypt的东西也是Python的东西,主要用来做GUI的,但。。那个时候我已经做完了)。
②这个GUI是要直接用place全局布局做出来,还是说用代码自动生成位置
③这个程序如果出现了负数或3位数和3位数的运算是不行的,这不是小学一年级的范围,应当排除这些题
④做题完毕后要出来提示答对了多少题,提供答案给客户,
⑤界面尽量做的简单一点,不要出现太多其他东西
⑥要不要出一个VIP模式啊,如果想查看答案或者使用错题本功能必须要用VIP,你问我为什么?因为我想赚W。(不过吧。没必要)
⑦Tkinter的界面默认是白色的面板这可不行,这得搞点颜色才行,孩子有时间做题肯定是放学后的晚上吧,要是白色的不得给孩儿的眼闪瞎。(不过现在的小学大多都是住校的吧,听客户的话孩子应该是走读)
⑧那就搞点颜色吧,用几张图片当Tkinter的背景客户也可以更换其他图片当背景多张图片以供选择。(问题来了:为什么不用Tkinter自带的颜色呢?嗯en。纯色的话也挺刺眼吧)
那么怎么实施呢?
首先吧,使用TKinter创建一个窗口固定他的窗口大小不让用户乱调,给界面做一个背景----一张图片,再加一个开始按钮
点击开始按钮就自动生成题,用户在题后框内输入答案,点击提交后检测答对了多少道题,再加一个查看答案的按钮用来查看答案。
代码怎么写呢?↓
1,创建一个列表用来存放自动生成的数学题,在创建一个列表来存放题的答案。
创建一个集合来装载IntVar()对象目的在于通过get()方法来验证是否是正确答案并判断,对应的还有它的Entry对象,也是用列表来存放
2,然后就是编写方法了,点击开始按钮开始答题这就是第一个方法generateA:生成数学题;
然后生成控件并把数学题放到控件中去,这就是第二个方法generateB,;(一个方法如果包含太多的功能不太妥,一个方法过于臃肿、耦合度高到后面做的时候会很麻烦,所以我创建了多个方法)
3,计算答案方法transform,获取提交后答题情况的方法getResult,孩子不会做想查看答案时的:checkReult方法,查看答案,
别的不多说的。放成品代码吧
#python做的
import tkinter as t import tkinter.messagebox as message import random as r import time as f wi=t.Tk() #设置标题,分辨率,无法调动分辨率 wi.title('数学题s') wi.geometry('1280x720') wi.resizable(False,False) ############################## #changeBG()方法用于改变窗口皮肤,通过传入的数对应相应的图片,Python真好呀 def changeBG(style): SKIN=t.Label(wi,justify = t.LEFT,image = PicBox[style-1],compound = t.CENTER) SKIN.place(x=0, y=0, relwidth=1, relheight=1) ########################################################### generateM() #把题再印刷一遍,因为更新了标签Label所以原来的控件会消失,所以重新放置一般,主要是我解决不了(误) #此函数为用于计算题 division=["+","-","/","*"] def transform(first,second,division): if(division=="+"): return first+second elif(division=="-"): return first-second elif (division == "/"): return first / second elif (division == "*"): return first * second else: pass MathBulk = [] #用于存储数学题 MathAnswer = [] #存储答案 FaultList=[] #存储算错的题 def generateA(num): #自动生成数学题。通过transform方法算答案放到MathAnswer,题库放到MathBulk,num指定生成多少到题 global MathBulk #用于存储数学题 global MathAnswer #存储答案 global valueArea #这个集合保存了StringVar的数据 global StartStatus StartStatus = True startButton.place_forget() temp = [] #用于临时装在数据 for i in range(0,num): y = i y = t.IntVar() #这个错误找了好久,我凸 初始化了tkinter的所有对象(StringVar除外),应执行以下操作:name = StringVar()而不是name = StringVar现在,StringVar类的变量名-实例和实例将自动传递参数“self” valueArea.append(y) while True: first = r.randrange(1, 99) second = r.randrange(1, 99) div = division[r.randrange(0, 2)] titles = transform(first, second, div) if titles >= 0: #过滤掉小于零的题 MathAnswer.append(titles) temp = [str(first),str(div),str(second),"="] MathBulk.append("".join(temp)) if len(MathBulk) == num: break generateM() #把控件放置窗口 #生成Label和Entry用来做题,好复杂,我都不想写文档了 textArea=[] #存放Entry对象 valueArea=[] #存放IntVar() submit=1 def generateM(): it = iter(MathBulk) it2 = iter(valueArea) MenuBar.entryconfig("换肤Skin", state='normal') #提交按钮及方法 global submit submit=t.Button(wi,text='提交',command=lambda : getResult()) submit.place(x=1000,y=600) #查看答案按钮 check = t.Button(wi, text='查看答案', command=lambda: checkResult()) check.place(x=1000, y=400) while True: #可要可不要,我忘了我为啥写这个了 for x in range(100,980,150): t.Label(wi, text=next(it),width=50,height=20,image=subImage,compound = t.CENTER,font=("楷体", 10)).place(x=x, y=50) temp=t.Entry(wi, text="", width=5,textvariable=next(it2)) temp.place(x=x + 57, y=50) textArea.append(temp) #把生成的Entry对象放进textArea, for x in range(100,980,150): # t.Label(wi, text=next(it)).place(x=x, y=150) t.Label(wi, text=next(it), width=50, height=20, image=subImage, compound=t.CENTER, font=("楷体", 10)).place(x=x, y=150) t.Entry(wi, text="", width=5,textvariable=next(it2)).place(x=x + 57, y=150) for x in range(100,980,150): t.Label(wi, text=next(it),width=50,height=20,image=subImage,compound = t.CENTER,font=("楷体", 10)).place(x=x, y=250) t.Entry(wi, text="", width=5,textvariable=next(it2)).place(x=x + 57, y=250) for x in range(100, 980,150): t.Label(wi, text=next(it), width=50, height=20, image=subImage, compound=t.CENTER, font=("楷体", 10)).place(x=x, y=350) t.Entry(wi, text="", width=5,textvariable=next(it2)).place(x=x + 57, y=350) if next(it, None) != None: break if next(it, None) != None: break def getResult(): print('getResult()') Rate=0 it=iter(MathAnswer) for i in valueArea: s=next(it) if(i.get()==s): Rate=Rate+1 t.messagebox.askyesno(title='答题完毕', message='正确率题数:'+str(Rate)) error="" if(Rate==0): error="你答题全错" else: error=" 正确率为:" + str(100/(len(MathBulk)) /Rate) t.messagebox.askyesno(title='答题完毕', message=error) FaultSubject() #调用错题本记录方法 global submit submit.config(state=t.DISABLED) ##提交按钮不能再提交 def checkResult(): ##for i in range(0,len(MathAnswer)): ## valueArea[i].set(MathAnswer[i]) stranswer="" #用于做字符串,把答案放在一条字符串上 for i in range(0,len(MathAnswer)): stranswer=stranswer+(str(i+1)+("题")+str(MathAnswer[i])+(" ")) t.messagebox.askyesno(title='答案', message=stranswer) def FaultSubject(): #此方法把错误的题给记录到一个列表中去里,将来可以做一个错题本功能 it = iter(MathAnswer) for i in range(len(MathBulk)): if (MathAnswer[i] != valueArea[i].get()): FaultList.append(MathBulk[i]) #第二个窗口 ###################### ##显示这个错题窗口 def showFault(TF): backWindow="" if TF==False: backWindow = t.Tk() backWindow.geometry('1280x400') backWindow.resizable(False,False) textFiled = t.Text(backWindow, width=135, height=30, undo=True, autoseparators=False) textFiled.place(x=20, y=20) backWindow.update() backWindow.deiconify() textFiled.delete(t.INSERT, t.END) if(len(FaultList)>0): for i in FaultList: textFiled.insert(t.INSERT,i+"? ") textFiled.config(state=t.DISABLED) else: backWindow.withdraw() ##隐藏错题的窗口而已 def hideFault(): pass #------------------------------此处为背景皮肤------------------ phote1 = t.PhotoImage(file='Pic/python.png') #Python phote2 = t.PhotoImage(file='Pic/circle.png') #圆环 phote3 = t.PhotoImage(file='Pic/kiting.png') #奢华 phote4 = t.PhotoImage(file='Pic/blue.png') #小❤二刺螈 phote5 = t.PhotoImage(file='Pic/tank.png') #坦克 phote6 = t.PhotoImage(file='Pic/AK105.png') #枪械 phote7 = t.PhotoImage(file='Pic/abstract.png') #抽象 subImage = t.PhotoImage(file='Pic/sub.png') #题 PicBox = [phote1,phote2,phote3,phote4,phote5,phote6,phote7] #把图片装起来 #------------------------------此处为背景皮肤------------------ #默认皮肤 SKIN = t.Label(wi,text = "Deep Blue Pure White",justify = t.LEFT,image = phote2, compound = t.CENTER,font = ("华文行楷", 20),fg = "white") SKIN.place(x=0,y=0,relwidth=1,relheight=1) #开始按钮 如果有其他控件使用了pack方式的布局,后面就不能使用grid布局,会报错的,就是因为这里使用过pack方式 ButtonImage=t.PhotoImage(file='Pic/OpcityBT.png') startButton=t.Button(wi,text='开始学习!',width=100,height=30,image=ButtonImage ,justify = t.LEFT,compound = t.CENTER ,command = lambda : generateA(20)) startButton.place(x=600,y=300) StartStatus = False #判断是否已经把题给生成好了,默认False,等使用了generateA后就是True了 #菜单 MenuBar=t.Menu(wi) SkinMenu=t.Menu(MenuBar,tearoff=0) Quit=t.Menu(MenuBar,tearoff=0) ##登出键 MenuBar.add_command(label='退出',command=lambda: t._exit()) FaultMenu=t.Menu(MenuBar,tearoff=0) ##错题本 ##皮肤的命令 MenuBar.add_cascade(label='换肤Skin',menu=SkinMenu) SkinMenu.add_command(label='程序员',command=lambda: changeBG(1)) SkinMenu.add_command(label='艺术',command=lambda: changeBG(2)) SkinMenu.add_command(label='奢华',command=lambda: changeBG(3)) SkinMenu.add_command(label='抽象',command=lambda: changeBG(7)) SkinMenu.add_command(label='二刺猿',command=lambda: changeBG(4)) SkinMenu.add_command(label='汽车',command=lambda: changeBG(5)) SkinMenu.add_command(label='枪械',command=lambda: changeBG(6)) MenuBar.entryconfig("换肤Skin",state='disabled') ##错题本的菜单 isAlreadyCreate=False MenuBar.add_command(label='错题记录',command=lambda: showFault(isAlreadyCreate)) #菜单显示出来 wi.config(menu=MenuBar) #窗口开始循环 wi.mainloop()
首先是一个默认界面只有开始学习按钮
开始后就自动生成题,默认答案都是0
点击查看答案就会吧答案显示出来,自动的放进Entry对象中,我这就不演示了,
提交后就会显示你做对了多少道题
可以更换皮肤 (这玩意我花了很长时间,我也不知道我做这个为了啥,开始做题后才可以变的)
那么这些图片有没有版权问题?我觉得不会,会画画的谁闲着没事逛博客园呢
总结
花费时间10+小时吧,具体忘了多少,我闲着没事会记这个吗,放假这么多天一天做一点,忘了
具体就
结语:
害,做这个玩意儿花好长时间,关键是考试他都不考这些你说气人不,我也不觉得我的编码技术提高了什么。说来这程序也就有矛盾,家长给孩子整个电脑做题这合适吗
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5-5更新:
代码之前是直接粘贴的,不是很美观,现在 已经是用bokeyuan自带的"插入代码",会让代码更直观一点
加入了错题本。做题后会记录