zoukankan      html  css  js  c++  java
  • 结对作业:四则运算(Java+JavaFX)

    一、简介

    二、PSP表

    PSP2.1

    Personal Software Process Stages

    预估耗时(分钟)

    实际耗时(分钟)

    Planning

    计划

     180

     200

    · Estimate

    · 估计这个任务需要多少时间

     250

     300

    Development

    开发

     400

     500

    · Analysis

    · 需求分析 (包括学习新技术)

     60

     50

    · Design Spec

    · 生成设计文档

     30 

     40

    · Design Review

    · 设计复审 (和同事审核设计文档)

     10

     30

    · Coding Standard

    · 代码规范 (为目前的开发制定合适的规范)

     5

     10

    · Design

    · 具体设计

     60

     70

    · Coding

    · 具体编码

     200

     220

    · Code Review

    · 代码复审

     30

     50

    · Test

    · 测试(自我测试,修改代码,提交修改)

     20

     30

    Reporting

    报告

     50

     70

    · Test Report

    · 测试报告

    20 

     20

    · Size Measurement

    · 计算工作量

     30

     30

    · Postmortem & Process Improvement Plan

    · 事后总结, 并提出过程改进计划

    30

     40

    合计

     1375

     1660

    三、效能分析

    • 程序理耗时最长的题目生成,判断是否合法和去重以及计算

    四、设计实现过程

    • 1,项目说明

    自然数:0, 1, 2, …。

    • 真分数:1/2, 1/3, 2/3, 1/4, 1’1/2, …。
    • 运算符:+, −, ×, ÷。
    • 括号:(, )。
    • 等号:=。
    • 分隔符:空格(用于四则运算符和等号前后)。
    • 算术表达式:

    e = n | e1 + e2 | e1 − e2 | e1 × e2 | e1 ÷ e2 | (e),

    其中e, e1和e2为表达式,n为自然数或真分数。

    • 四则运算题目:e = ,其中e为算术表达式。
    • 2,基本需求

    1. 使用 -n 参数控制生成题目的个数,例如

    Myapp.exe -n 10  将生成10个题目。

    1. 使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围,例如

    Myapp.exe -r 10  将生成10以内(不包括10)的四则运算题目。该参数可以设置为1或其他自然数。该参数必须给定,否则程序报错并给出帮助信息。

    1. 生成的题目中计算过程不能产生负数,也就是说算术表达式中如果存在形如e1− e2的子表达式,那么e1≥ e2。
    2. 生成的题目中如果存在形如e1÷ e2的子表达式,那么其结果应是真分数。
    3. 每道题目中出现的运算符个数不超过3个。
    4. 程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。例如,23 + 45 = 和45 + 23 = 是重复的题目,6 × 8 = 和8 × 6 = 也是重复的题目。3+(2+1)和1+2+3这两个题目是重复的,由于+是左结合的,1+2+3等价于(1+2)+3,也就是3+(1+2),也就是3+(2+1)。但是1+2+3和3+2+1是不重复的两道题,因为1+2+3等价于(1+2)+3,而3+2+1等价于(3+2)+1,它们之间不能通过有限次交换变成同一个题目。

    生成的题目存入执行程序的当前目录下的Exercises.txt文件,格式如下:

    1. 四则运算题目1
    2. 四则运算题目2

    ……

    其中真分数在输入输出时采用如下格式,真分数五分之三表示为3/5,真分数二又八分之三表示为2’3/8。

    1. 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件,格式如下:
    1. 答案1
    2. 答案2

    特别的,真分数的运算如下例所示:1/6 + 1/8 = 7/24。

    1. 程序应能支持一万道题目的生成。
    2. 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,输入参数如下:

    Myapp.exe -e <exercisefile>.txt -a <answerfile>.txt

    统计结果输出到文件Grade.txt,格式如下:

    Correct: 5 (1, 3, 5, 7, 9)

    Wrong: 5 (2, 4, 6, 8, 10)

    其中“:”后面的数字5表示对/错的题目的数量,括号内的是对/错题目的编号。为简单起见,假设输入的题目都是按照顺序编号的符合规范的题目。

    • 设计思路

    1. 对于表达式的生成,大致的思路为:

    (1)      随机数决定运算符数量n,从而决定操作数的数量(n+1)

    (2)      将生成分为2n + 1步

    (3)      奇数步骤时:

    随机数决定是否生成括号

    随机数决定生成的操作数是整数还是分数

    (4)      偶数步骤时:

    随机数决定生成的运算符是什么符号

                  其中,每一步生成后,都用append方法进行直接拼接

      2.对于解决题目重复的问题:

    观察重复题目的一些主要特点:

    (1)      所用到的运算符完全相同(不含括号),只是出现的顺序不同

    (2)      所用到的操作数完全相同,只是出现的顺序不同

    (3)      答案相同

    由此得到:当同时满足上述三个条件可视为题目重复。

    开始的时候因为也难以解决同时判断三组数据的问题思考了很久,后来突然想到可以把运算符和操作数一起记录后进行排序,然后以其为key与答案一起存入HashMap中,便解决了这个难题。

    大致步骤为:

    (1)      在生成操作数和运算符的同时,将其加入到一个字符串S中

    (2)      表达式完全生成后,对字符串S进行排序

    (3)      判断Map中是否存在S的映射

    若存在,匹配是否存在相同的答案,若存在相同的答案,则视为重复,否则在值中添加答案A(形式为:“(A)”)

    若不存在,添加S 到(A)的映射

      3.对于计算过程

    (1)  采用前缀表达式,将表达式转为前缀表达式再用栈进行计算。

    (2)  将分式封装成Fraction类,并实现其加减乘除方法。

    (3)  在计算过程中存在分式则转成Fraction对象进行计算,否在采用简单整数运算

    • 流程图

    五、部分源代码

    • 分式实例类Fractio类
    package com.myapp.entity;
    
    /**
     * 带分数
     */
    public class Fraction {
        /**
         * 带分数的整数部分
         */
        private int integer;
    
        /**
         * 分子
         */
        private int molecule;
        /**
         * 分母
         */
        private int denominator;
    
        /**
         * @param integer     整数
         * @param molecule    分子
         * @param denominator 分母
         */
        public Fraction(int integer, int molecule, int denominator) {
            this.integer = integer;
            this.molecule = molecule;
            this.denominator = denominator;
        }
    
        /**
         * 加一个整数
         *
         * @param num
         */
        public void add(int num) {
            this.integer += num;
    
        }
    
        /**
         * 加一个分式
         *
         * @return
         */
        public void add(Fraction fraction) {
            this.integer += fraction.getInteger();
            if (this.denominator == fraction.getDenominator()) {
                this.molecule += fraction.getMolecule();
            } else {
                this.molecule = this.molecule * fraction.getDenominator() + fraction.getMolecule() * this.denominator;
                this.denominator *= fraction.getDenominator();
            }
        }
    
        /**
         * 减法一个整数
         * @param num
         */
        public boolean reduce(int num) {
            this.integer -= num;
            if (this.integer < 0) {
                return false;
            } else {
                return true;
            }
        }
    
        /**
         * 减一个分式
         *
         * @param fraction
         */
        public boolean reduce(Fraction fraction) {
            this.integer -= fraction.getInteger();
            if (this.denominator == fraction.getDenominator()) {
                this.molecule -= fraction.getMolecule();
            } else {
                this.molecule = this.molecule * fraction.getDenominator() - fraction.getMolecule() * this.denominator;
                this.denominator *= fraction.getDenominator();
            }
    
            //分子小于等于0
            while (this.molecule < 0) {
                this.molecule += this.denominator;
                this.integer--;
            }
            if (this.integer < 0) {
                return false;
            } else {
                return true;
            }
        }
    
    
    
        /**
         * 乘一个整数
         *
         * @param num
         */
        public void ride(int num) {
            if (this.integer != 0) {
                this.molecule += this.integer * this.denominator;
                this.integer = 0;
            }
            this.molecule *= num;
    
        }
    
        /**
         * 乘一个分式
         *
         * @param fraction
         */
        public void ride(Fraction fraction) {
            if (this.integer != 0) {
                this.molecule += this.integer * this.denominator;
                this.integer = 0;
            }
    
    //        if(fraction.getInteger() != 0) {
    //            fraction.setMolecule(fraction.getInteger() * fraction.getDenominator() +fraction.getMolecule());
    //            fraction.setInteger(0);
    //        }
    //        this.molecule *= fraction.molecule;
    
            //不改参数
            this.molecule *= fraction.getInteger() * fraction.getDenominator() +fraction.getMolecule();
    
            this.denominator *= fraction.getDenominator();
    
        }
    
        /**
         * 除以一个整数
         * @param num
         */
        public boolean divide(int num){
            if (num == 0) {
                return false;
            }
            this.molecule += this.integer * this.denominator;
            this.integer = 0;
            this.denominator *= num;
            return true;
        }
    
        /**
         * 除以一个分式
         * @param fraction
         */
        public boolean divide(Fraction fraction){
            if (fraction.getVaule() == 0) {
                return false;
            }
            if (this.integer != 0) {
                this.molecule += this.integer * this.denominator;
                this.integer = 0;
            }
            if(fraction.getInteger() != 0) {
                this.denominator *= fraction.getInteger() * fraction.getDenominator() +fraction.getMolecule();
            }else {
                this.denominator *= fraction.getMolecule();
            }
            this.molecule *= fraction.getDenominator();
            return true;
        }
    
        /**
         * 求两数最大公约数
         *
         * @param a
         * @param b
         * @return
         */
        private static int getCommonDivisor(int a, int b) {
            if (b == 0) {
                return a;
            } else {
                int remainder = a % b;
                a = b;
                b = remainder;
                return getCommonDivisor(a, b);
            }
        }
    
        /**
         * 化简
         */
        public void simplification(){
            //化简
            if (this.molecule > this.denominator) {
                this.integer += this.molecule / this.denominator;
                this.molecule = this.molecule % this.denominator;
            }
            //约分
            int commonDivisor = getCommonDivisor(this.denominator, this.molecule);
            this.denominator /= commonDivisor;
            this.molecule /= commonDivisor;
        }
    
        @Override
        public String toString() {
            simplification();
            if (this.molecule == 0){
                //分子为0
                return this.integer+"";
            } else if (denominator == 1) {
                //分母为1
                return (this.integer + this.molecule) + "";
            } else if (this.integer != 0) {
                return this.integer + "'" + this.molecule + "/" + denominator;
            } else {
                return this.molecule + "/" + denominator;
            }
        }
    
        /**
         * 返回小数数值
         *
         * @return
         */
        public double getVaule() {
            return this.integer + 1.0 * this.molecule / this.denominator;
        }
    
        public int getInteger() {
            return integer;
        }
    
        public void setInteger(int integer) {
            this.integer = integer;
        }
    
        public int getMolecule() {
            return molecule;
        }
    
        public void setMolecule(int molecule) {
            this.molecule = molecule;
        }
    
        public int getDenominator() {
            return denominator;
        }
    
        public void setDenominator(int denominator) {
            this.denominator = denominator;
        }
    
    
    }
    • 题目成类
    package com.myapp.production;
    
    import com.myapp.entity.Fraction;
    import com.myapp.util.CalculateUtil;
    import com.sun.org.apache.bcel.internal.generic.ALOAD;
    
    import java.util.*;
    
    public class CreateQuestion {
    
        //控制题目个数,默认为10
        private int n = 10;
        //控制题目中的数值
        private int r = -1;
        //用于判断重复题目
        private Map<ArrayList<String>, String> judge = new IdentityHashMap<>();
    
        public CreateQuestion() {
    
        }
        public CreateQuestion(int n, int r) {
            this.n = n;
            this.r = r;
        }
    
        public void setN(int n) {
            this.n = n;
        }
    
        public void setR(int r) {
            this.r = r;
        }
    
        public Map<String, String> CreateQuestions(){
            Map<String, String> questions = new HashMap<>();
            int totalNum = n;
            while(n > 0) {
                String question = this.createArithmeticExpression();
                if (question.equals("Error")) continue;
                String answer = CalculateUtil.Calculate(question);
    //            System.out.println(n+"Q:" + question + "
    A:" + answer);
                questions.put(question, answer);
                n--;
                if (n == 0) {
                    n = totalNum - questions.keySet().size();
                }
            }
    
            return questions;
        }
    
        public String createArithmeticExpression(){
            /**
             * @param question 题目
             * @param opQuantity 运算符数
             * @param step 步骤数
             * @param parenthesisPosition 左括号的位置
             * @param division 除号的位置
             * @param leftParenthesis 左括号数
             * @param rightParenthesis 右括号数
             * @param adjacent 左括号是否相邻
             * @param judge 用于同时储存题目用到的数字和题目用到的运算符(不含括号,下同)
             * @param numAL 储存题目用到的数字
             * @param opAL 储存题目用到的运算符
             * @param re 用于同时储存题目用到的数字和题目用到的运算符以及题目的答案
             * @param ans 题目的答案
             */
            if (r == -1) {
                System.out.println("请先使用"-r"设置参数r以控制题目中的数值范围.");
                return "Error";
            }
            if (r <= 1){
                System.out.println("参数r不能小于2.");
                return "Error";
            }
    
            StringBuffer question = new StringBuffer();
            Random random = new Random();
    
            //随机决定运算符的个数(1-3个)
            int opQuantity = random.nextInt(3) + 1;
            //根据运算符个数决定操作步数
            int step = 2*opQuantity + 1;
    
            //决定括号总数
            int leftParenthesis = random.nextInt(opQuantity);
            int rightParenthesis = 0;
    
            int parenthesisPosition = 0;
            int division = 0;
            boolean adjacent = false;
    
            ArrayList<String> numOp = new ArrayList<>();
    
            //当前步数
            int i = 1;
            while (i <= step){
                //单数步骤时生成数字
                if (i%2 == 1){
                    //是否生成括号
                    switch (leftParenthesis){
                        case 0: break;
                        case 1: {
                            if (i == step - 2) {
                                question.append("( ");
                                parenthesisPosition = i;
                                leftParenthesis--;
                                rightParenthesis++;
                            }
                            else {
                                switch (random.nextInt(2)){
                                    case 0: break;
                                    case 1: {
                                        question.append("( ");
                                        parenthesisPosition = i;
                                        leftParenthesis--;
                                        rightParenthesis++;
                                    }
                                }
                            }
                        }break;
                        case 2:{
                            if (i == 3){
                                switch (random.nextInt(2)){
                                    case 0: {
                                        question.append("( ");
                                        leftParenthesis--;
                                        rightParenthesis++;
                                    }break;
                                    case 1: {
                                        question.append("( ( ");
                                        leftParenthesis -= 2;
                                        rightParenthesis += 2;
                                        adjacent = true;
                                    }
                                }
                                parenthesisPosition = i;
                            }
                            if (i == 1){
                                switch (random.nextInt(3)){
                                    case 0: break;
                                    case 1: {
                                        question.append("( ");
                                        leftParenthesis--;
                                        rightParenthesis++;
                                        parenthesisPosition = i;
                                    }break;
                                    case 2: {
                                        question.append("( ( ");
                                        leftParenthesis -= 2;
                                        rightParenthesis += 2;
                                        adjacent = true;
                                        parenthesisPosition = i;
                                    }
                                }
                            }
                        }
                    }
    
                    //生成数字
                    switch ((random.nextInt(2))){
                        //生成整数
                        case 0: {
                            //除数不能为0
                            if (i - 1 == division) {
                                int integer = random.nextInt(r) + 1;
    
                                Fraction num = new Fraction(0, integer, 1);
                                numOp.add(num.toString());
    
                                question.append(integer);
                            }
                            else {
                                int integer = random.nextInt(r+1);
    
                                Fraction num = new Fraction(0, integer, 1);
                                numOp.add(num.toString());
    
                                question.append(integer);
                            }
                        }break;
                        //生成分数
                        case 1: {
                            /**
                             * @param integer 整数
                             * @param molecule 分子
                             * @param denominator 分母
                             *
                             */
                            int integer = random.nextInt(r);
                            int molecule;
                            int denominator = random.nextInt(r - 1) + 2;
                            //分子小于分母
                            molecule = random.nextInt(denominator - 1) + 1;
    
                            Fraction num = new Fraction(integer, molecule, denominator);
                            numOp.add(num.toString());
    
                            if (integer != 0){
                                question.append(integer).append("'");
                            }
    
    
    
                            question.append(molecule).append("/").append(denominator);
                        }
                    }
    
                    //生成右括号
                    if (rightParenthesis != 0 && parenthesisPosition != i){
                        if (question.indexOf("(") == 0 && rightParenthesis == 1 && i == step -2){
                            question.append(" )");
                            rightParenthesis--;
                        }
                        switch (rightParenthesis){
                            case 1: {
                                if (i == step) question.append(" )");
                                else {
                                    switch (random.nextInt(2)){
                                        case 0: break;
                                        case 1: {
                                            question.append(" )");
                                            rightParenthesis--;
                                        }
                                    }
                                }
                            }break;
                            case 2: {
                                if (adjacent){
                                    question.append(" )");
                                    rightParenthesis--;
                                }
                                else {
                                    question.append(" ) )");
                                    rightParenthesis -= 2;
                                }
                            }
                        }
                    }
                }
                //偶数步骤时生成运算符
                else {
                    String op = "";
                    switch (random.nextInt(4)){
                        case 0: {
                            op = "+";
                            question.append(" + ");
                        }break;
                        case 1: {
                            op = "-";
                            question.append(" - ");
                        }break;
                        case 2: {
                            op = "×";
                            question.append(" × ");
                        }break;
                        case 3: {
                            op = "÷";
                            question.append(" ÷ ");
                            division = i;
                        }
                    }
                    numOp.add(op);
                }
                i++;
            }
    
            //若答案计算过程中出现负数或除零错误,则题目生成错误
            String ans = CalculateUtil.Calculate(question.toString());
            if (ans == null) return "Error";
    
            //将用到的数字和运算符重写排序
            sort(numOp);
    
            //若用到的数字、运算符相同,题目的答案也相同,则视为重复的题目
            if (judge.containsKey(numOp) && judge.get(numOp).equals(ans)) return "Error";
            else {
                judge.put(numOp, ans);
                return question.toString();
            }
        }
    
        //重写方法,使其排序并能保留重复项
        public static void sort(List<String> list) {
            TreeSet<String>  ts = new TreeSet<>(new Comparator<String>() {
    
                @Override
                public int compare(String s1, String s2) {
                    int num = s1.compareTo(s2);
                    return num==0?1:num;
                }
    
            });
    
            ts.addAll(list);
            list.clear();
            list.addAll(ts);
        }
    }
    • 计算工具类
    package com.myapp.util;
    
    import com.myapp.entity.Fraction;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Stack;
    
    /**
     * 计算工具类
     */
    public class CalculateUtil {
    
        /***
         *    获得前缀表达式
         * @param exp
         * @return
         */
        public static List<String> getExpression(String exp) {
    //        String exp = "1 + ( ( 2 + 3 ) × 4 ) - 5";
            Stack<String> charStack = new Stack<>();
            Stack<String> expression = new Stack<>();
            String[] split = exp.trim().split("\s+");
            int leng = split.length;
            for (int i = leng - 1; i >= 0; i--) {
    
                // 符号
                if (split[i].matches("[+|\-|×|÷|)]")) {
                    while (true) {
                        //如果栈为空或栈顶为")"或者运算符为×÷)
                        if (charStack.empty() || ")".equals(charStack.peek()) || "×".equals(split[i]) || "÷".equals(split[i]) || ")".equals(split[i])) {
                            charStack.push(split[i]);
                            break;
                            //运算符与栈顶同时为+或-
                        } else if (split[i].matches("[+|\-]") && charStack.peek().matches("[+|\-]")) {
                            charStack.push(split[i]);
                            break;
                        } else {
                            expression.push(charStack.pop());
                        }
                    }
                } else if ("(".equals(split[i])) {
                    while (true) {
                        if (charStack.peek().equals(")")) {
                            charStack.pop();
                            break;
                        }
                        expression.push(charStack.pop());
                    }
                } else {
                    expression.push(split[i]);
                }
    
    //            System.out.println(split[i]);
    
            }
            while (!charStack.empty()) {
                expression.push(charStack.pop());
            }
            List<String> expList = new ArrayList<>(expression.size());
            while (!expression.empty()){
                expList.add(expression.pop());
            }
            return expList;
        }
    
        /***
         * 计算前缀表达式
         * @param exp
         * @return
         */
        public static String Calculate(String exp) {
            List<String> expression = getExpression(exp);
            String num ;
            if (exp.indexOf('÷') > 0 || exp.indexOf('/') > 0) {
                Stack<Fraction> numStack = new Stack<>();
                Fraction fraction = null;
                for (int i = expression.size() - 1; i >= 0; i--) {
                    num = expression.get(i);
                    switch (num) {
                        case "+":
                            fraction = numStack.pop();
                            fraction.add(numStack.pop());
                            numStack.push(fraction);
                            break;
                        case "-":
                            fraction = numStack.pop();
                            fraction.reduce(numStack.pop());
                            numStack.push(fraction);
                            //出现负值直接返回空
                            if (numStack.peek().getVaule() < 0){
                                return null;
                            }
                            break;
                        case "×":
                            fraction = numStack.pop();
                            fraction.ride(numStack.pop());
                            numStack.push(fraction);
                            break;
                        case "÷":
                            fraction = numStack.pop();
                            if (!fraction.divide(numStack.pop())){
                                //除数为0
                                return null;
                            }
                            numStack.push(fraction);
                            break;
                        default:
                            numStack.push(TransformUtil.expToFraction(num));
                    }
    
                }
                return numStack.pop().toString();
            } else {
                Stack<Integer> numStack = new Stack<>();
                for (int i = expression.size() - 1; i >= 0; i--) {
                    num = expression.get(i);
                    switch (num) {
                        case "+":
                            numStack.push(numStack.pop() + numStack.pop());
                            break;
                        case "-":
                            numStack.push(numStack.pop() - numStack.pop());
                            //出现负值直接返回空
                            if (numStack.peek() < 0){
                                return null;
                            }
                            break;
                        case "×":
                            numStack.push(numStack.pop() * numStack.pop());
                            break;
                        default:
                            numStack.push(Integer.parseInt(num));
                    }
    
                }
                return numStack.pop().toString();
            }
        }
        public static void main(String[] args) {
    
    //        String exp = "( 3 + 1'7/8 ) × ( 1/2 )";
    //        String exp2 = "3 × 1 + ( ( 2 + 3 ) × 4 ) - 5";
            String exp = "2 ÷ ( 1/2 - 1/2 )";
            System.out.println(Calculate(exp));
    //        System.out.println(Calculate(exp2));
        }
    
    
    }
    • Main类
    package com.myapp;
    
    import com.myapp.production.CreateQuestion;
    import com.myapp.util.CalculateUtil;
    import com.myapp.util.FileUtil;
    import com.myapp.view.Gui;
    import javafx.application.Application;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Main {
        public static String QUESTION_FILE_NAME = "exercises.txt";
        public static String ANSWER_FILE_NAME = "answer.txt";
        public static void main(String[] args) {
            long start = System.currentTimeMillis();
            switch (args.length) {
                case 0:
                    System.out.println("请输入参数!");
                    return;
                case 1:
                    if ("-x".equals(args[0])) {
                        Application.launch(Gui.class);
                    }
                    break;
                case 2:
                    switch (args[0]) {
                        case "-n":
                            System.out.println("必须使用"-r"设置参数r以控制题目中的数值范围.");
                            break;
                        case "-r":
                            //题目中数值(自然数、真分数和真分数分母)的范围
                            //指定题目数目
                            CreateQuestion createQuestionR = new CreateQuestion();
                            createQuestionR.setR(Integer.parseInt(args[1]));
                            FileUtil.writeQuestion(createQuestionR.CreateQuestions(), QUESTION_FILE_NAME, ANSWER_FILE_NAME);
                            break;
                        case "-s":
                            //指定题目文件计算出答案文件
                            creatAnswerFile(args[1]);
                            break;
                        default:
                            System.out.println("请输入正确参数");
                    }
                    break;
                case 4:
                    if ("-e".equals(args[0]) && "-a".equals(args[2])) {
                        List[] result = exercisesCheck(args[1], args[3]);
                        if (result != null) {
                            System.out.println("Correct: " + result[0].size() + result[0]);
                            System.out.println("Wrong: " + result[1].size() + result[1]);
                        }
                    } else if ("-n".equals(args[0]) && "-r".equals(args[2])) {
                        FileUtil.writeQuestion(new CreateQuestion(Integer.parseInt(args[1]), Integer.parseInt(args[3])).CreateQuestions(),
                                QUESTION_FILE_NAME, ANSWER_FILE_NAME);
                    } else if ("-r".equals(args[0]) && "-n".equals(args[2])) {
                        FileUtil.writeQuestion(new CreateQuestion(Integer.parseInt(args[3]), Integer.parseInt(args[1])).CreateQuestions(),
                                QUESTION_FILE_NAME, ANSWER_FILE_NAME);
                    } else {
                        System.out.println("请输入正确参数");
                    }
                    break;
                default:
                    System.out.println("请输入正确参数");
            }
            System.out.println("耗时" + (System.currentTimeMillis() - start) + "毫秒");
    
        }
    
        /**
         * 检验答案
         *
         * @param questionFile
         * @param answerFile
         */
        public static List<Integer>[] exercisesCheck(String questionFile, String answerFile) {
            List<Integer> Correct = new ArrayList<>();
            List<Integer> Wrong = new ArrayList<>();
            List<String>[] exercises = FileUtil.readQuestion(questionFile, answerFile);
    
            if (exercises == null) {
                return null;
            }
            //题目
            String answerString;
            //答案
            String expression;
            //题目序号
            int i = 1;
            //两文件数目不对应时取最短数目文件为标准
            int length = exercises[0].size() < exercises[1].size() ? exercises[0].size() : exercises[1].size();
            for (int index = 0; index < length; index++) {
                //获取对应答案
                expression = exercises[0].get(index);
                answerString = exercises[1].get(index);
    //            System.out.println(CalculateUtil.Calculate(expression));
                if (answerString.equals(CalculateUtil.Calculate(expression))) {
                    Correct.add(i++);
                } else {
                    Wrong.add(i++);
                }
            }
            List[] result = new List[2];
            result[0] = Correct;
            result[1] = Wrong;
            return result;
        }
    
        /**
         * 根据题目文件生成答案
         *
         * @param fileName
         */
        public static void creatAnswerFile(String fileName) {
            List<String> questions = FileUtil.readFile(fileName);
            if (questions == null) {
                return;
            }
            List<String> answers = new ArrayList<>(questions.size());
            String answer;
            for (String question : questions) {
                answer = CalculateUtil.Calculate(question);
                if (answer == null) {
                    answers.add("计算过程出现负数");
                } else {
                    answers.add(answer);
                }
            }
            FileUtil.writeFile(answers, fileName.replaceFirst("\.txt", "【答案】.txt"));
        }
    
    
    }

    六、测试图

    • 命令行测试

     

     

    • 可视化图形界面

     

    • 当前目录文件

     

    七、项目小结

    • 陈忠明:

    知识上学习了前缀表达式的生成及计算,学会用JavaFx实现简单图形界面。

    经过本次合作,了解到团队合作讨论交流的重要性,有更多的想法思路碰撞融合产生更好的思路,不同人有不同的编码风格,合作前需先确定编码规范,张焜在项目讨论中有许多独特想法,在一开始讨论就对生成算法有了思路实 在tql,在合作过程中也能及时找出我的bug并提出优化建议。合作使我们的代码质量得到提高。

    感谢我的搭档张焜的耐心交流以及其丰富的想法,致想法小天才,找bug小能手坤坤!

     

    • 张焜:

    经过本次结对项目,我深刻地体会到了需求分析时,一个人自己想和多个人一起讨论的效率的差距有多大,一个人思考往往会因为疏忽而产生的遗漏,但多个人一起讨论,就容易在别人的想法中找出自己所没有考虑到的东西,也就能更加精确地达成目的。测试的过程中遇到问题,也要及时向对方请教、反馈,否则容易出现更多的问题。

    忠明大佬思考比较全面,往往能提出一些我所考虑不到的点,效率之高令也我钦佩不已,也会在我不太明白的时候进行适当地指导,这里非常感谢忠明哥!

  • 相关阅读:
    Memory Limit Exceeded
    浙江省程序设计竞赛2019
    hdu3974 Assign the task
    TCP面向字节流和UDP面向报文的区别
    django-admin和django-admin.py的区别
    利用 pip 安装 Python 程序包到个人用户文件夹下
    PyCharm中目录directory与包package的区别及相关import详解
    分布式表示(Distributed Representation)
    Nginx
    32.最长有效括号
  • 原文地址:https://www.cnblogs.com/chzhm/p/12684811.html
Copyright © 2011-2022 走看看