结对作业:四则运算(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 + "\nA:" + 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小能手坤坤!

 

  • 张焜:

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

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

posted @ 2020-04-12 15:17  chenzhongming  阅读(424)  评论(2编辑  收藏  举报