软件工程第一周作业

时间:2021-08-18 21:56:07

实现功能:

1.整数和真分数的四则运算, 运算数和运算结果都可以是整数或分数;

2.能生成任意个运算数的算式;

3.算式的个数、数的范围、运算数的个数由命令行输入;

4.保证生成的算式不重复;

5.支持括号。

 

实现思路:

1.新定义了表达式类,数据成员包含表达式的值,表达式的字符串形式,以及两个子表达式中间的算符。

   方法成员包括两个构造函数,其中一个随机生成算式并计算结果,另一个是默认的,用来分配空间;一个输出函数,用来打印算式;以及其他辅助函数。

   构造函数的思路:构造两个较短的子表达式,然后用随机的算符连接在一起。递归的边界是当表达式的长度为1或者2。

2.在运算数类中,数据成员包括分子和分母,此外新增了一个数据成员:运算数的字符串形式,

   新增了两个构造函数,其中一个用来随机生成运算数,另一个是默认的,用来分配空间。

3.在主类里调用表达式类的方法,来生成和输出算式;接受用户输入并判断正误。

 

结果截图:

 

软件工程第一周作业

 

程序代码:

GitHub地址:https://github.com/EverBlue1997/MyFirstRepository/tree/master/Week1v2.0

 

主类Week1:

import java.util.Scanner;

public class Week1 {
    
    public static void main(String[] args) {
        
        Scanner scan = new Scanner(System.in);
           
        int r = Integer.parseInt(args[0]);              //运算数的范围,由命令行输入
        int n = Integer.parseInt(args[1]);              //算式的数量,由命令行输入
        int l = Integer.parseInt(args[2]);              //运算数的个数,由命令行输入
        int count = 0;                                  //用户答对的题数
        
           expression e[];                                 //创建一个算式数组
           e = new expression[n];    
           int same = 0;                                   //重复标志
        
        for (int i = 0; i < n; i ++ ) {
            
            do {
                
                same = 0;
                e[i] = new expression (l, r);
                
                for (int j = 0; j < i; j ++) {          //判断与之前的算式是否重复
                    if ((e[j].exp).equals(e[i].exp))  {
                        same = 1;
                        break;
                    }
                }
                
            } while (same == 1);

            e[i].print();                                        //将算式打印到屏幕上
            
            if (scan.nextLine().equals (e[i].value.str))  {      //接受用户输入的答案并判断正误              
                System.out.println("回答正确!\n");
                count ++;
            }
            else  {
                System.out.println("回答错误! 正确答案是: " + e[i].value.str + "\n");
            }
            
        }
        
        //输出分数
        System.out.println("您答对了" + count + "道题目,得分:" + 100 * count / n + "!\n");
        
        scan.close();

}

}

运算数类number:

/*
 * 操作数类的定义
*/

public class number {
        
    int n;                     //分子
    int d;                     //分母
    String str;                //字符串形式
    
    /*
     * 操作数类的构造函数
     * 参数range为分子和分母的取值范围
     */
    public number (int range)    {
        
        d  =  (int) (Math.random() * range + 1.0);               //分子
        n  =  (int) (Math.random() * range + 1.0);               //分母

        if (d < n)  {                                            //如果分子大于分母,则当做整数处理
            d = 1;
        }
        
        yf();                                                    //约分
        
        str = new String();
        if (d == 1)    {                                         //生成这个数的字符串形式
            str += n;
        }
        else    {
            str += n + "/" + d;
        }

        
    }
    
    /*
     * 默认的构造函数
     */
    public number ()  {
        
        str = new String ();
        
    }
    
    /*求最大公约数*/
    public int GCD (int a, int b) {
        
        int gcd = 1;
        
        for (int i = 1; i <= a; i ++) {
            if (a % i == 0 && b % i == 0) {
                gcd = i;
            }
        }
        
        return gcd;
    }
    
    /*对分数进行约分*/
    public void yf () {
        
        int gcd = GCD (d, n);
        
        d /= gcd;
        n /= gcd;
        
    }

}

 

表达式类expression:

/*
 * 表达式类的定义
 */

public class expression {

    String  exp;         //表达式的字符串形式
    number  value;       //表达式的值
    char    op = ' ';    //两个子表达式中间的算符

    
    /*
     * 表达式类的构造函数
     * 参数length为表达式的长度, range为运算数的范围
     */
    public expression (int length, int range)  {
        
        exp = new String ();
        value = new number();
        
        char opr[] = {'+','-','*','/'};           //四则运算符
        
        if (length == 1)    {       //递归边界,表达式长度为1
            
            number num = new number (range);
            
            exp += num.str;
            
            value = num;
            
        }
        
        else if (length == 2)    {  //递归边界,表达式长度为2
            
            number n1 = new number (range);
            number n2 = new number (range);
            op = opr[(int) (Math.random() * 4)];
            
            exp += n1.str + " " + op + " " + n2.str;
            
            value = solve (n1, n2, op);
            
        }
        
        else    {                   //如果表达式的长度大于2,则要递归生成表达式
            
            int temp = (int) (Math.random() * (length-1)) + 1;         
            op = opr[(int) (Math.random() * 4)];
            
            //将表达式分解为两个子表达式,子表达式的长度随机生成
            expression e1 = new expression (temp, range);
            expression e2 = new expression (length - temp, range);
            
            //将子表达式拼接在一起            
            if (temp == 1                   //如果子表达式长度为1,或者长度为2且算符为乘除,则不用加括号
                    || (temp == 2 && (e1.op == '*' || e1.op == '/')))  {                
                exp += e1.exp;                
            }
            else  {
                exp += "(" + e1.exp + ")";
            }
            
            exp += " " + op + " ";
            
            if (length - temp == 1          //如果子表达式长度为1,或者长度为2且算符为乘除,则不用加括号
                    || (length - temp == 2 && (e2.op == '*' || e2.op == '/')))  {                
                exp += e2.exp;                
            }
            else  {
                exp += "(" + e2.exp + ")";
            }
            
            //计算结果
            value = solve (e1.value, e2.value, op);
            
        }
        
    }
    
    /*
     * 默认的构造函数
     */
    public expression ()  {
        
        exp = new String();
        value = new number();
        
    }
    
    /*输出表达式*/
    public void print ()  {
        
        System.out.println(exp + " = ");
        
    }
    
    /*求两运算数表达式的值*/
    public number solve (number x, number y, char op)  {
        
        number t1 = new number(), t2 = new number();
        int lcm = LCM (x.d, y.d);
        
        t1.n = x.n * lcm / x.d;            //将两数通分
        t2.n = y.n * lcm / y.d;
        t1.d = t2.d = lcm;

        switch (op) {                      //计算结果
        
            case '+':
                t1.n += t2.n;
                break;
                
            case '-':
                t1.n -= t2.n;
                break;
                
            case '*':
                t1.n = x.n * y.n;
                t1.d = x.d * y.d;
                break;
                
            case '/':
                t1.n = x.n * y.d;
                t1.d = x.d * y.n;
                break;
                
            default:
                break;
                
        }

        t1.yf();                 //将结果进行约分
        
        if (t1.d == 1)    {      //生成结果的字符串形式
            t1.str += t1.n;
        }
        else    {
            t1.str += t1.n + "/" + t1.d;
        }
        
        return t1;
        
    }
    
    /*求最小公倍数*/
    public int LCM (int a, int b) {
        
        return a * b / GCD(a,b);
        
    }
    
    /*求最大公约数*/
    public int GCD (int a, int b) {
        
        int gcd = 1;
        
        for (int i = 1; i <= a; i ++) {
            if (a % i == 0 && b % i == 0) {
                gcd = i;
            }
        }
        
        return gcd;
    }

    
}