【Python】- 实现一个小程序,随机出题、判题、打分功能

579 阅读5分钟

我正在参加「掘金·启航计划」

最近在学习python,刚好看到一个需求,尝试实现下,题目如下
文章最后面会有完整的代码

  • 效果如下 image.png

【开发信息】

1)python版本:3.6 2)开发工具:VS 2017 3)操作系统:windows11

【题目信息】

  • 实现一个小程序,有如下功能 1)随机出题(30以内整数加减乘除法的算术题)
    2)判题,
    3)打分,
  • 要求如下 1)使用tkinter库绘制界面
    绘制生成图形界面窗口,高宽度大小为800x600
    2)界面元素
    若干标签控件Label、
    若干文本框控件Entry、
    三个命令按钮控件Button、
    以及其他个性化控件元素,根据自己觉得不错的控件
    3)标签、文本框、按钮
    label_name=姓名(标签),input_name=请输入姓名(文本框)
    label_no=学号(标签),input_no=请输入学号(文本框)
    label_questionId=题号(标签)
    label_question_num=题目数字(标签)
    label_operator=运算符+-* /(标签)
    label_equal=等号(标签)
    label_result=结果(文本框)
    button_random=随机生成试题(按钮)
    button_confirm=提交(按钮)
    button_answer=查看答案(按钮)
    4)随机生成10个题目,且是简单的单步运算题目,如下
    比如:5+8=__ 7-3=__ 2 * 4=__ 5÷2=__
    注:除法结果为整数即可
  • 程序流程 1)学生在界面上输入自己的姓名、学号信息
    使用字典学号和姓名键值对保存多组数据,点击随机生成试题按钮时判断是否存在当前输入的学社会功能信息
    如果输入信息为空,那么使用messagebox弹出提示信息:“请注意:姓名或学号不能为空”
    如果存在学生信息,那么自动生成10道简单的加减乘除运算题目,否则弹出对话框窗口提示“姓名或学号有误,请重新输入!”
    2)学生在每个题目对应的文本框中输入对应答案
    3)答题结束之后,点击提交按钮,页面给出学生的测试成绩(成绩为百分制)
    4)最后,可以点击查看答案按钮,查看本次测试的正确答案
    注意:在提交按钮按下之前,查看答案按钮应该是灰色、不可用的状态。或者,如果没有做完全部题目就点击查看答案按钮,则自动提交现有题目,并显示分数
    5)当点击提交按钮时,根据实际答案情况给出成绩,并将本次测试页面的全部基础信息(含:学生信息/题目/结果/成绩等),存入磁盘文件【学生姓名-学生学号.txt】;多次运行此程序测试、做题,磁盘文件根据测试时间,内容应能顺序记录追加(可正序,也可逆序);【注意:文件中不能只有最后一次的测试信息记录】 6)设计窗口中各种元素的布局

【tkinter库信息】

1)tkinter是python自带的GUI界面模块
2)导入模块
import tkinter as tk
as后面的是别名,和sql字段as别名一样
3)使用TK方法创建一个窗口
main_windows = tk.Tk()
还需要添加一个主方法才能显示
main_windows.mainloop()
4)设置标题
必须再主方法之前
main_windows.title('计算器') 5)设置长宽以及窗口坐标

【有趣知识点】

1)方法外定义变量,在方法内赋值,结果值不变
以下代码value值不变,还是2
image.png

value=2
def test():
    value=value*10
  • 解决方法 在方法内,使用global关键词声明
    global value
    image.png

【完整代码】

可以根据需求情况,精简代码

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# 2022.06.08 11:23
import tkinter as tk
from tkinter import *
from tkinter import messagebox
import random as rd
import math

my_name = ''
my_no = ''
entry_no_value = ''
entry_name_value = ''
my_info={
    "my_no":"",
    "my_name":"",
    "my_score":0,
    "answer":{},
    "my_answer":{}
}
operator=['+','-','*','÷']
student_info = [{'no':1,'name': '张三'},{'no':2,'name': '李四'},{'no':3,'name': '王五'}]

# 随机生成试题 - 点击事件
def randomCreateQuestion():
    my_no = entry_no_value.get()
    my_name = entry_name_value.get()
    my_info['my_no']=my_no
    my_info["my_name"]=my_name
    flag = 0
    for item in student_info:
        if str(item['no']) == my_no and item['name'] == my_name:
            flag = 1
            break
    if my_no.strip() == '' and my_name.strip() == '':
        messagebox.askyesno("温馨提示","请注意:姓名或学号不能为空!", icon='info', default='no')
    elif flag == 0:
        messagebox.askyesno("温馨提示","姓名或学号有误,请重新输入!", icon='info', default='no')
    else:
        button_random.config(state=tk.DISABLED)
        createQuestion()

mw = tk.Tk()

# 创建窗口
def createWindows():
    mw.title('简单运算试题') # 设置标题
    mw.geometry("800x600") # 绘制窗口的长宽
createWindows()

# 创建学号 - 标签和输入文本框
def createNoLabelEntry():
    global entry_no_value
    label_no = tk.Label(mw, text="学号:")
    label_no.place(x=100,y=100)
    entry_no_value = _entry_no_value = StringVar()
    entry_no = tk.Entry(mw, bd =1,textvariable=_entry_no_value)
    entry_no.place(x=140,y=100)
createNoLabelEntry()

# 创建姓名标签和输入文本框
def createNameLabelEntry():
    global entry_name_value
    label_name = tk.Label(mw, text="姓名:")
    label_name.place(x=100,y=130)
    entry_name_value = _entry_name_value = StringVar()
    entry_name = tk.Entry(mw, bd =1,textvariable=_entry_name_value)
    entry_name.place(x=140,y=130)
createNameLabelEntry()

# 随机生成试题 - 按钮
button_random={}
def createRandomButton():
    global button_random
    button_random=_button_random = tk.Button(mw, text="随机生成试题",command=randomCreateQuestion)
    _button_random.place(x=140,y=160)
createRandomButton()

# 提交 - 按钮
confirm_button={}
def createConfirmButton():
    global confirm_button
    button = tk.Button(mw, text="提交",command=getScore)
    button.place(x=100,y=190+10*30,w=60)
    confirm_button=button

# 计算成绩
def getScore():
    index=0
    my_score=0
    for value in answer:
        _v=my_answer[index].get()
        if _v=='':
            continue
        my_value=int(_v)
        index+=1
        if value==my_value:
            my_score+=10 # 回答正确一题加10分
        else:
            continue
    my_info["my_score"]=my_score
    confirm_button.config(state=tk.DISABLED)       # 提交按钮不可点击状态
    answer_button.config(state=tk.ACTIVE)          # 查看按钮可点击状态
    button_random.config(state=tk.ACTIVE)          # 随机生成试题
    testScoreLabel() # 显示成绩
    writeTxt()       # 将本次信息写入到txt
    
# 测试成绩 - 标签
def testScoreLabel():
    label = tk.Label(mw, text="您的本次测试成绩为:%s" % my_info["my_score"])
    label.place(x=100,y=200+11*30)
    
# 按钮 - 查看答案
answer_button={}
def createAnswerButton():
    global answer_button
    button = tk.Button(mw, text="查看答案",command=displayAnswer)
    button.place(x=180,y=190+10*30,w=60)
    button.config(state=tk.DISABLED)
    answer_button=button

# 标签 - 显示答案 
def displayAnswer():
    index=0
    for value in answer:
        color='#f60'
        _v=my_answer[index].get()
        if _v!='':
            my_value=int(_v)
            if value==my_value:
                color='#099dff'
        label = tk.Label(mw, text="%s" % str(value),fg=color)
        label.place(x=300,y=190+index*30)
        index+=1
    answer_button.config(state=tk.DISABLED)          # 查看答案按钮不可点击状态

# 输出信息到txt
def writeTxt():
    file_name='%s/%s-%s.txt' % ("calculator",my_info['my_name'],my_info['my_no'])
    with open(file_name, 'a', newline='') as write_f:
        write_f.write('学号:%s\n姓名:%s\n本次测试成绩:%s\n' % (my_info["my_no"],my_info["my_name"],str(my_info['my_score'])))
        index=0
        my_score=0
        for value in answer:
            line_str='[%s]、%s' % (str(index+1),my_info["question"][index])
            _v=my_answer[index].get()
            if _v!='':
                my_value=int(_v)
                if value==my_value:
                    color='#099dff'
                line_str+=' %s (%s)' % (my_value,value)
            else:
                line_str+=' %s (%s)' % ('',value)
            index+=1
            write_f.write('%s\n' % (line_str))
        write_f.write('\n')

# 循环生成10道试题
answer=[]
question=[]
my_answer=[]
def createQuestion():
    answer.clear();
    my_answer.clear();
    max_num=30      # 最大整数30
    max_count=10    # 10道题目
    unit_value=30   # 控件之间的间距
    for index in range(max_count):
        # 题号 - 标签
        new_str="[%s]、" % (str(index+1))
        label = tk.Label(mw, text=new_str)
        label.place(x=100,y=190+index*unit_value)
        # 题目数字和运算符 - 标签
        left_num=math.floor(rd.random()*30)+1
        right_num=math.floor(rd.random()*30)+1
        operator_index=math.floor(rd.random()*4)
        operator_index=math.floor(rd.random()*4)
        operator_value=operator[operator_index]
        new_str="%-5s%-5s%-5s = " % (str(left_num),str(operator_value),str(right_num))
        question.append(new_str)
        label_q = tk.Label(mw, text=new_str)
        label_q.place(x=130,y=190+index*unit_value)
        if operator_index==0:
            answer.append(left_num+right_num)
        elif operator_index==1:
            answer.append(left_num-right_num)
        elif operator_index==2:
            answer.append(left_num*right_num)
        elif operator_index==3:
            answer.append(math.floor(left_num/right_num))
        # 答案 - 文本框
        entry_answer_value = StringVar()
        my_answer.append(entry_answer_value)
        entry_answer = tk.Entry(mw, bd =1,textvariable=entry_answer_value)
        entry_answer.place(x=240,y=190+index*unit_value,w=50)
        my_info["answer"]=answer
        my_info["question"]=question
        my_info["my_answer"]=my_answer
        # 创建提交和查看答案按钮
        createConfirmButton()
        createAnswerButton()

mw.mainloop()