计应193第一组小学生做题软件——任远航

需求分析:作为一名小学生的家长,我希望制作一个出题软件,完成100以内的正整数的加减法题./....以减轻我的家庭负担?

    这是一个程序,实现简单出题并提供答案就行

   (其实给小学生整个电脑软件让做题就挺离谱的,从小盯电脑眼不得看坏了?汗。。其次:现在一年级的学生都玩电脑了吗)

技术难点:

  1. 制作一个可以互动的GUI
  2. 随机生成数学题
  3. GUI设置后,把生成的数学题放到GUI
  4. 题做完后提交,要验证答案是否正确,对了多少道题

思考:

  首先这样的一个程序是一个带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自带的"插入代码",会让代码更直观一点

加入了错题本。做题后会记录

原文地址:https://www.cnblogs.com/bladepoint/p/14829120.html