主要完成功能:在用戶指定最多的運算符個數後,該程序能夠隨機生成在指定個數以內的四冊運算式(包括+,-,*,/,(,),真分數等),在用戶輸入答案後,程序能夠計算隨機生成的運算式得到結果,然後與用戶輸入的結果進行比對,並判斷對錯與記錄用戶得分。
界面與運行結果為(在出題時真分數用“()”括起來):

該項目文件的結構如圖:

其中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 }