现代软件工程_第一周练习_第1题_更新版

主要完成功能:在用户指定最多的运算符个数后,该程序能够随机生成在指定个数以内的四册运算式(包括+,-,*,/,(,),真分数等),在用户输入答案后,程序能够计算随机生成的运算式得到结果,然后与用户输入的结果进行比对,并判断对错与记录用户得分。

界面与运行结果为(在出题时真分数用“()”括起来):

该项目文件的结构如图:

其中Calculation.java的代码为:

 1 package ljf;
 2 
 3 public class Calculation {
 4     //判断是否为数字
 5     public static boolean isNumber(char ch){
 6         switch (ch) {
 7         case '+':return false;
 8         case '-':return false;
 9         case '*':return false;
10         case '/':return false;
11         default:
12             return true;
13         }
14     }
15     
16     public static Fraction cal(String str){
17         Stack<Fraction> stack=new Stack<Fraction>(20);
18         FractionCalculation fc=new FractionCalculation();
19         String[] array=MidToPosT.Change(str);
20         int i=0;
21         Fraction fa,fb;
22         char op;
23         while(!array[i].equals("#")){
24             //是数字
25             if(isNumber(array[i].charAt(0))){
26                 //化成分数进栈
27                 stack.push(new Fraction(Integer.parseInt(array[i++]), 1));
28             }else{
29                 fb=stack.pop();
30                 fa=stack.pop();
31                 op=array[i++].charAt(0);
32                 fa=fc.fraccalculate(fa, op, fb);
33                 stack.push(fa);
34             }
35         }
36         fa=stack.getTop();
37         return fa;
38     }
39 }

其中Fraction.java的代码为:

 1 package ljf;
 2 
 3 public class Fraction {
 4       public int numerator;
 5       public int denominator;
 6       public Fraction(int numerator, int denominator){
 7         this.numerator=numerator;
 8         this.denominator=denominator;
 9       }
10       public double getRet(){
11         return (double)numerator/denominator;
12       }
13       public String toString(){
14         return numerator+"/"+denominator;
15       }
16       public int getint(){
17           return numerator;
18       }
19 }

其中FractionCalculation.java的代码为:

  1 package ljf;
  2 
  3 import java.util.Scanner;
  4 import java.math.*; 
  5 
  6 public class FractionCalculation {
  7     public char operate(){
  8         int i;
  9         char op = ' ';
 10         i=(int)(Math.random()*100)%4+1;
 11         switch(i){
 12         case 1:op='+';break;
 13         case 2:op='-';break;
 14         case 3:op='*';break;
 15         case 4:op='/';
 16         }
 17         return op;    
 18     }
 19      
 20     public int num(){
 21         int i;
 22         i=(int)(Math.random()*100);
 23         return i;
 24     }
 25     
 26     public void intmatch(){//整数出题
 27         int a=this.num();
 28         int b=this.num();
 29         char op=this.operate();
 30         //int answer;
 31         String myanswer;
 32         System.out.print("请做题:"+a+op+b+"=");
 33         String answer1=this.intcalculate(a, op, b);
 34         //System.out.print(answer1);
 35         Scanner in= new Scanner(System.in); 
 36         myanswer=in.next();
 37         if(myanswer.equals(answer1)){
 38             System.out.println("恭喜,答案正确。");
 39         }
 40         else{
 41             System.out.println("很抱歉,答案错误。正确答案为:"+answer1);
 42         }
 43     }
 44     
 45     public String intcalculate(int a,char op,int b){//整数之间的计算方法
 46         if(op=='+')
 47             return (a+b)+"";
 48         else if(op=='-')
 49             return (a-b)+"";
 50         else if(op=='*')
 51             return (a*b)+"";
 52         else{
 53             int max=this.maxyueshu(a, b);
 54             a=a/max;
 55             b=b/max;
 56             if(b==1){
 57                 return a+"";
 58             }
 59             else{
 60                 Fraction t=new Fraction(a,b);
 61                 String tt=t.toString();
 62                 return tt;
 63             }
 64         }           
 65     }
 66     
 67 
 68     
 69     public int maxyueshu( int a, int b ){
 70         return a%b==0?b:maxyueshu(b,a%b);     
 71     }
 72     
 73     public Fraction simple(Fraction a){
 74         int max=this.maxyueshu(a.denominator, a.numerator);
 75         a.denominator=a.denominator/max;
 76         a.numerator=a.numerator/max;
 77         return a;
 78     }
 79     
 80    
 81     public Fraction fraccalculate(Fraction a,char op,Fraction b){//分数之间的计算
 82         int fenzi,fenmu;
 83         
 84         if(op=='+'){
 85              fenzi=a.denominator*b.numerator+a.numerator*b.denominator;
 86              fenmu=a.denominator*b.denominator;
 87         }else if(op=='-'){
 88              fenzi=a.numerator*b.denominator-a.denominator*b.numerator;
 89              fenmu=a.denominator*b.denominator;
 90         }else if(op=='*'){
 91              fenzi=a.numerator*b.numerator;
 92              fenmu=a.denominator*b.denominator;
 93         }else{
 94              fenzi=a.numerator*b.denominator;
 95              fenmu=a.denominator*b.numerator;
 96         }
 97         if(fenzi*fenmu==0){
 98             return new Fraction(fenzi, fenmu);
 99         }else{
100             return this.simple(new Fraction(fenzi,fenmu));
101         }
102         
103     }
104     
105    
106     public void frcmatch(){//分数形式b1/a1和b2/a2
107         int a1=0,b1=0,a2=0,b2=0;
108         char op=' ';
109         String myanswer;
110         while(b1>=a1){
111             a1=this.num()+1;
112             b1=this.num();
113         }
114         Fraction t1=this.simple(new Fraction(a1,b1));
115         while(b2>=a2){
116             a2=this.num()+1;
117             b2=this.num();
118         }
119         Fraction t2=this.simple(new Fraction(a2,b2));
120         op=this.operate();
121         if(op=='/'&&t2.numerator==0){//判读第二个分数的分子是否等于0,此时的分数不能执行除法
122             this.frcmatch();
123         }else{
124             System.out.print("请做题:("+t1.toString()+")"+op+"("+t2.toString()+")=");
125         }
126         Fraction answer=new Fraction(1,1);
127         answer=this.fraccalculate(t1, op, t2);
128         Scanner in= new Scanner(System.in); 
129         myanswer=in.next();
130         if(myanswer.equals(answer.toString())){
131             System.out.println("恭喜,答案正确。");
132         }
133         else{
134             System.out.println("很抱歉,答案错误。正确答案为:"+answer);
135         }
136     }
137     
138     public static void main(String[] args) {
139         FractionCalculation a=new FractionCalculation();
140         int num;
141         for(num=1;num<=100;num++){
142             int i=a.num();
143             if(i>50)
144                 a.intmatch();
145             else
146                 a.frcmatch();
147         }
148     }
149 
150 }

其中GenerateFormula.java的全部代码为:

  1 package ljf;
  2 
  3 public class GenerateFormula {
  4 
  5     // e := n | e1 + e2 | e1 − e2 | e1 × e2 | e1 ÷ e2 | (e) , 其中e,
  6     // e1和e2为表达式,n为自然数或真分数
  7     public static int n = 0;
  8     public static int nMax = 0;
  9     public static int s = 10;
 10 
 11     public static int maxyueshu(int a, int b) {
 12         return a % b == 0 ? b : maxyueshu(b, a % b);
 13     }
 14 
 15     public static String getTrueFraction() {
 16         int i, j;// i分子,j分母,分母要大于分子,要约粉
 17         while (true) {
 18             i = (int) (Math.random() * 100) % s + 1;
 19             j = (int) (Math.random() * 100) % s + 1;
 20             if ((j > i) && (j != 1)) {
 21                 int max = maxyueshu(j, i);
 22                 i /= max;
 23                 j /= max;
 24                 return i + "/" + j;
 25             }
 26         }
 27     }
 28 
 29     public static String fourRan(int pre) {
 30         // pre代表上一步的运算符,1+ 2- 3* 4/ 5() 6数
 31         n++;
 32         int i = (int) (Math.random() * 100) % 6 + 1;
 33 
 34         String str = "";
 35         if (n < nMax)
 36             ;
 37         else
 38             i = 6;
 39         switch (i) {
 40         case 1:
 41             str = fourRan(1) + "+" + fourRan(1);
 42             break;
 43         case 2:
 44             str = fourRan(2) + "-" + fourRan(2);
 45             break;
 46         case 3:
 47             str = fourRan(3) + "*" + fourRan(3);
 48             break;
 49         case 4:
 50             str = fourRan(4) + "/" + fourRan(4);
 51             break;
 52         case 5:
 53             if(pre==5){
 54                 str=fourRan(5);
 55             }else{
 56             str = "(" + fourRan(5) + ")";
 57             }
 58             break;
 59         case 6:
 60             int temp = (int) (Math.random() * 100) % 2 + 1;
 61             if (temp == 1) {
 62                 // 生成数字返回
 63                 if (pre == 4) {
 64                     return (int) (Math.random() * s) + 1 + "";
 65                 } else {
 66                     return (int) (Math.random() * s) + "";
 67                 }
 68 
 69             } else {
 70                 if(pre==5){
 71                     return  getTrueFraction() ;
 72                 }else
 73                 return "(" + getTrueFraction() + ")";
 74 
 75             }
 76         }
 77 
 78         return str;
 79     }
 80 
 81     public static String getFormula(int ni, int si) {
 82         n=0;
 83         nMax = ni;
 84         s = si;
 85         String str = "", result = "";
 86         int i;
 87         i = (int) (Math.random() * 100) % 4 + 1;
 88         switch (i) {
 89         case 1:
 90             str = fourRan(1) + "+" + fourRan(1);
 91             break;
 92         case 2:
 93             str = fourRan(2) + "-" + fourRan(2);
 94             break;
 95         case 3:
 96             str = fourRan(3) + "*" + fourRan(3);
 97             break;
 98         case 4:
 99             str = fourRan(4) + "/" + fourRan(4);
100             break;
101 
102         }
103 /*
104         // 对生成的式子进行去除多余括号处理
105         String[] postfix = MidToPosT.Change(str);
106         String[] infix = PostToMid.getInfixByPostfix(postfix);
107         for (int in = 0; !infix[in].equals("#"); in++) {
108             result = result + infix[in];
109         }
110         return result;
111         */
112         return str;
113     }
114 
115 }

其中MidToPosT.java的代码为:

  1 package ljf;
  2 
  3 public class MidToPosT {
  4 
  5     // 定义符号的优先级
  6     public static int Precedence(char sign) {
  7         switch (sign) {
  8         // +、-都为1
  9         case '+':
 10         case '-':
 11             return 1;
 12             // *、/为2
 13         case '*':
 14         case '/':
 15             return 2;
 16         case '(':
 17         case ')':
 18         default:
 19             return 0;
 20         }
 21     }
 22 
 23     /**************** 中缀表达式转换成后缀表达式 ********************/
 24     public static String[] Change(String str) {
 25         String[] s2 = new String[Test.MAX_RANGE];
 26         // #为结束符
 27         String s1 = str + "#";
 28         // 定义大小为20的String类型的栈
 29         Stack<Character> T = new Stack<Character>(Test.MAX_RANGE);
 30         int i = 0, j = 0;
 31         char ch;
 32         String temp = " ";
 33         T.push('@');
 34         ch = s1.charAt(i);
 35         while (ch != '#') {
 36             // 遇到'('就进栈
 37             if (ch == '(') {
 38                 T.push(ch);
 39                 ch = s1.charAt(++i);
 40             } else if (ch == ')') {
 41                 // 遇到')'就把栈中'('后的符号全部出栈
 42                 while (T.getTop() != '(')
 43                     s2[j++] = String.valueOf(T.pop());
 44                 T.pop();
 45                 ch = s1.charAt(++i);
 46             } else if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {
 47                 char w = T.getTop();
 48                 while (Precedence(w) >= Precedence(ch)) {
 49                     s2[j++] = String.valueOf(w);
 50                     T.pop();
 51                     w = T.getTop();
 52                 }
 53                 T.push(ch);
 54                 ch = s1.charAt(++i);
 55             } else {
 56                 if ((ch >= '0' && ch <= '9') || ch == '.') {
 57                     int k = i;
 58                     int flag = 1;
 59                     int arr = 0;
 60                     int q = 0;// 记录到下一个位置
 61                     for (; s1.charAt(i) >= '0' && s1.charAt(i) <= '9'; i++) {
 62                         if (i == s1.length() - 1) {
 63                             flag = 0;
 64                             break;
 65                         }
 66                     }
 67                     if (flag == 1) {
 68                         q = i;
 69                         i--;
 70                         for (int t = k; t <= i; t++) {
 71                             int single = Integer.parseInt(String.valueOf(s1
 72                                     .charAt(t)));
 73                             for (int p = t; p < i; p++) {
 74                                 single = single * 10;
 75                             }
 76                             arr = arr + single;
 77                         }
 78                         i = q;
 79                     } else {
 80                         q = i;
 81                         q++;
 82                         for (int p = k; p <= i; p++) {
 83                             int single = Integer.parseInt(String.valueOf(s1
 84                                     .charAt(p)));
 85                             for (int t = p; t < i; t++) {
 86                                 single = single * 10;
 87                             }
 88                             arr = arr + single;
 89                         }
 90                         i = q;
 91                     }
 92 
 93                     s2[j++] = String.valueOf(arr);
 94                     ch = s1.charAt(i);
 95                 }
 96             }
 97         }
 98         ch = T.pop();
 99         while (ch != '@') {
100             s2[j++] = String.valueOf(ch);
101             ch = T.pop();
102         }
103         s2[j++] = "#";
104         return s2;
105     }
106 
107 
108 }

其中Stack.java的全部代码为:

 1 package ljf;
 2 
 3 public class Stack<T> {
 4     private int top;
 5     private T[] stackArray;
 6     private int maxSize;
 7 
 8     //
 9     public Stack(int maxSize) {
10         this.maxSize = maxSize;
11         this.top = -1;
12         stackArray = (T[])new Object[this.maxSize];
13     }
14 
15     //进栈
16     public void push(T push) {
17         stackArray[++top] =push;
18     }
19 
20     // 出栈
21     public T pop() {
22         return stackArray[top--];
23     }
24 
25     // 得到栈顶元素
26     public T getTop() {
27         return stackArray[top];
28     }
29 
30     // peek the character at index n
31     public T peekN(int index) {
32         return stackArray[index];
33     }
34 
35     //判断是否为空
36     public boolean isEmpty() {
37         return (top == -1);
38     }
39 
40     // return stack size
41     public int size() {
42         return top + 1;
43     }
44 
45 }

其中Test.java的代码为:

 1 package ljf;
 2 
 3 import java.util.Scanner;
 4 
 5 public class Test {
 6 
 7     public static int MAX_RANGE = 40;
 8 
 9     public static void main(String[] args) {
10         // TODO Auto-generated method stub
11 
12         FractionCalculation fCal = new FractionCalculation();
13         Scanner sc = new Scanner(System.in);
14         System.out.print("输入最多能接受的操作符总数:");
15         int n = sc.nextInt();
16         System.out.print("输入能接受的最大操作数:");
17         int s = sc.nextInt();
18         int sum = 0, trueSum = 0;
19         char flag = 'y';
20         while (flag == 'y') {
21             sum++;// 记录做题总数
22             String str = GenerateFormula.getFormula(n, s);
23             System.out.print(str + "=");
24             String userAnswer = sc.next().trim();
25             // 判断是否为大于1的真分数
26             if (userAnswer.indexOf("'") > 0) {
27                 String[] array = userAnswer.split("'");
28                 // 判断是否是负数的输入
29                 if (array[0].indexOf("-") >= 0) {
30                     Fraction a = new Fraction(Integer.parseInt(array[0]
31                             .split("-")[1]), 1);
32                     Fraction b = new Fraction(Integer.parseInt(array[1]
33                             .split("/")[0]), Integer.parseInt(array[1]
34                             .split("/")[1]));
35                     userAnswer = "-" + fCal.fraccalculate(a, '+', b).numerator
36                             + "/" + fCal.fraccalculate(a, '+', b).denominator;
37                 } else {
38                     Fraction a = new Fraction(Integer.parseInt(array[0]), 1);
39                     Fraction b = new Fraction(Integer.parseInt(array[1]
40                             .split("/")[0]), Integer.parseInt(array[1]
41                             .split("/")[1]));
42                     userAnswer = fCal.fraccalculate(a, '+', b).numerator + "/"
43                             + fCal.fraccalculate(a, '+', b).denominator;
44                 }
45             }
46             // 化简用户输入的结果
47             if (userAnswer.indexOf("/") > 0) {
48                 if (userAnswer.split("/")[1].equals("1")) {
49                     userAnswer = userAnswer.split("/")[0];
50                 }
51             }
52             // 计算真正的结果并化简
53             Fraction fa = Calculation.cal(str.trim());
54             if (fa.numerator * fa.denominator < 0) {
55                 fa.numerator = fa.numerator > 0 ? -fa.numerator : fa.numerator;
56                 fa.denominator = fa.denominator > 0 ? fa.denominator
57                         : -fa.denominator;
58             }
59             String trueAnswer;
60             if (fa.denominator == 1) {
61                 trueAnswer = fa.numerator + "";
62             } else {
63                 if (fa.numerator == 0) {
64                     trueAnswer = "0";
65                 } else {
66                     trueAnswer = fa.numerator + "/" + fa.denominator;
67                 }
68             }
69 
70             if (trueAnswer.equals(userAnswer)) {
71                 System.out.println("√");
72                 trueSum++;
73             }
74             else {
75                 System.out.println("×   正确答案是:" + trueAnswer);
76             }
77 
78             System.out.println();
79             System.out.print("是否继续(继续y , 退出n):");
80             flag = sc.next().charAt(0);
81         }
82         System.out.println("退出成功!  共做 "+sum+" 道题,做对 "+trueSum+" 道题,做错 "+(sum-trueSum)+" 道题。");
83     }
84 
85 }
原文地址:https://www.cnblogs.com/xiaolong2333/p/5862570.html