湖南大学结对编程个人项目互评

一、简介:

   本博客为对结对编程队友的个人项目代码的评价分析

 

二、代码结构分析:

   1.数据变量

      由下图可以看出队友使用列表数据类型带表示9位老师的用户名和密码,加减乘除也放在operatorList列表中,还有下方一系列用户操作的变量

import os
import random
import time

personList = [['小学', '张三1', '123'], ['小学', '张三3', '123'], ['小学', '张三3', '123'],
              ['初中', '李四1', '123'], ['初中', '李四2', '123'], ['初中', '李四3', '123'],
              ['高中', '王五1', '123'], ['高中', '王五2', '123'], ['高中', '王五3', '123']]
operatorList = ['+', '-', '*', '/']
user_name = ''  # 用户名字
level = ''  # 题目难度
command = ''  # 中间变量,存储命令
question_num = ''  # 试卷题目数量
judge = ''  # 中间变量,用于满足-1跳出

  

2.方法函数

  这里我们从__main__部分开始看函数,开头直接进入main函数了

if __name__ == '__main__':
    main()

  

  下图为main函数部分,在这里队友先调用了login()函数,即登录函数,登录函数在下面分析,之后调用set()函数建立集合,用于存放生成的试卷,接下来调用get_num()函数,提示用户输入题目数量和题目难度,使用全局变量judge表示输入-1则重新登录,接下来获取时间,生成存放试卷的txt文档,读取历史题目文档,使用for循环调用create_question()生成题目,同时进行查重,如果没有重复则加入试卷中,按顺序生成规定数量的题目后,提示用户生成试卷成功

def main():
    global judge
    while True:
        content = ''
        judge = False
        login()
        q_set = set()
        get_num()
        if judge:  # 如果输入-1则重新登录
            continue
        pre_time = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
        pre_path = os.getcwd()
        targetpath = pre_path + '/' + user_name + '/' + level  # 生成文件目录
        # 如果没有文件则创建
        if not os.path.exists(targetpath):
            os.makedirs(targetpath)
        files = os.listdir(targetpath)
        # 遍历当前目录下的文件读取历史题目到content
        for file in files:
            text_path = targetpath + '/' + file
            text = open(text_path, 'r', encoding='utf-8')
            content += text.read()
        # 循环生成题目并查重保存到指定目录
        for i in range(int(question_num)):
            q_temp = ''.join(create_question())
            q_set.add(q_temp)
            if len(q_set) == i or (q_temp in content):
                i -= 1
                continue
            f = open('{0}/{1}.txt'.format(targetpath, pre_time), 'a', encoding='utf-8')
            f.write('(' + str(i + 1) + ')' + q_temp + '\n' + '\n')
            f.close()
        print('生成试卷成功,请重新登录')

  

  接下来是login()函数就是将输入的用户名和密码与系统中存放的用户密码进行对比,没有返回值,而是通过修改全局变量来传递参数

def login():
    """实现登录功能

    按照输入与列表存储的用户信息匹配判断是否通过登录

    Return:
        如果输入满足条件则跳出函数执行下一部分
        如果输入不满足条件则打印输出请输入用户名和密码
    """
    global user_name, level
    login_flag = False
    print('请输入用户名和密码,两者之间用空格隔开')
    while True:
        str_user = input().split(' ')  # 临时变量,获取当前命令行输入
        if len(str_user) != 2:
            print('请输入正确的用户名、密码')
            continue
        inner_name = str_user[0]
        inner_password = str_user[1]
        # 以下for循环判断输入用户和密码是否匹配
        for i in range(len(personList)):
            if inner_name == personList[i][1]:
                if inner_password == personList[i][2]:
                    login_flag = True
                    user_name = inner_name
                    level = personList[i][0]
        if login_flag:
            break
        else:
            print('请输入正确的用户名、密码')

  

  get_num()函数,这里就到了检测用户输入来进行操作了,输入数字10-30就生成题目,输入切换为+学历就切换出题学历,同样,这里的代码没有返回值,就通过全局变量来进行参数的返回判断

def get_num():
    """获取题目数量和题目难度

    按照输入获取题目数量和难度等级,输入格式不对则提醒重新输入

    Return:
        经过函数调用返回当前题目数量和题目难度
    """
    global command, question_num, judge, level
    while True:
        print('准备生成' + level + '数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):')
        command = input()
        if command == '-1':
            judge = True
            break
        # 判断输入是否为纯数或为字符串
        if command.isdigit():
            question_num = int(command)
            if 30 >= question_num >= 10:
                break
            else:
                print('输入范围不符合要求!')
                continue
        if command == '切换到小学':
            level = '小学'
            continue
        if command == '切换到初中':
            level = '初中'
            continue
        if command == '切换到高中':
            level = '高中'
            continue
        else:
            print('请输入小学、初中和高中三个选项中的一个')
            continue

  

  下面就是重点creat_question()函数,这里就是按所选的难度生成一个题目

   队友生成题目这部分运用了些巧妙的构思,因为小学初中高中的难度是在上一个难度递增的,所以他首先生成数字和加减乘除的简单组合运算,然后判断如果当前难度不等于小学,就添加根号或平方(如果当前难度为初中则保证至少一个根号或平方),如果当前难度为高中,就添加三角函数(保证至少一个三角函数),这样的方式就保证了代码的简洁化

def create_question():
    """生成题目,按所选难度依次逐步生成

    按照选取的难度,随机生成操作数和操作符,按梯度生成题目,并将题目存在列表返回

    Return:
        返回一个列表,列表存储当前生成题目
    """
    global level
    out_date = []
    operand = random.randint(1, 5)
    brackets_num = random.randint(0, operand - 1)  # 随机括号个数
    # 随机生成数值和操作符
    for i in range(operand - 1):
        out_date.append(str(random.randint(1, 100)))
        out_date.append(operatorList[random.randint(0, 3)])
    out_date.append(str(random.randint(1, 100)))
    out_date.append('=')
    # 以下while循环实现加括号,通过brackets_num变量判断括号是否加完
    while brackets_num != 0:
        choose_before = random.randint(0, len(out_date) - 2)
        if out_date[choose_before].isdigit():
            out_date.insert(choose_before, '(')
            while True:
                choose_after = random.randint(choose_before + 1, len(out_date) - 1)
                if out_date[choose_after].isdigit():
                    out_date.insert(choose_after + 1, ')')
                    brackets_num = brackets_num - 1
                    break
    if level == '小学':  # 判断难度是否在此返回
        return out_date
    gp = 0  # 判断是否加根号或平方
    # 以下for循环遍历合理位置随机加根号或平方
    for i in range(len(out_date)):
        if out_date[i].isdigit() or out_date[i] == '(':
            temp = random.randint(0, 1)
            if temp == 0:
                out_date[i] = '√' + out_date[i]
                gp = 1
                continue
        if out_date[i].isdigit() or out_date[i] == ')':
            temp = random.randint(0, 1)
            if temp == 1:
                out_date[i] = out_date[i] + '^2'
                gp = 1
                continue
    # 以下循环实现若难度为初中且没有加平方或根号则随机加一
    while gp != 1 and level == '初中':
        i = random.randint(0, len(out_date) - 1)
        if out_date[i].isdigit():
            temp = random.randint(0, 1)
            if temp == 0:
                out_date[i] = '√' + out_date[i]
                gp = 1
            if temp == 1:
                out_date[i] = out_date[i] + '^2'
                gp = 1
        if out_date[i] == ')':
            out_date[i] = out_date[i] + '^2'
            gp = 1
        if out_date[i] == '(':
            out_date[i] = '√' + out_date[i]
            gp = 1
    if level == '初中':  # 判断难度是否在此返回
        return out_date
    gpc = 0  # 判断是否加三角函数运算符
    # 以下循环遍历合理位置随机加或不加三角运算符
    for i in range(len(out_date)):
        if out_date[i].isdigit() or out_date[i] == '(' or out_date[i] == '√':
            temps = random.randint(0, 1)
            if temps == 1:
                temp = random.randint(0, 2)
                if temp == 0:
                    out_date[i] = 'sin' + out_date[i]
                if temp == 1:
                    out_date[i] = 'cos' + out_date[i]
                if temp == 2:
                    out_date[i] = 'tan' + out_date[i]
                gpc = 2
    # 以下循环实现若一次遍历没有加三角函数操作符则随机位置加一个
    while gpc != 2:
        i = random.randint(0, len(out_date) - 1)
        if out_date[i].isdigit() or out_date[i] == '(' or out_date[i] == '√':
            temp = random.randint(0, 2)
            if temp == 0:
                out_date[i] = 'sin' + out_date[i]
            if temp == 1:
                out_date[i] = 'cos' + out_date[i]
            if temp == 2:
                out_date[i] = 'tan' + out_date[i]
        gpc = 2
    return out_date

  

三、优缺点分析:

   优点:

  1.代码简洁,尤其是在生成题目函数部分构思特别巧妙,先生成数字和加减乘除的简单组合也就是小学难度的题,之后检测如果难度不是小学,就随机生成根号和平方,再往下就检测难度如果是高中,就加入三角函数,这样就让代码特别的简洁高效

  2.注释简明扼要,不繁复冗长,代码也容易看懂

  3.生成题目那里也花了心思,生成的式子中能存在多个括号,同时括号的左右两边可以直接加上根号和平方项,为生成的题目增加了难度

 

   缺点:

  1.函数很少使用返回值,很多直接使用全局变量来传递参数,我觉得这是十分危险的做法,不仅在运行代码过程中容易出错,而且非常不适合代码重用

   2.封装性较低,没有很好的掌握面向对象的编程思想,面向过程的编程思想较重

   3.生成存放试卷的目录就是代码文件目录,生成时有些卡顿,而且没有提示的说

  4.小部分变量名使用中文缩写,如pg(平方根号),虽然让代码看起来简洁,但如果后期进入工程的话就可能会带来些许麻烦

 

四、体会与收获:

  这次的个人项目互评让之前没有过这种经历的我收获颇丰,我学到了队友巧妙的编程思想,尤其是生成题目那一块,想到了难度的层层递增这一特点,所以分层编程,让代码十分简洁明了,我一开始有近七百行代码,无从优化,也是由队友启发,最后修正到三百来行。分析原理,巧妙而又简洁的编程思想是之前面向过程编程经验带来的,同时也带来了封装性不够,模块化编程思想缺乏等问题,见贤思齐,见不贤而内自省,在之后的结对项目中,我们都需要取长补短,提高自己面向对象的编程能力,做好函数功能模块化,共同开发出高效,健壮,正确的代码项目。

posted @ 2021-09-27 20:50  所行不负年少  阅读(41)  评论(0)    收藏  举报