中小学数学卷子自动生成程序——与Creddit同学的结对编程项目分析

1.简单介绍


项目名称:中小学数学卷子自动生成程序

主要功能:a.登陆

                     通过命令行输入账号和密码进行登陆,成功后出现提示

                     否则需要重新输入

                  b.切换难度

                     可以输入“切换为XX”,修改生成题目的类型,如小学,初中,高中,不符合要求时提示重新输入

                  c.随机生成试卷

                     根据提示,输入数字,可以随机生成需要的数量的题目,题目难度默认为账户类型,亦可输入切换;

                     生成的试卷以txt格式和固定格式的文件名保存在特定的目录下;

                     新生成的题目不能与同文件夹下的题目重复。

                 D.附录

                     小学、初中、高中题目难度要求

小学

初中

高中

难度要求

+,-,*./

平方,开根号

sin,cos,tan

备注

只能有+,-,*./和()

题目中至少有一个平方或开根号的运算符

题目中至少有一个sin,cos或tan的运算符

2.开发环境

                  Windows10 python3.7

3.思路结构

                 由于老师提供的说明文档中已经对项目的要求介绍的非常详细。正常的一个思路就是将程序分为几个模块,包括:登陆,切换,生成等。

                 我的队友也不例外,他的python源代码中,除了主函数外,分为了Validlogin(), response_login(), paper_generating() 三个部分,从函数名就可以知道,我的队友想法相同。

                  那么我们就接下来就从这三个部分入手。

4.关键部分介绍

A.Validlogin() (登陆部分)

 1 def Validlogin():
 2     global user_id,level
 3     print('输入用户名和密码,两者之间用空格隔开')
 4     try:
 5         f=open("USER_IDlist.txt","r",encoding="utf-8")
 6         userlist=f.read().split('\n')
 7         login_flag=False
 8         while True:
 9             user_login=input().split(' ')
10             while len(user_login)!=2:
11                 user_login=input("请输入正确的用户名、密码:").split(' ')
12             id=user_login[0]
13             psd=user_login[1]
14             for i in range(len(userlist)):
15                 str=userlist[i].split()
16                 if str[0].lstrip("username:")==id and str[1].lstrip("password:")== psd:
17                     level=str[2].lstrip("level:")
18                     user_id=id
19                     login_flag=True
20             if login_flag:
21                 print("登陆成功!\n当前选择为{}出题".format(level))
22                 break
23             else: print("请输入正确的用户名、密码! ")
24     except Exception as error:
25         print(error)

            全局变量 user_id, level 分别代表登陆的账户的用户名和生成试卷难度

            由于读取文件可能会产生异常,用try/except控制。

            队友将文档提供的账户和密码保存为 文件USER_IDlist.txt中,每次登陆前先进行读取。

            接下里是一个while循环配合flag标志判断输入的账号名和密码是否正确。

            这一部分的逻辑比较简单,直接遍历预设的账户,判断是否符合。

B.reponse_login()

def response_login():
    try:
        while True:
            global level,num
            str=input('准备生成{}数学题目,请输入生成题目数量,大小范围在(含)10-30以内:'.format(level))
            result = re.match(r'切换为(.+)', str)
            if  str.isdigit() :
                if int(str)<10 or int(str)>30:
                    print("输入范围不符合要求!")
                    continue
                else:
                    num=int(str)
                    break
            elif result:
                if(result.group(1)=='小学' or result.group(1)=='初中' or result.group(1)=='高中'):
                    level=result.group(1)
                    print("切换成功!")
                    continue
                else:
                    print("请输入小学,初中,高中三个选项中的一个!")
                    continue
            elif not result:
                try:
                    if int(str)==-1:
                        print("即将重新登陆!")
                        Validlogin()
                    else:print("请输入正确的命令!")
                except:
                    print("请输入正确的命令!")

    except Exception as error:
        print(error)

           第二部分是选择部分 。这部分有两个功能:切换难度和输入题号,因此需要判断输入的字符串是题数或是切换难度的关键词。

           输入后,使用match()判断是否匹配关键字,使用isdigit()判断是否是数字。

           当输入为切换难度时,判断难度类型是否符合,若符合,用全局变量level提取。

           当不是输入数字时,可以一直切换难度,所以整体是在while循环中。

           使用全局变量num,将输入的题号提取。

c.paper_generating()

def paper_generating():
    global level,num
    content = ''
    pre_time = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
    pre_path = os.getcwd()
    targetpath = pre_path + '/' + user_id+'/'+level
    ques_set = set()
    if not os.path.exists(targetpath):
        os.makedirs(targetpath)
    files = os.listdir(targetpath)
    for file in files:
        text_path = targetpath + '/' + file
        text = open(text_path, 'r',encoding='utf-8')
        content += text.read()
    for j in range(num):
        question=[]
        operater_num = random.randint(1, 5)
        k = operater_num - 2
        if operater_num < 2:
            k = 0
        bracket_num = random.randint(0, k)
        for i in range(operater_num+1):
            question.append(str(random.randint(MIN_N,MAX_N)))
            question.append(Arithmetic_operator[random.randint(0,3)])
        question.append(str(random.randint(MIN_N,MAX_N)))
        ins=[2*i for i in range(operater_num+1)]
        if level=='初中':
            add_num=random.randint(1,2)
            for i in range(add_num):
                if(random.randint(0,1)==1):
                    question[ins[random.randint(0,operater_num)]] = ps_operator[0] + question[ins[i]]
                else:
                    question[ins[random.randint(0,operater_num)]] =question[ins[i]]+ps_operator[1]
        if level=='高中':
            add_num_1 = random.randint(0, 1)
            add_num_2=random.randint(1,2)
            for i in range(add_num_1):
                if(random.randint(0,1)==1):
                    question[ins[random.randint(0,operater_num)]] = ps_operator[0] + question[ins[i]]
                else:
                    question[ins[random.randint(0,operater_num)]] =question[ins[i]]+ps_operator[1]
            for i in range(add_num_2):
                k=random.randint(0,2)
                question[ins[random.randint(0,operater_num)]] =Trigonometric_operator[k] +"("+ question[ins[i]]+")"
        for i in range(bracket_num):
            question[ins[i]]='('+question[ins[i]]
            t=random.randint(1,2)
            question[ins[i+t]] = question[ins[i+t]]+')'
        for i in range(len(question)):
            if re.match(r'\([0-9]+\)', question[i]):
                if not (re.match(r'sin\([0-9]+\)', question[i]) or re.match(r'cos\([0-9]+\)', question[i]) or re.match(
                        r'tan\([0-9]+\)', question[i])):
                    question[i] = str(random.randint(1, 100))
        ques = ''.join(question)
        ques_set.add(ques)
        if ques in content or len(ques_set) == j:
            j -= 1
            continue
        f = open(targetpath + '/' + pre_time + '.txt', 'a',encoding='utf-8')
        f.write('(' + str(j + 1) + ') ' + ques + " = ?" + '\n'+'\n')
    print("出题成功!",end='')

          第三部分是生成题目保存到文件。

          生成文件部分比较常规,利用time的函数,直接生成以时间命名的文件,并根据当前路径进行存放。

          读取旧文件,先将所有字符保存到一个字符串content中。

          然后根据难度随机生成题目。

          生成题目分为三步基本以random为核心。

          先随机生成不定数量不定值的操作数;然后根据不同难度会用到不同的符号,采用全局变量的数组控制;在随机生成一些括号加入到式子中。

          生成后的式子到content中进行比较,如果能在content找到则说明重复,则重新生成。

 5.结果展示

总结:

         队友采用python进行开发,而我采用了Java语音。两份项目很大的差异也是由开发环境不同导致的。自己完成工程后,再学习别人的代码,体验非常新鲜有趣。

         

优点:

         与Java相比,python更加简单简洁,虽然Java也有很多好用的包、工具,但是使用起来也不方便,无论是配置环境的导入或是在代码上的实现,比起python还是麻烦太多。
         并且Java类似c、c++的语法,加上面向对象的代码风格,在编写这种简单的项目代码量会增加很多。

缺点:

        虽然队友的逻辑和实现都没有什么问题,但是由于空行分段比较少,看起来比较密集,寻找代码中的细节没有那么容易。

猜你喜欢

转载自www.cnblogs.com/One-Random/p/11551526.html