个人作业1——四则运算题目生成程序(基于控制台)

码云地址:https://git.oschina.net/lzx84/szys

题目:

从《构建之法》第一章的 “程序” 例子出发,像阿超那样,花二十分钟写一个能自动生成小学四则运算题目的命令行 “软件”。

满足以下需求:

    1. 除了整数以外,还要支持真分数的四则运算,真分数的运算,例如:1/6 + 1/8 = 7/24
    2. 运算符为 +, −, ×, ÷
    3. 并且要求能处理用户的输入,并判断对错,打分统计正确率。
    4. 要求能处理用户输入的真分数, 如 1/2, 5/12 等
    5. 使用 -n 参数控制生成题目的个数,例如执行下面命令将生成10个题目
      Myapp.exe -n 10

需求分析:

  • 需要处理分数,包括化简分数、识别整数等。并考虑特殊情况,如分数分母不为0等。考虑到题目要求小学水平,则分子分母数值不超过100。
  • 需要编写分数四则运算的算法,并考虑特殊情况,如减法结果不能为负数,除法中除数不能为0等。
  • 需统计用户正确的题目数,与总题目数。
  • 需要实现字符串的识别与比较。

功能实现:

  • 基本功能:能随机生成若干四则运算式,并检测用户答案,统计正确率。
  • 扩展功能:实现多项运算、统计做题时长、避免重复题型、控制题目难度等(未实现)
  • 高级功能:实现错题统计功能、实现多用户竞赛功能、实现更复杂的运算等(未实现)

设计实现:

    Fraction类:

    Calculate类:

    Dofrac类:

代码说明:

  Fraction类:

public class Fraction {

    private int fenzi;
    private int fenmu;

    public Fraction() {
        super();
    }

    public Fraction(int fenzi, int fenmu) {
        super();
        this.fenzi = fenzi;
        this.fenmu = fenmu;
        this.simplify(fenzi, fenmu); //在构造函数中直接化简分数(感觉此方法欠妥)
    }



    public void simplify(int fenzi, int fenmu) { 
        int GCD = Dofrac.GCD(fenzi, fenmu);
        this.fenzi = fenzi / GCD;
        this.fenmu = fenmu / GCD;
    }//化简分数

    @Override
    public String toString() {
        if (fenzi == 0) {
            return 0 + "";
        } else if (fenzi % fenmu == 0) {
            return fenzi / fenmu + "";
        } else
            return fenzi + "/" + fenmu;
    }//改写toString,输出为分数形式

    public int getFenzi() {
        return fenzi;
    }

    public void setFenzi(int fenzi) {
        this.fenzi = fenzi;
    }

    public int getFenmu() {
        return fenmu;
    }

    public void setFenmu(int fenmu) {
        this.fenmu = fenmu;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + fenmu;
        result = prime * result + fenzi;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Fraction other = (Fraction) obj;
        if (fenmu != other.fenmu)
            return false;
        if (fenzi != other.fenzi)
            return false;
        return true;
    }

}

Calculate类:

public class Calculate {
    public static Fraction add(Fraction f1, Fraction f2) {

        int fz1 = f1.getFenzi();
        int fz2 = f2.getFenzi();
        int fm1 = f1.getFenmu();
        int fm2 = f2.getFenmu();
        Fraction f = new Fraction(fz1 * fm2 + fm1 * fz2, fm1 * fm2);
        return f;

    }//加法运算

    public static Fraction sub(Fraction f1, Fraction f2) {
        int fz1 = f1.getFenzi();
        int fz2 = f2.getFenzi();
        int fm1 = f1.getFenmu();
        int fm2 = f2.getFenmu();
        Fraction f = new Fraction(fz1 * fm2 - fm1 * fz2, fm1 * fm2);
        return f;
    }//减法运算

    public static Fraction mul(Fraction f1, Fraction f2) {
        int fz1 = f1.getFenzi();
        int fz2 = f2.getFenzi();
        int fm1 = f1.getFenmu();
        int fm2 = f2.getFenmu();
        Fraction f = new Fraction(fz1 * fz2, fm1 * fm2);
        return f;
    }//乘法运算

    public static Fraction div(Fraction f1, Fraction f2) {
        int fz1 = f1.getFenzi();
        int fz2 = f2.getFenzi();
        int fm1 = f1.getFenmu();
        int fm2 = f2.getFenmu();
        Fraction f = new Fraction(fz1 * fm2, fm1 * fz2);
        return f;
    }//除法运算

    public static boolean compare(Fraction f1, Fraction f2) {
        int fz1 = f1.getFenzi();
        int fz2 = f2.getFenzi();
        int fm1 = f1.getFenmu();
        int fm2 = f2.getFenmu();
        if (fz1 * fm2 >= fz2 * fm1) {
            return true;
        } else{

return false;

}

}//比较两分数的大小 }

Dofrac类:

public class Dofrac {

    public static Fraction CreatFrac() {
        int fz, fm,co;
co=(int)(Math.random()*2);//co取[0,1]得随机值,分别代表分数和整数

          if(co==0){

              fm = (int) (2 + Math.random() * (100 - 2 + 1));//分母为2-100的随机数
              fz =(int) (0 + Math.random() * (fm - 0 + 1));//分子为 0--fm 的随机数(确保真分数)
          }else {
              fm=1;
              fz=(int) (0 + Math.random() * (100 - 0 + 1));
          }


        Fraction frac = new Fraction(fz, fm);
        return frac;
    }//创建随机分数

    public static boolean check(String input) {
        if (input.matches("[0-9]+")||input.matches("[0-9]+/[0-9]+")) {
            return true;
        } else
            {
            return false;
        }
    }//利用正则表达式处理用户输入的答案
public static int GCD(int m, int n) { while (true) { if ((m = m % n) == 0) return n; if ((n = n % m) == 0) return m; } }//计算最大公约数
public static Fraction MakeFor(Fraction f1, Fraction f2, int op, int i) { Fraction result = new Fraction(); switch (op) { case 1: { result = Calculate.add(f1, f2); System.out.println("第" + i + "题:" + f1.toString() + "+" + f2.toString()); break; } case 2: { if (!Calculate.compare(f1, f2)) { Fraction temp = f1; f1 = f2; f2 = temp; }//比较两分数的大小,若减数小于被减数,则将两个数交换 result = Calculate.sub(f1, f2); System.out.println("第" + i + "题:" + f1.toString() + "-" + f2.toString()); break; } case 3: { result = Calculate.mul(f1, f2); System.out.println("第" + i + "题:" + f1.toString() + "*" + f2.toString()); break; } case 4: { if (f2.getFenzi() == 0) { f2.setFenzi((int) (1 + Math.random() * (10 - 1 + 1))); }//若除数分子为0,则分子重新取一个1——100的随机数 result = Calculate.div(f1, f2); System.out.println("第" + i + "题:" + f1.toString() + "÷" + f2.toString()); break; } } return result; } }

Generator类(执行类)

public class Generator {

    public static void main(String[] args) {
        try {
            int op = 0;
            String input;
            int flag = 0;//用于检测用户答对的题目数
            Scanner sc = new Scanner(System.in);
            System.out.println("【四则运算题目生成器】");
            System.out.println("请输入需要的题目数量:");
            int n = sc.nextInt();
            for (int i = 1; i <= n; i++) {
                Fraction f1 = Dofrac.CreatFrac();
                Fraction f2 = Dofrac.CreatFrac();
                op = (int) (Math.random() * 4 + 1);
                Fraction result = Dofrac.MakeFor(f1, f2, op, i);
                input = sc.next();
                while (!Dofrac.check(input)) {
                    System.out.println("输入有误,请重新输入:");
                    input = sc.next();
                }

                if (input.equals(result.toString())) {
                    System.out.println("回答正确");
                    System.out.println("---------------------------------------------");
                    flag++;
                } else {
                    System.out.println("回答错误,正确答案是:" + result.toString());
                    System.out.println("---------------------------------------------");
                }

            }
            System.out.println("---------------------------------------------");
            System.out.println("答题完毕,你的正确率为" + 100 * flag / n + "%");
            sc.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

 测试运行:

 

PSP表:

PSP2.1 Personal Software Process Stages Time (%) Senior Student Time (%)
Planning 计划 5min 30min
· Estimate 估计这个任务需要多少时间 8min 10min
Development 开发 2h 1h30min
· Analysis 需求分析 (包括学习新技术) 10min 8min
· Design Spec 生成设计文档 0 0
· Design Review 设计复审 3min 1min
· Coding Standard 代码规范 0 0
· Design 具体设计 1h 30min
· Coding 具体编码 1h 40min
· Code Review 代码复审 0 0
· Test 测试(自我测试,修改代码,提交修改) 5min 8min
Reporting 报告 30min 40min
· 测试报告 0 0
· 计算工作量 0 0
· 并提出过程改进计划 0 0

总结:

         此次作业整体难度不大,但是刚开始看到题目构思的时候,却一度陷入僵局。也许是因为太久没有编程,很多知识都忘记了,导致刚开始的时候不懂从何下手。在思考了很久,复习了很多以前的知识后,大体上有了思路,但也不是很清晰,想到什么写什么,迷迷糊糊就完成了。中间遇到的BUG也不是很多,但是调试花了很多时间,感觉这是自己编程思想不够系统,对软件的应用也不是很熟悉造成的,根本原因还是在于练习不够,经验不足。希望以后多加练习,可以更加进步。最后感谢老师们和助教的辛勤付出,你们辛苦了!

原文地址:https://www.cnblogs.com/lzx84/p/6514048.html