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