碼市連結: https://coding.net/u/Lynn_LinYan/p/Random/git
一、需求分析:
- 除了整數以外,還要支援真分數的四則運算,真分數的運算,例如:1/6 + 1/8 = 7/24
- 運算符為 +, −, ×, ÷
- 并且要求能處理使用者的輸入,并判斷對錯,打分統計正确率。
- 要求能處理使用者輸入的真分數, 如 1/2, 5/12 等
-
使用 -n 參數控制生成題目的個數,例如執行下面指令将生成10個題目
Myapp.exe -n 10
二、功能設計:
- 基本功能:實作簡單的加減乘除出題并驗證對錯
- 擴充功能:能實作真分數的加減乘除
- 進階功能:統計正确率和錯誤率
三、設計實作:

項目中設計了一個重要的類,其方法和屬性如上圖所示;還有一個就是main類,主要實作輸入輸出以及驗證答案是否正确。在實作的過程中主要就是分數的運算比較難,設計産生随機數的話,其實将整數看成分母為1的分數比較好處理,這樣一來,問題就轉換成分數的加減乘除了,但是分數的運算涉及到最大公約數和最小公倍數,是以寫函數的時候也寫了這兩個函數來處理分數的加減以及最後結果的化簡。最後通過重寫toString方法輸出真确的答案,在main函數中與使用者輸入的答案進行一一比較,判斷正确并統計正确率。
1.重要的函數:
産生随機數:
1 //随機産生一個分數或者整數
2 public void createFenShu(RandomNum f){
3 Random random=new Random();
4 int a=random.nextInt(101);
5 int b=random.nextInt(100) + 1; //産生随機數1-100作為分母
6 if(b!=0&&((a%b==0)||a<b)) //為整數或者真分數(分母不為0且分子小于分母)
7 {
8 f.setFenzi(a);
9 f.setFenmu(b);
10 }
11 else
12 createFenShu(f);
13 }
14 public void createInteger(RandomNum f){
15 Random random=new Random();
16 int a=random.nextInt(101);
17 f.setFenzi(a);
18 f.setFenmu(1); //分母為1,即産生整數
19 }
重寫toString方法:
1 @Override
2 public String toString() {
3 // TODO Auto-generated method stub
4 int n = this.FindZuiDa();
5 int fenzi = this.fenzi/n;
6 int fenmu = this.fenmu/n;
7 if(fenzi == 0){
8 return Integer.toString(fenzi);
9 }
10 if(fenzi >= fenmu){ //如果分子大于分母
11 if(fenzi % fenmu == 0){
12 return Integer.toString(fenzi / fenmu);
13 }else{
14 return Integer.toString(fenzi) + "/" + Integer.toString(fenmu);
15 }
16 }else{
17 return Integer.toString(fenzi) + "/" + Integer.toString(fenmu);
18 }
19 }
20
加法運算:
1 //加運算
2 public String Add(RandomNum r2){
3 int zuiXiao =this.FindZuixiao(r2);
4 int fenzi = ((zuiXiao / this.fenmu) * this.fenzi) + ((zuiXiao / r2.getFenmu())* r2.getFenzi());
5 this.setFenzi(fenzi);
6 this.setFenmu(zuiXiao);
7 return this.toString();
8 }
減法運算:
1 //減運算
2 public String Substract(RandomNum r2){
3 int zuiXiao =this.FindZuixiao(r2);
4 int fenzi = ((zuiXiao / this.fenmu) * this.fenzi) - ((zuiXiao / r2.getFenmu())* r2.getFenzi());
5 this.setFenzi(fenzi);
6 this.setFenmu(zuiXiao);
7 return this.toString();
8 }
乘法運算:
1 public String mul(RandomNum r2){
2 this.fenzi = this.fenzi * r2.getFenzi();
3 this.fenmu = this.fenmu * r2.getFenmu();
4 return this.toString();
5 }
除法運算:
1 //除運算
2 public String deivde(RandomNum r2){
3 this.fenzi = this.fenzi * r2.getFenmu();
4 this.fenmu = this.fenmu * r2.getFenzi();
5 return this.toString();
6 }
2.代碼說明:
(1)用一個随機數生成兩個随機數,使得這兩個數是整數或者分數随機。
1 int totalCnt = 0; //總題數
2 int cnt = 0; //目前已完成的題數,用來做循環的判斷
3 int rightCnt = 0; //做正确的題數
4 int errorCnt = 0; //做錯誤的題數
5 Scanner input = new Scanner(System.in);
6 System.out.print("請輸入你要做的題數:");
7 totalCnt = input.nextInt();
8 while (cnt < totalCnt) {
9 RandomNum a = new RandomNum();
10 RandomNum b = new RandomNum();
11 int number = new Random().nextInt(2);
12 switch (number) { //随機生成的題目是整式或者分式或者混合式子
13 case 0:
14 a.createInteger(a);
15 b.createInteger(b);
16 break;
17 case 1:
18 a.createFenShu(a);
19 b.createFenShu(b);
20 break;
21 default:
22 a.createInteger(a);
23 b.createFenShu(b);
24 break;
25 }
26
(2)用一個随機數産生加減乘除算式中的任意一個并驗證使用者輸入的答案是否與正确答案一緻,将分子、分母分别放在StrArr[0],Str[1]中。(注意下面第二張代碼展示了如何避免減法産生負數;減法,乘法,除法和加法類似,在此處不一一粘貼代碼)
1 number = new Random().nextInt(4);
2 String result ;
3 String[] strArr = new String[2]; //存放使用者輸入的答案的分子和分母
4 switch (number) {
5 // 加法
6 case 0:
7 System.out.print(a.toString() + " + " + b.toString() + " = ");
8 result = input.nextLine();
9 while(result.length() == 0 ||result.equals('\n') || result.equals('\r')){
10 result = input.nextLine();
11 }
12 if (result.trim().indexOf("/") >= 0) { //如果輸入的答案是分數
13 strArr = result.trim().split("/"); //将輸入答案的分子分母分開放在strArr[0]和strArr[1]中并去掉空格
14 } else {
15 strArr[0] = result.trim();
16 strArr[1] = "1"; //否則置分母為1
17 }
18 if (strArr[1].equals("0")) { //若輸入的分數分母為0,則答案錯誤
19 System.out.println("答案錯誤!正确答案為:" + a.Add(b));
20 errorCnt++;
21 } else {
22 try {
23 int fz1 = Integer.parseInt(strArr[0].trim());
24 int fm1 = Integer.parseInt(strArr[1].trim());
25 RandomNum c = new RandomNum(fz1, fm1);
26 a.Add(b);
27 if (c.toString().equals(a.toString())) {
28 rightCnt++;
29 System.out.println("答案正确!");
30 } else {
31 errorCnt++;
32 System.out.println("答案錯誤!正确答案為:" + a.toString());
33 }
34 } catch (NumberFormatException e) {
35 // TODO Auto-generated catch block
36 //e.printStackTrace();
37 errorCnt++;
38 System.out.println("答案錯誤!正确答案為:" + a.Add(b));
39 }
40
41 }
42 break;
1 // 減法
2 case 1:
3 double x = (double) a.getFenzi() / a.getFenmu();
4 double y = (double) b.getFenzi() / b.getFenmu();
5 if (x < y) { //若出現負數,則将減數和被減數替換位置
6 int fzTemp = a.getFenzi();
7 int fmTemp = a.getFenmu();
8 a.setFenmu(b.getFenmu());
9 a.setFenzi(b.getFenzi());
10 b.setFenmu(fmTemp);
11 b.setFenzi(fzTemp);
12 }
(3)統計正确題數、錯誤題數以及正确率和錯誤率
1 System.out.println('\n'+"共答題"+cnt+"道,錯誤"+errorCnt+"題"+",正确"+rightCnt+"題");
2 System.out.println("正确率為:"+rightCnt*100/cnt+"%");
3.測試運作
四、展示PSP:這份PSP可能有點不太準,因為當時自己開始做這個實驗的時候沒有這樣的打算,做完後也隻能大概一下把零零散散的時間湊起來然後填好這個表格,我覺得花比較多的時間是在考慮如何處理分數這一塊,還有整個封裝,因為對java沒有很好的掌握,很多類合在一起寫,不是很規範;再有就是花在測試和改錯的時間比較長。我在下面表格中寫編寫代碼的時間比較久是因為挺久沒寫java的了,很多語句和用法都有些忘記了,然後查找的時間花了挺多。
五、小結
終于來到小結這個天地了,此時此刻我的心情多麼歡快啊!!!終于寫好了這個作業,其實在寫代碼的時候遇到了蠻多問題的,一般是先自己百度然後不會的再問同學的。比如在算式出來但是使用者自己不小心按回車的情況下,這樣也算錯誤的話,那不是賊可憐,是以想要判斷在輸入時回車的情況下繼續輸入,這就得想如何能知道使用者輸入的是回車呢?剛開始我隻是很簡單地認為接收到的是換行然後就刷刷刷往裡寫,但是測試好像通不過,為了這個問題百度了挺久的,最後才找到解決的辦法。剛開始做的時候,思路是完全亂的,因為有分數,不太懂怎麼處理,各種在網上找靈感,最終通過别人的指點,确定了用分數表示整數。如果很久沒寫代碼,真的會忘記很多,希望自己以後能堅持。這過程真的曲折,但是認真過後最開心了。