软件工程 https://edu.cnblogs.com/campus/gdgy/InformationSecurity1912-Softwareengineering
作业要求 https://edu.cnblogs.com/campus/gdgy/InformationSecurity1912-Softwareengineering/homework/12147
作业目标 实现一个自动生成小学四则运算题目的程序,并且能够对题目和学生答题的答案进行比较,判断学生的答题情况
项目成员1 3119005484 殷威鸿
项目成员2 3119005465 李伟辰

代码连接

PSP表格

PSP各个阶段 预估时间(分钟) 实际的记录时间(分钟)
计划: 明确需求和其他因素,估计以下的各个任务需要多少时间 60 60
开发 (包括下面 8 项子任务) 1000 1200
需求分析 (包括学习新技术、新工具的时间) 60 180
生成设计文档 30 30
设计复审 20 30
代码规范 (为目前的开发制定或选择合适的规范) 30 30
具体设计 60 80
具体编码 640 730
代码复审 100 120
测试(自我测试,修改代码,提交修改) 60 60
报告 60 80
测试报告 20 20
计算工作量 10 10
事后总结, 并提出过程改进计划 40 30
合计 1190 1400

设计实现

  1. 项目中有Expression类用于实现生成四则运算表达式,Fraction类建一个分数结构体用于实现计算,tree类实现排除重复题目,IOLInk用于题目和答案的输出和用于读入题目和答案文件实现对于学生答题情况的判断。

  2. Expression中用infixExpression方法生成一个四则运算表达式。如何计算生成的表达式的结果,就要用到countansewer方法,但是由于计算是有优先级之分,所以要先把表达式转为后缀表达式,用到了栈实现,在suffixExprssion中。

  3. 对于题目答案的计算用了一个分数结构体,整数分母为1,这样就能实现对表达式进行运算,计算过程中对于除数0做了返回计算为负数的处理,当结果为负数是重新生成题目。

  4. 程序一次运行生成的题目不能重复,主要还是用tree类生成逆波兰的树,再对树遍历比较树是否相等,从而实现判重。

关键代码

Expression类中的题目生成:

public static String infixExpression(int range){

            String str1 = "";
       do {
            int num = 0;
            Random random = new Random();
            num = random.nextInt(3) + 2;
            if (num == 2) {
                String op = getoperator();
                String s1 = getrandommath(range);
                String s2 = getrandommath(range);
                str1 = " "+s1 + " " + op + " " + s2;
            } else if (num == 3) {
                String op1 = getoperator();
                String op2 = getoperator();
                String s1 = getrandommath(range);
                String s2 = getrandommath(range);
                String s3 = getrandommath(range);
                str1 = " "+s1 + " " + op1 + " " + s2 + " " + op2 + " " + s3;

            } else {//num==4加一个括号
                int i = random.nextInt(2);
                String op1 = getoperator();
                String op2 = getoperator();
                String s1 = getrandommath(range);
                String s2 = getrandommath(range);
                String s3 = getrandommath(range);
                if (i == 0) {
                    str1 = "("+" " + s1 + " " + op1 + " " + s2 + ")" + " " + op2 + " " + s3;
                } else {
                    str1 = s1 + " " + op1 + " " +"("+" "+ s2  + " " + op2 + " " + s3+" "+")";
                }

            }
        }while(countanswer(str1).contains("-"));//负数重新生成

       return str1 + " =" + " "+"、";
    }

Fraction中的计算

public class Fraction {
    int numerator = 0;//分子
    int denominator = 0;//分母
    public Fraction(int a ,int b){
        numerator = a;
        denominator = b;
    }
    //辗转相除,算最大公因子
    public static int getdiv(int x,int y){

        while(y!=0){
            int r= x%y;
            x = y;
            y = r;
        }
        return x;
    }
    // 乘法
    public static Fraction multiply(Fraction x, Fraction y)
    {    Fraction f = new Fraction (1,1);
        f.numerator = x.numerator*y.numerator;
        f.denominator =x.denominator*y.denominator;
        if(f.numerator!=0){
            int a=getdiv(f.numerator,f.denominator);
            f.numerator = f.numerator/a;
            f.denominator = f.denominator/a;
        }
        return f;
    }
    //除法
    public static Fraction divide(Fraction x, Fraction y)
    {   Fraction f = new Fraction(1, 1);
    //除数为0,返回一个负数
        if (y.numerator == 0) {
            f.numerator = -x.numerator ;
            f.denominator = 0*x.denominator;
            return f;
        } else {
            f.numerator = x.numerator * y.denominator;
            f.denominator = x.denominator * y.numerator;
            if (f.numerator != 0) {
                int a = getdiv(f.numerator, f.denominator);
                f.numerator = f.numerator / a;
                f.denominator = f.denominator / a;
            }
        }
        return f;
    }
    // 加法
    public static Fraction add(Fraction x, Fraction y)
    {
        Fraction f = new Fraction (1,1);
        f.numerator = x.numerator*y.denominator+y.numerator*x.denominator;
        f.denominator =x.denominator*y.denominator;
        if(f.numerator!=0){
            int a=getdiv(f.numerator,f.denominator);
            f.numerator = f.numerator/a;
            f.denominator = f.denominator/a;
        }
        return f;
    }
    // 减法
    public static Fraction  subtract(Fraction x, Fraction y) {
          Fraction f = new Fraction (1,1);
            f.numerator = x.numerator * y.denominator - y.numerator *                                   x.denominator;
            f.denominator = x.denominator * y.denominator;
            if (f.numerator != 0) {
                int a = getdiv(f.numerator, f.denominator);
                f.numerator = f.numerator / a;
                f.denominator = f.denominator / a;
            }
            return f;
        }

}

运行结果

1、生成题目

java -jar FourOperations.jar -n 10000 -r 10 生成10000道题,并且取值范围为[0,10)

题目:

答案

2、判断学生的答题情况

这里为了方便直接修改Answer.txt文件中的1、10、20、32、100、10000题的答案作为学生答题文件与题目对比

java -jar FourOperations.jar

-e C:\Users\MZ\Desktop\FourOperations\out\artifacts\FourOperations_jar\Exercises.txt

-a C:\Users\MZ\Desktop\FourOperations\out\artifacts\FourOperations_jar\Answers.txt

-e 题目文件路径 -a 文件文件路径

结果:

成功判断除了学生的答题情况

效能分析

类的内存消耗

全部性能

项目小结

殷威鸿:

​ 编程能力还是不足,很多过程都是搜索了很多资料才会写。程序中对于分数的处理让我焦头烂额,不过因为是结队作业所以写代码的效率还是比自己一个人高的。对于自己的编码能力确实还是需要提升。

李伟辰:

​ 编程能力比自己的结队伙伴还要不足,所以大部分都是队友完成,而我负责帮忙收索资料和帮忙改bug,然后跟着队友做,学习一下相关知识,能做的就帮忙做,努力继续提升自己的编程水平。

 posted on 2021-10-25 18:05  ywFong  阅读(119)  评论(0)    收藏  举报