天天看點

個人作業1——四則運算題目生成程式(基于控制台)

碼雲位址:https://git.oschina.net/lzx84/szys

題目:

從《建構之法》第一章的 “程式” 例子出發,像阿超那樣,花二十分鐘寫一個能自動生成國小四則運算題目的指令行 “軟體”。

滿足以下需求:

    1. 除了整數以外,還要支援真分數的四則運算,真分數的運算,例如:1/6 + 1/8 = 7/24
    2. 運算符為 +, −, ×, ÷
    3. 并且要求能處理使用者的輸入,并判斷對錯,打分統計正确率。
    4. 要求能處理使用者輸入的真分數, 如 1/2, 5/12 等
    5. 使用 -n 參數控制生成題目的個數,例如執行下面指令将生成10個題目

      Myapp.exe -n 10

需求分析:

  • 需要處理分數,包括化簡分數、識别整數等。并考慮特殊情況,如分數分母不為0等。考慮到題目要求國小水準,則分子分母數值不超過100。
  • 需要編寫分數四則運算的算法,并考慮特殊情況,如減法結果不能為負數,除法中除數不能為0等。
  • 需統計使用者正确的題目數,與總題目數。
  • 需要實作字元串的識别與比較。

功能實作:

  • 基本功能:能随機生成若幹四則運算式,并檢測使用者答案,統計正确率。
  • 擴充功能:實作多項運算、統計做題時長、避免重複題型、控制題目難度等(未實作)
  • 進階功能:實作錯題統計功能、實作多使用者競賽功能、實作更複雜的運算等(未實作)

設計實作:

    Fraction類:

    Calculate類:

    Dofrac類:

代碼說明:

  Fraction類:

public class Fraction {

    private int fenzi;
    private int fenmu;

    public Fraction() {
        super();
    }

    public Fraction(int fenzi, int fenmu) {
        super();
        this.fenzi = fenzi;
        this.fenmu = fenmu;
        this.simplify(fenzi, fenmu); //在構造函數中直接化簡分數(感覺此方法欠妥)
    }



    public void simplify(int fenzi, int fenmu) { 
        int GCD = Dofrac.GCD(fenzi, fenmu);
        this.fenzi = fenzi / GCD;
        this.fenmu = fenmu / GCD;
    }//化簡分數

    @Override
    public String toString() {
        if (fenzi == 0) {
            return 0 + "";
        } else if (fenzi % fenmu == 0) {
            return fenzi / fenmu + "";
        } else
            return fenzi + "/" + fenmu;
    }//改寫toString,輸出為分數形式

    public int getFenzi() {
        return fenzi;
    }

    public void setFenzi(int fenzi) {
        this.fenzi = fenzi;
    }

    public int getFenmu() {
        return fenmu;
    }

    public void setFenmu(int fenmu) {
        this.fenmu = fenmu;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + fenmu;
        result = prime * result + fenzi;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Fraction other = (Fraction) obj;
        if (fenmu != other.fenmu)
            return false;
        if (fenzi != other.fenzi)
            return false;
        return true;
    }

}      

Calculate類:

public class Calculate {
    public static Fraction add(Fraction f1, Fraction f2) {

        int fz1 = f1.getFenzi();
        int fz2 = f2.getFenzi();
        int fm1 = f1.getFenmu();
        int fm2 = f2.getFenmu();
        Fraction f = new Fraction(fz1 * fm2 + fm1 * fz2, fm1 * fm2);
        return f;

    }//加法運算

    public static Fraction sub(Fraction f1, Fraction f2) {
        int fz1 = f1.getFenzi();
        int fz2 = f2.getFenzi();
        int fm1 = f1.getFenmu();
        int fm2 = f2.getFenmu();
        Fraction f = new Fraction(fz1 * fm2 - fm1 * fz2, fm1 * fm2);
        return f;
    }//減法運算

    public static Fraction mul(Fraction f1, Fraction f2) {
        int fz1 = f1.getFenzi();
        int fz2 = f2.getFenzi();
        int fm1 = f1.getFenmu();
        int fm2 = f2.getFenmu();
        Fraction f = new Fraction(fz1 * fz2, fm1 * fm2);
        return f;
    }//乘法運算

    public static Fraction div(Fraction f1, Fraction f2) {
        int fz1 = f1.getFenzi();
        int fz2 = f2.getFenzi();
        int fm1 = f1.getFenmu();
        int fm2 = f2.getFenmu();
        Fraction f = new Fraction(fz1 * fm2, fm1 * fz2);
        return f;
    }//除法運算

    public static boolean compare(Fraction f1, Fraction f2) {
        int fz1 = f1.getFenzi();
        int fz2 = f2.getFenzi();
        int fm1 = f1.getFenmu();
        int fm2 = f2.getFenmu();
        if (fz1 * fm2 >= fz2 * fm1) {
            return true;
        } else{
 
            return false;

        }      
}//比較兩分數的大小

}      

Dofrac類:

public class Dofrac {

    public static Fraction CreatFrac() {
        int fz, fm,co;
        co=(int)(Math.random()*2);//co取[0,1]得随機值,分别代表分數和整數

          if(co==0){      

              fm = (int) (2 + Math.random() * (100 - 2 + 1));//分母為2-100的随機數

              fz =(int) (0 + Math.random() * (fm - 0 + 1));//分子為 0--fm 的随機數(確定真分數)

          }else {

              fm=1;

              fz=(int) (0 + Math.random() * (100 - 0 + 1));

          }

Fraction frac = new Fraction(fz, fm);
        return frac;
    }//建立随機分數

    public static boolean check(String input) {
        if (input.matches("[0-9]+")||input.matches("[0-9]+/[0-9]+")) {
            return true;
        } else
            {      
return false;      
}
    }//利用正規表達式處理使用者輸入的答案

    public static int GCD(int m, int n) {
        while (true) {
            if ((m = m % n) == 0)
                return n;
            if ((n = n % m) == 0)
                return m;
        }
    }//計算最大公約數

    public static Fraction MakeFor(Fraction f1, Fraction f2, int op, int i) {
        Fraction result = new Fraction();
        switch (op) {
        case 1: {
            result = Calculate.add(f1, f2);
            System.out.println("第" + i + "題:" + f1.toString() + "+" + f2.toString());
            break;

        }
        case 2: {
            if (!Calculate.compare(f1, f2)) {
                Fraction temp = f1;
                f1 = f2;
                f2 = temp;
            }//比較兩分數的大小,若減數小于被減數,則将兩個數交換
            result = Calculate.sub(f1, f2);
            System.out.println("第" + i + "題:" + f1.toString() + "-" + f2.toString());
            break;
        }
        case 3: {
            result = Calculate.mul(f1, f2);
            System.out.println("第" + i + "題:" + f1.toString() + "*" + f2.toString());
            break;
        }
        case 4: {
            if (f2.getFenzi() == 0) {
                f2.setFenzi((int) (1 + Math.random() * (10 - 1 + 1)));
            }//若除數分子為0,則分子重新取一個1——100的随機數
            result = Calculate.div(f1, f2);
            System.out.println("第" + i + "題:" + f1.toString() + "÷" + f2.toString());
            break;
        }
        }
        return result;

    }
}      

Generator類(執行類)

public class Generator {

    public static void main(String[] args) {
        try {
            int op = 0;
            String input;
            int flag = 0;//用于檢測使用者答對的題目數
            Scanner sc = new Scanner(System.in);
            System.out.println("【四則運算題目生成器】");
            System.out.println("請輸入需要的題目數量:");
            int n = sc.nextInt();
            for (int i = 1; i <= n; i++) {
                Fraction f1 = Dofrac.CreatFrac();
                Fraction f2 = Dofrac.CreatFrac();
                op = (int) (Math.random() * 4 + 1);
                Fraction result = Dofrac.MakeFor(f1, f2, op, i);
                input = sc.next();
                while (!Dofrac.check(input)) {
                    System.out.println("輸入有誤,請重新輸入:");
                    input = sc.next();
                }

                if (input.equals(result.toString())) {
                    System.out.println("回答正确");
                    System.out.println("---------------------------------------------");
                    flag++;
                } else {
                    System.out.println("回答錯誤,正确答案是:" + result.toString());
                    System.out.println("---------------------------------------------");
                }

            }
            System.out.println("---------------------------------------------");
            System.out.println("答題完畢,你的正确率為" + 100 * flag / n + "%");
            sc.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}      

 測試運作:

PSP表:

PSP2.1 Personal Software Process Stages Time (%) Senior Student Time (%)
Planning 計劃 5min 30min
· Estimate 估計這個任務需要多少時間 8min 10min
Development 開發 2h 1h30min
· Analysis 需求分析 (包括學習新技術)
· Design Spec 生成設計文檔
· Design Review 設計複審 3min 1min
· Coding Standard 代碼規範
· Design 具體設計 1h
· Coding 具體編碼 40min
· Code Review 代碼複審
· Test 測試(自我測試,修改代碼,送出修改)
Reporting 報告
· 測試報告
計算工作量
并提出過程改進計劃

總結:

         此次作業整體難度不大,但是剛開始看到題目構思的時候,卻一度陷入僵局。也許是因為太久沒有程式設計,很多知識都忘記了,導緻剛開始的時候不懂從何下手。在思考了很久,複習了很多以前的知識後,大體上有了思路,但也不是很清晰,想到什麼寫什麼,迷迷糊糊就完成了。中間遇到的BUG也不是很多,但是調試花了很多時間,感覺這是自己程式設計思想不夠系統,對軟體的應用也不是很熟悉造成的,根本原因還是在于練習不夠,經驗不足。希望以後多加練習,可以更加進步。最後感謝老師們和助教的辛勤付出,你們辛苦了!