實現一個自動生成小學四則運算題目的命令行程序(java實現)


Github項目地址:https://github.com/xiaobaot/wordcount/tree/master/sizeyusuan

團隊成員:謝家明(代碼生成)    謝竣(測試完善)

項目需求:

1. 使用 -n 參數控制生成題目的個數,例如

 Myapp.exe -n 10

 將生成10個題目。

2. 使用 -r 參數控制題目中數值(自然數、真分數和真分數分母)的范圍,例如

 Myapp.exe -r 10

 將生成10以內(不包括10)的四則運算題目。該參數可以設置為1或其他自然數。該參數必須給定,否則程序報錯並給出幫助信息。

3. 生成的題目中計算過程不能產生負數,也就是說算術表達式中如果存在形如e1 − e2的子表達式,那么e1 ≥ e2

4. 生成的題目中如果存在形如e1 ÷ e2的子表達式,那么其結果應是真分數

5. 每道題目中出現的運算符個數不超過3個。

6. 程序一次運行生成的題目不能重復,即任何兩道題目不能通過有限次交換+和×左右的算術表達式變換為同一道題目。例如,23 + 45 = 和45 + 23 = 是重復的題目,6 × 8 = 和8 × 6 = 也是重復的題目。3+(2+1)和1+2+3這兩個題目是重復的,由於+是左結合的,1+2+3等價於(1+2)+3,也就是3+(1+2),也就是3+(2+1)。但是1+2+3和3+2+1是不重復的兩道題,因為1+2+3等價於(1+2)+3,而3+2+1等價於(3+2)+1,它們之間不能通過有限次交換變成同一個題目。

生成的題目存入執行程序的當前目錄下的Exercises.txt文件,格式如下:

1. 四則運算題目1

2. 四則運算題目2

……

 其中真分數在輸入輸出時采用如下格式,真分數五分之三表示為3/5,真分數二又八分之三表示為2’3/8。

7. 在生成題目的同時,計算出所有題目的答案,並存入執行程序的當前目錄下的Answers.txt文件,格式如下:

 1. 答案1

2. 答案2

 特別的,真分數的運算如下例所示:1/6 + 1/8 = 7/24。

8. 程序應能支持一萬道題目的生成。

9. 程序支持對給定的題目文件和答案文件,判定答案中的對錯並進行數量統計,輸入參數如下:

 Myapp.exe -e <exercisefile>.txt -a <answerfile>.txt

 統計結果輸出到文件Grade.txt,格式如下:

 Correct: 5 (1, 3, 5, 7, 9)

Wrong: 5 (2, 4, 6, 8, 10)

其中“:”后面的數字5表示對/錯的題目的數量,括號內的是對/錯題目的編號。為簡單起見,假設輸入的題目都是按照順序編號的符合規范的題目

PSP開發耗時

 

PSP2.1

Personal Software Process Stages

預估耗時(分鍾)

實際耗時(分鍾)

Planning

計划

60

100

· Estimate

· 估計這個任務需要多少時間

100

120

Development

開發

600

660

· Analysis

· 需求分析 (包括學習新技術)

120

150

· Design Spec

· 生成設計文檔

40

50

· Design Review

· 設計復審 (和同事審核設計文檔)

50

60

· Coding Standard

· 代碼規范 (為目前的開發制定合適的規范)

40

40

· Design

· 具體設計

60

60

· Coding

· 具體編碼

120

120

· Code Review

· 代碼復審

60

90

· Test

· 測試(自我測試,修改代碼,提交修改)

60

60

Reporting

報告

90

90

· Test Report

· 測試報告

60

60

· Size Measurement

· 計算工作量

30

30

· Postmortem & Process Improvement Plan

· 事后總結, 並提出過程改進計划

30

30

合計

 

1520

1720

 

設計思路

1.我們首先想到的是整數化分數的運算,再對分子分母進行化簡,我們試圖生成兩個分子和兩個分母(分母至少一個為零時則全置為1,從而達到生成整數而用分數去運算的效果)來實現讓整數和分數的計算可以同步。

2.對分數(不論是結果還是題目)進行判斷,是假分數則化為帶分數的形式,是真分數保持不變。

3.通過對不同文件的操作輸出題目,答案以及統計答題者情況。

4.程序需求中的查重功能沒有實現。

具體代碼實現

main函數部分代碼:

public static void main(String[] args){
     Scanner sc= new Scanner(System.in);
     System.out.println("請輸入產生幾以內的數字:");
     range=sc.nextInt();
     System.out.println("請輸入產生多少個運算表達式:");
     int num=sc.nextInt();
     int rightcount[]=new int[num+2];
     int wrongcount[]=new int[num+2];
     int right1=0;
    int wrong1=0;
    String[] results=new String[num];int i;
     for( i=0;i<num;i++){ 
/*具體的功能如下面的代碼(兩個class除外)*/

}

生成題目:

 

String expArr[]=new String[2];//定義生成的題目
        int a= (int) (random.nextInt(range));//分子
        int b= (int) (random.nextInt(range));//分母
        int c= (int) (random.nextInt(range));//另一個分子
        int d= (int) (random.nextInt(range));//另一個分母
        int fuhao;//運算符
        fuhao= (int) (random.nextInt(4));
        if(b!=0&&d!=0) {//分母均不為0時生成帶有分數的計算題,同時計算結果
        if(fuhao==0) {
            int fenzi=a*d+b*c;
            int fenmu=b*d;
            expArr[0]=biaodashi(a,b)+'+'+biaodashi(c,d)+'=';
            System.out.println(expArr[0]);
            results[i]=reductionofFraction(fenzi, fenmu);
        
        }
        if(fuhao==1&&a*d-b*c>=0) {
            int fenzi=a*d-b*c;
            int fenmu=b*d;
            expArr[0]=biaodashi(a,b)+'-'+biaodashi(c,d)+'=';
            System.out.println(expArr[0]);
            results[i]=reductionofFraction(fenzi, fenmu);
            
        }
        if(fuhao==1&&a*d-b*c<0) {
            int fenzi=b*c-a*d;
            int fenmu=b*d;
            expArr[0]=biaodashi(a,b)+'-'+biaodashi(c,d)+'=';
            System.out.println(expArr[0]);
            results[i]=reductionofFraction(fenzi, fenmu);
            
        }
        if(fuhao==2) {
            int fenzi=a*c;
            int fenmu=b*d;
            expArr[0]=biaodashi(a,b)+'×'+biaodashi(c,d)+'=';
            System.out.println(expArr[0]);
            results[i]=reductionofFraction(fenzi, fenmu);
            
        }
        if(fuhao==3&&c!=0) {
            int fenzi=a*d;
            int fenmu=b*c;
            expArr[0]=biaodashi(a,b)+'÷'+biaodashi(c,d)+'=';
            System.out.println(expArr[0]);
            results[i]=reductionofFraction(fenzi, fenmu);
            
        }
        if(fuhao==3&&c==0) {
            break;
            /*c=1;
            int fenzi=a*d;
            int fenmu=b*c;
            expArr[0]=biaodashi(a,b)+'÷'+biaodashi(c,d)+'=';
            System.out.println(expArr[0]);
            results[i]=reductionofFraction(fenzi, fenmu);*/
            
        }
        
        }
        else {//分母至少一個為0時生成只含有整式的運算式,同時計算結果
            b=1; d=1;
            if(fuhao==0) {
            int fenzi=a*d+b*c;
            int fenmu=b*d;
            expArr[0]=a+"+"+c+"=";
            System.out.println(expArr[0]);
            results[i]=reductionofFraction(fenzi, fenmu);//計算結果
            
        }
        if(fuhao==1&&a*d-b*c>=0) {
            int fenzi=a*d-b*c;
            int fenmu=b*d;
            expArr[0]=a+"-"+c+"=";
            System.out.println(expArr[0]);
            results[i]=reductionofFraction(fenzi, fenmu);//計算結果
}
if(fuhao==1&&a*d-b*c<0) { int fenzi=b*c-a*d; int fenmu=b*d; expArr[0]=c+"-"+a+"="; System.out.println(expArr[0]); results[i]=reductionofFraction(fenzi, fenmu);//計算結果
}
if(fuhao==2) { int fenzi=a*c; int fenmu=b*d; expArr[0]=c+"×"+a+"="; System.out.println(expArr[0]); results[i]=reductionofFraction(fenzi, fenmu);//計算結果
}
if(fuhao==3&&c!=0) { int fenzi=a*d; int fenmu=b*c; expArr[0]=a+"÷"+c+"="; System.out.println(expArr[0]); results[i]=reductionofFraction(fenzi, fenmu);//計算結果
}
if(fuhao==3&&c==0) { break;//排除分母為零的情況 /*c=1; int fenzi=a*d; int fenmu=b*c; expArr[0]=a+"÷"+c+"="; System.out.println(expArr[0]); results[i]=reductionofFraction(fenzi, fenmu);*/ }

 

對分數的處理:

public static String reductionofFraction(int a, int b) {// 結果的分數約分,用於計算結果
        int y = 1;
        for (int i = a; i >= 1; i--) {
            if (a % i == 0 && b % i == 0) {
                y = i;
                break;
            }
        }
        int z = a / y;// 分子
        int m = b / y;// 分母
        if (z == 0) {
            return "0";
        }
        if(m==1) return z+"";
        else  return biaodashi(z,m);
        
    }
    public static String biaodashi(int a,int b) {//判斷假分數,並化假分數為帶分數
        if(a>=b) {
            int c;
            c=a/b;
            int d;
            d=a%b; 
            {if(d==0) {return c+"";}
            return c+"'"+d+"/"+b;}
        }return a+"/"+b;
    }

生成題目文件及答案文件:

 

 

FileWriter fw = null;
    try {
   
        File f=new File("Exersies.txt");//題目寫入
        fw = new FileWriter(f, true);
    } catch (IOException e) {
        e.printStackTrace();
    }if(expArr[0]!=null) {
    PrintWriter pw = new PrintWriter(fw);
    pw.println(i+1+"."+expArr[0]);
    pw.flush();
    try {
        fw.flush();
        pw.close();
        fw.close();
    } catch (IOException e) {
        e.printStackTrace();
    }}FileWriter fn = null;
    try {
        
            File f=new File("Answer.txt");//答案寫入
            fn = new FileWriter(f, true);
        } catch (IOException e) {
            e.printStackTrace();
        }if(expArr[0]!=null) {
        PrintWriter pn = new PrintWriter(fn);
        pn.println(i+1+"."+results[i]);
        pn.flush();
        try {
            fn.flush();
            pn.close();
            fn.close();
        } catch (IOException e) {
            e.printStackTrace();
        }}

 

統計並輸出答題者的情況:

 

System.out.println("輸入ok提交!");//答題完成后輸入ok即可提交
     Scanner sc1=new Scanner(System.in);
     String submit=sc1.nextLine();
        if(submit.equals("ok")){
     String array[]=new String[num];
     try
        {   int k=0;
            
            FileReader fr = new FileReader("H://eclipse2//eclipse3//sizeyusuan//Your_answers.txt");
            BufferedReader br = new BufferedReader(fr);
            String s ;
            while((s = br.readLine())!=null) {//讀取小學生的答案
                array[k]=s;    k++;
                }br.close();
            fr.close();        
            }catch(IOException e){
                System.out.println("指定文件不存在");
            }
    for(int j=0;j<num;j++){
         if(array[j].equals(results[j])) {//驗證答案,統計正確和錯誤的個數
             
             rightcount[j]=j+1;
             right1++;
         }
         else {
             
             wrongcount[j]=j+1;
             wrong1++;
         }
     }
    FileWriter fg = null;
    try {
        //反饋正確與錯誤題目的信息
            File f=new File("Grade.txt");
            fg = new FileWriter(f, true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        PrintWriter pg = new PrintWriter(fg);
        pg.println(" ");
        pg.print("Correct:"+right1+"(");
        for (int j = 0; j <= num; j++) {
            if (rightcount[j] != 0) {
                 pg.print(rightcount[j] + ",");
            }
        }
        pg.println(")");
        pg.print("Wrong:"+wrong1+"(");
        for (int j = 0; j <= num; j++) {
            if (wrongcount[j] != 0) {
                 pg.print(wrongcount[j] + ",");
            }
        }
        pg.print(")");
        pg.flush();
        try {
            fg.flush();
            pg.close();
            fg.close();
        } catch (IOException e) {
            e.printStackTrace();
        }}

 測試運行

題目文件

 

答案文件

答題者答案文件

校對文件

項目小結

1.每道題目中出現的運算符個數我們只實現了單個運算符,當我們后來試圖擴展多個運算符的時候發現時間不夠了,因此只能上交較為簡單的版本。

2.查重功能以我們的算法和我們的能力感覺實現有難度,所以並不在我們的計划中。

3.遇到的困難主要是數組越界,通過嚴謹的檢查以及步步驗證的方式找出了錯誤並解決了。另一個須待解決的問題是生成題目的速度有些緩慢,因此完善了多次的算法來提高代碼的執行效率。

4.總的來說,在結對編程中我們有各自的想法,通過代碼的形式來進行人與人之間的交流不失為一種好的方法,在這個過程中我們培養了團隊協作的能力和與他人交際的能力,同時也促使自身的編程能力不斷提高,這使我們都受益匪淺。當然如果還有機會的話,我還是希望可以實現帶括號的運算式的生成以及答案的計算。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM