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

简介: 最近在学习python,刚好看到一个需求,尝试实现下,题目如下文章最后面会有完整的代码
作者:小5聊基础
简介:一只喜欢全栈方向的程序员,欢迎咨询,尽绵薄之力答疑解惑
编程原则:Write Less Do More
  • 效果如下

image.png

【开发信息】

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

【题目信息】

  • 实现一个小程序,有如下功能

1)随机出题(30以内整数加减乘除法的算术题)<br/>
2)判题,<br/>
3)打分,<br/>

  • 要求如下

1)使用tkinter库绘制界面 <br/>
绘制生成图形界面窗口,高宽度大小为800x600 <br/>
2)界面元素 <br/>
若干标签控件Label、<br/>
若干文本框控件Entry、<br/>
三个命令按钮控件Button、<br/>
以及其他个性化控件元素,根据自己觉得不错的控件<br/>
3)标签、文本框、按钮<br/>
label_name=姓名(标签),input_name=请输入姓名(文本框)<br/>
label_no=学号(标签),input_no=请输入学号(文本框)<br/>
label_questionId=题号(标签)<br/>
label_question_num=题目数字(标签)<br/>
label_operator=运算符+-* /(标签) <br/>
label_equal=等号(标签)<br/>
label_result=结果(文本框)<br/>
button_random=随机生成试题(按钮)<br/>
button_confirm=提交(按钮)<br/>
button_answer=查看答案(按钮)<br/>
4)随机生成10个题目,且是简单的单步运算题目,如下<br/>
比如:5+8=__ 7-3=__ 2 * 4=__ 5÷2=__ <br/>
注:除法结果为整数即可 <br/>

  • 程序流程

1)学生在界面上输入自己的姓名、学号信息 <br/>
使用字典学号和姓名键值对保存多组数据,点击随机生成试题按钮时判断是否存在当前输入的学社会功能信息 <br/>
如果输入信息为空,那么使用messagebox弹出提示信息:“请注意:姓名或学号不能为空” <br/>
如果存在学生信息,那么自动生成10道简单的加减乘除运算题目,否则弹出对话框窗口提示“姓名或学号有误,请重新输入!” <br/>
2)学生在每个题目对应的文本框中输入对应答案 <br/>
3)答题结束之后,点击提交按钮,页面给出学生的测试成绩(成绩为百分制) <br/>
4)最后,可以点击查看答案按钮,查看本次测试的正确答案 <br/>
注意:在提交按钮按下之前,查看答案按钮应该是灰色、不可用的状态。或者,如果没有做完全部题目就点击查看答案按钮,则自动提交现有题目,并显示分数 <br/>
5)当点击提交按钮时,根据实际答案情况给出成绩,并将本次测试页面的全部基础信息(含:学生信息/题目/结果/成绩等),存入磁盘文件【学生姓名-学生学号.txt】;多次运行此程序测试、做题,磁盘文件根据测试时间,内容应能顺序记录追加(可正序,也可逆序);【注意:文件中不能只有最后一次的测试信息记录】
6)设计窗口中各种元素的布局

【tkinter库信息】

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

【有趣知识点】

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

value=2
def test():
    value=value*10
  • 解决方法

在方法内,使用global关键词声明<br/>
global value<br/>
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()
相关文章
|
1月前
|
计算机视觉 Python
Python实用记录(一):如何将不同类型视频按关键帧提取并保存图片,实现图片裁剪功能
这篇文章介绍了如何使用Python和OpenCV库从不同格式的视频文件中按关键帧提取图片,并展示了图片裁剪的方法。
66 0
|
4天前
|
缓存 监控 测试技术
Python中的装饰器:功能扩展与代码复用的利器###
本文深入探讨了Python中装饰器的概念、实现机制及其在实际开发中的应用价值。通过生动的实例和详尽的解释,文章展示了装饰器如何增强函数功能、提升代码可读性和维护性,并鼓励读者在项目中灵活运用这一强大的语言特性。 ###
|
7天前
|
缓存 开发者 Python
探索Python中的装饰器:简化代码,增强功能
【10月更文挑战第35天】装饰器在Python中是一种强大的工具,它允许开发者在不修改原有函数代码的情况下增加额外的功能。本文旨在通过简明的语言和实际的编码示例,带领读者理解装饰器的概念、用法及其在实际编程场景中的应用,从而提升代码的可读性和复用性。
|
12天前
|
设计模式 缓存 测试技术
Python中的装饰器:功能增强与代码复用的艺术####
本文将深入探讨Python中装饰器的概念、用途及实现方式,通过实例演示其如何为函数或方法添加新功能而不影响原有代码结构,从而提升代码的可读性和可维护性。我们将从基础定义出发,逐步深入到高级应用,揭示装饰器在提高代码复用性方面的强大能力。 ####
|
13天前
|
缓存 测试技术 数据安全/隐私保护
探索Python中的装饰器:简化代码,增强功能
【10月更文挑战第29天】本文通过深入浅出的方式,探讨了Python装饰器的概念、使用场景和实现方法。文章不仅介绍了装饰器的基本知识,还通过实例展示了如何利用装饰器优化代码结构,提高代码的可读性和重用性。适合初学者和有一定经验的开发者阅读,旨在帮助读者更好地理解和应用装饰器,提升编程效率。
|
20天前
|
开发者 Python
探索Python中的装饰器:简化代码,增强功能
【10月更文挑战第22天】在Python的世界里,装饰器是一个强大的工具,它能够让我们以简洁的方式修改函数的行为,增加额外的功能而不需要重写原有代码。本文将带你了解装饰器的基本概念,并通过实例展示如何一步步构建自己的装饰器,从而让你的代码更加高效、易于维护。
|
16天前
|
小程序 数据挖掘 UED
开发1个上门家政小程序APP系统,都有哪些功能?
在快节奏的现代生活中,家政服务已成为许多家庭的必需品。针对传统家政服务存在的问题,如服务质量不稳定、价格不透明等,我们历时两年开发了一套全新的上门家政系统。该系统通过完善信用体系、提供奖励机制、优化复购体验、多渠道推广和多样化盈利模式,解决了私单、复购、推广和盈利四大痛点,全面提升了服务质量和用户体验,旨在成为家政行业的领导者。
|
21天前
|
开发框架 Python
探索Python中的装饰器:简化代码,增强功能
【10月更文挑战第20天】在编程的海洋中,简洁与强大是航行的双桨。Python的装饰器,这一高级特性,恰似海风助力,让代码更优雅、功能更强大。本文将带你领略装饰器的奥秘,从基础概念到实际应用,一步步深入其内涵与意义。
|
27天前
|
云计算 Python
用python给你写个简单的计算器功能网页啊
这张图片展示了阿里巴巴集团的组织架构图,涵盖了核心电商、云计算、数字媒体与娱乐、创新业务等主要板块,以及各板块下的具体业务单元和部门。
|
1月前
|
设计模式 开发者 Python
Python中的装饰器:简化代码与增强功能
【10月更文挑战第9天】在编程的世界里,效率和可读性是衡量代码质量的两大关键指标。Python语言以其简洁明了的语法赢得了无数开发者的青睐,而装饰器则是其独特魅力之一。本文将深入探讨装饰器的工作原理、使用方法以及如何通过自定义装饰器来提升代码的重用性和可维护性,让读者能够更加高效地编写出既优雅又功能强大的代码。