團隊名稱:起航
成員:
康取 201306114422
陳鍵 201306114416
羅偉業 201306114446
開發需求;
如同英語有隨身記APP,數學也能有隨身練,通過簡單的四則運算,提高使用者的心算速度。
物件導向;
小學生
四則運算功能;
1.產生兩個整數的四則運算算式
2.產生帶有分數的四則運算算式
3.產生帶有括號的四則運算算式
4.答題後匹配正確答案,正確則提示正確,錯誤則顯示正確答案
5.練習模式與考試模式供使用者選擇
6.練習模式是通過大量的題目練習
7.考試模式是在一定的時間內完成題目,並記錄分數,顯示正確率
8.美觀,簡潔的圖形使用者操作介面
小組成員分工;
康取;負責產生帶有分數的四則運算算式及驗證答案
陳健;負責圖形使用者操作介面設計(介面的計時功能,驗證答案後彈出正確與否),考試模式統計正確率與考試分數。帶括號的四則運算算式及驗證答案
羅偉業;負責兩個整數間的四則運算算式及驗證答案
程式碼如下;
package com.app.senior_calculator; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Toast; public class APP extends Activity { // 偏好設定 //private SharedPreferences sp; //private SharedPreferences.Editor editor; /** level and mode (index) **/ int selectedLevelIndex = 0; int selectedModeIndex = 0; int chioceItems; Bundle bundle = new Bundle(); /** choices **/ private String iconName1 = "選擇難度"; private String[] arrayLevel = new String[] { "加減", "乘除", "四則運算(帶分數)", "四則運算(含括號)" }; private String iconName2 = "選擇模式"; private String[] arrayModel = new String[] { "Practice", "Examination" }; /** 題目庫 **/ private List<Question> source = new ArrayList<Question>(); public void onclick(View v) { switch (v.getId()) { case R.id.StartTest: DialogDifficulty(arrayLevel, iconName1).show(); break; case R.id.Medol: DialogDifficulty(arrayModel, iconName2).show(); break; case R.id.Help: Toast.makeText(APP.this, " Dont know what to do……", Toast.LENGTH_SHORT).show(); break; case R.id.Exit: Toast.makeText(APP.this, " Closing…………", Toast.LENGTH_SHORT).show(); finish(); break; } } /** 定義一個Dialog 展示 level選擇 後者為標題 **/ public Dialog DialogDifficulty(final String[] array_data, final String dialogtitle) { chioceItems = selectedLevelIndex; if (dialogtitle.equals("選擇難度")) chioceItems = selectedLevelIndex; else if (dialogtitle.equals("選擇模式")) chioceItems = selectedModeIndex; Dialog alertDialog; alertDialog = new AlertDialog.Builder(this, R.style.dialog) .setTitle(dialogtitle) .setIcon(R.drawable.diologicon) .setSingleChoiceItems(array_data, chioceItems, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (dialogtitle.equals("選擇難度")) selectedLevelIndex = which; else if (dialogtitle.equals("選擇模式")) selectedModeIndex = which; /** 模式傳遞過去TestView根據模式來設定時間長度. */ bundle.putString("difficulty", arrayModel[selectedModeIndex]); } }) .setPositiveButton("確認", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { bundle.putString("difficulty", arrayModel[selectedModeIndex]); /* // 確定後儲存資料模式跟難度的下標資料.. if (dialogtitle.equals("選擇難度")) editor.putInt("selectedLevelIndex", which); if (dialogtitle.equals("選擇模式")) editor.putInt("selectedModeIndex", which); editor.commit();// 提交修改 */ /** 在確定難度後跳轉出題目 設定模式到時候不跳轉. **/ if (dialogtitle.equals("選擇難度")) createexercise(); } }) .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 實現函式- 。- 呼叫. Toast.makeText(APP.this, " canceling ", Toast.LENGTH_SHORT).show(); } }).create(); return alertDialog; } /** 出題模組 根據選擇的模式出先不同數量的題目. **/ public void createexercise() { int totalNumber = 50; if (arrayModel[selectedModeIndex].equals("Examination")) totalNumber = 25; switch (selectedLevelIndex) { case 0: source = new ArrayList<Question>(); Toast.makeText(APP.this, String.valueOf(selectedLevelIndex), Toast.LENGTH_LONG) .show(); /* 在這裡產生 totalNumber 條 題目. 出現了問題!!!????? */ new SimpleCreate().simpleExerciseInitation(0, totalNumber, source); for (int i = 0; i < source.size(); i++) Log.i("info", source.get(i).getExercise() + "=" + source.get(i).getAnswer()); bundle.putSerializable("resource", (Serializable) source); Intent MAintent = new Intent(APP.this, TestView.class); MAintent.putExtras(bundle); startActivity(MAintent); break; case 1: source = new ArrayList<Question>(); new SimpleCreate().simpleExerciseInitation(1, totalNumber, source); for (int i = 0; i < source.size(); i++) Log.i("info", source.get(i).getExercise() + "=" + source.get(i).getAnswer()); bundle.putSerializable("resource", (Serializable) source); Intent intent1 = new Intent(APP.this, TestView.class); intent1.putExtras(bundle); startActivity(intent1); break; case 2: source = new ArrayList<Question>(); new MidiumCreate().midiumCreateInitation(totalNumber, source); for (int i = 0; i < source.size(); i++) Log.i("info", source.get(i).getExercise() + "=" + source.get(i).getAnswer()); bundle.putSerializable("resource", (Serializable) source); Intent intent2 = new Intent(APP.this, TestView.class); intent2.putExtras(bundle); startActivity(intent2); break; case 3: source = new ArrayList<Question>(); // 出題目驗證. new CreateEFraction().createYouExercisess(2, source); for (int i = 0; i < source.size(); i++) Log.i("info", source.get(i).getExercise() + "=" + source.get(i).getAnswer()); bundle.putSerializable("resource", (Serializable) source); Intent intent3 = new Intent(APP.this, TestView.class); intent3.putExtras(bundle); startActivity(intent3); break; default: Toast.makeText(APP.this, "errors happend ", Toast.LENGTH_LONG) .show(); break; } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.app); /*// 獲取偏好設定例項 sp = getSharedPreferences("MySP", MODE_PRIVATE); editor = sp.edit(); editor.putInt("selectedLevelIndex",0); editor.putInt("selectedModeIndex", 0); editor.commit();// 提交修改 */ } }
package com.app.senior_calculator; import java.math.BigDecimal; import java.util.List; import java.util.Random; public class SimpleCreate { private MyCalculate calculate = new MyCalculate(); //偉業的生產 private String simpleExercise(int choice) { String practice = ""; int x = (int) (Math.random() * 50); int y = (int) (Math.random() * 50); int Random_Index; Random rad = new Random(); switch (choice) { case 0: String[] fuHao_1 = { "+" + "", "-" + "" }; Random_Index = rad.nextInt(fuHao_1.length); if (Random_Index == 1 && x < y) return y + fuHao_1[Random_Index] + x; practice = x + fuHao_1[Random_Index] + y; break; case 1: String[] fuHao_2 = { "x" + "", "/" + "" }; Random_Index = rad.nextInt(fuHao_2.length); if (Random_Index == 1 && y == 0) y = 1 + (int) (Math.random() * 50); practice = x + fuHao_2[Random_Index] + y; break; default: break; } return practice; } //weiye 生產 public void simpleExerciseInitation(int choice,int number, List<Question> question){ String questiontemp=""; String answertemp=""; for(int i=0;i<number;i++){ questiontemp = simpleExercise(choice); calculate.setExpression(questiontemp); answertemp = calculate.getResult(); answertemp = adjustResult(answertemp); question.add(new Question(questiontemp,answertemp,i+1)); /* Log.i("info", question.get(i).getExercise() + "=" + question.get(i).getAnswer() + " 第" +question.get(i).getCountNumber()+"題");*/ } } /** 比較答案的對錯,精度為0.001 **/ public String adjustResult(String CorrectResult) { BigDecimal correctAnswer = new BigDecimal(CorrectResult); double cAnswer; cAnswer = correctAnswer.doubleValue(); int temp = (int) Math.round(cAnswer * 1000); cAnswer = temp / 1000.0; String answer = String.valueOf(cAnswer); return answer; } }
package com.app.senior_calculator; import java.math.BigDecimal; import java.util.List; import java.util.Random; public class MidiumCreate { private MyCalculate calculate = new MyCalculate(); // 康取的生產演算法 by kanqu public String midiumCreate() { int a = 0;// 隨機數分子 int a2 = 1;// 隨機數分母 int b = 0; int b2 = 1; int c = 0; int c2 = 1; int e = 0; int d = 0; int f = 0; String op = ""; String op2 = ""; Random r = new Random(); a = r.nextInt(100) + 1; a2 = r.nextInt(100) + 1; b = r.nextInt(100) + 1; b2 = r.nextInt(100) + 1; c = r.nextInt(100) + 1; c2 = r.nextInt(100) + 1; d = r.nextInt(4) + 1; e = r.nextInt(4) + 5; f = r.nextInt(4) + 9; switch (d) { case 1: { op = "+" + ""; break; } case 2: { op = "-" + ""; break; } case 3: { op = "x" + ""; break; } case 4: { op = "/" + ""; break; } } switch (e) { case 5: { op2 = "+" + ""; break; } case 6: { op2 = "-" + ""; break; } case 7: { op2 = "x" + ""; break; } case 8: { op2 = "/" + ""; break; } } switch (f) { case 9: { return a + op + b + op2 + c; } case 10: { return "("+""+a + "/"+"" + a2 +")"+""+ op + b + op2 + c; } case 11: { return a + op + "("+"" +b + "/"+"" + b2 +")"+""+ op2 + c; } case 12: { return a + op + b + op2 + "(" + "" + c + "/" + "" + c2+")"+""; } } return ""; } // 傳參生產 public void midiumCreateInitation(int number, List<Question> question) { String questiontemp = ""; String answertemp = ""; for (int i = 0; i < number; i++) { questiontemp = midiumCreate(); calculate.setExpression(questiontemp); answertemp = calculate.getResult(); answertemp =adjustResult(answertemp); question.add(new Question(questiontemp, answertemp, i + 1)); /* Log.i("info", question.get(i).getExercise() + "=" + question.get(i).getAnswer() + " 第" + question.get(i).getCountNumber() + "題");*/ } } /** 比較答案的對錯,精度為0.001 **/ public String adjustResult(String CorrectResult) { BigDecimal correctAnswer = new BigDecimal(CorrectResult); double cAnswer; cAnswer = correctAnswer.doubleValue(); int temp = (int) Math.round(cAnswer * 1000); cAnswer = temp / 1000.0; String answer = String.valueOf(cAnswer); return answer; } }
package com.app.senior_calculator; import android.app.ActionBar; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.TextView; public class Score extends Activity{ private TextView right,wrong,score; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.score); ActionBar actionBar = getActionBar(); actionBar.show(); actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setDisplayShowHomeEnabled(true); right = (TextView) findViewById(R.id.rnumber); wrong = (TextView) findViewById(R.id.wnumber); score = (TextView) findViewById(R.id.score); Bundle bundle = new Bundle(); bundle = getIntent().getExtras(); right.setText(bundle.getString("rightnumber").toString()); wrong.setText(bundle.getString("wrongnumber").toString()); String temp =getScroe(bundle.getString("rightnumber").toString() , bundle.getString("wrongnumber").toString()); score.setText(temp); } public void onclick(View v ){ switch (v.getId()) { case R.id.Back: startActivity(new Intent (Score.this,APP.class)); break; case android.R.id.home: startActivity(new Intent(Score.this,TestView.class)); break; } } public String getScroe(String right , String wrong){ double rightnumber = Double.parseDouble(right); double wrongnumber = Double.parseDouble(wrong); double totalScore = (rightnumber/(rightnumber+wrongnumber ))*100; return String.valueOf(totalScore); } }
package com.app.senior_calculator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import android.annotation.SuppressLint; import android.app.ActionBar; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class TestView extends Activity { private boolean secondSubmit = false; /** 元件 **/ private Button preBtn, nextBtn, subBtn; private TextView CorrectAndWrong; // 對錯比例 private TextView wrongNumber; private TextView rightNumber; int total, right = 0, wrong = 0; private TextView noticeText;// 模式提醒. private TextView Explanation;// 錯題解析 private double[] userAnswer;// 使用者答案記錄. private TextView TiHao; private TextView Clock; int recleantime = 60; int minute = 9; /** 答錯題目之後顯示正確答案 **/ private EditText UserInput; /** 使用者輸入 **/ private String UserAnswer; /** 使用者題目答案 **/ private TextView userquestion; /** 使用者題目 **/ /** Counter 題號 兼顧 題目list的下標 **/ private int Counter = 0; private List<Question> TestTitle; boolean judge = false;// 判斷輸出未做題目的 題號. @SuppressWarnings("unchecked") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.testview); ActionBar actionBar = getActionBar(); actionBar.show(); actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setDisplayShowHomeEnabled(true); preBtn = (Button) findViewById(R.id.previous); nextBtn = (Button) findViewById(R.id.next); subBtn = (Button) findViewById(R.id.submitButton); preBtn.setEnabled(true); nextBtn.setEnabled(true); subBtn.setEnabled(true); CorrectAndWrong = (TextView) findViewById(R.id.CorrectAndWrong); wrongNumber = (TextView) findViewById(R.id.wrongNumber); rightNumber = (TextView) findViewById(R.id.rightNumber); noticeText = (TextView) findViewById(R.id.noticeText); Explanation = (TextView) findViewById(R.id.Explanation); Clock = (TextView) findViewById(R.id.tv_timer); Clock.setVisibility(0); TiHao = (TextView) findViewById(R.id.userQuestionNum); UserInput = (EditText) findViewById(R.id.useranswer); userquestion = (TextView) findViewById(R.id.userquestion); TestTitle = (List<Question>) this.getIntent().getSerializableExtra( "resource"); TiHao.setText("第" + TestTitle.get(Counter).getCountNumber() + "題"); userquestion.setText(TestTitle.get(Counter).getExercise()); Bundle temp = this.getIntent().getExtras(); total = TestTitle.size();// 總的題目數量 CorrectAndWrong.setText(right + "/" + total); userAnswer = new double[total]; for (int j = 0; j < total; j++) userAnswer[j] = 0.0; System.out.println("info" + temp.getString("difficulty")); if (temp.getString("difficulty").equals("Examination")) { noticeText.setText("\n這個模式是考試模式,在這個模式需要在 10 分鐘內做完25道題目。\n"); new Thread(new MyThread()).start(); } if (temp.getString("difficulty").equals("Practice")) { minute = 44; noticeText.setText("\n這個模式是練習模式,在這個模式需要在 45 分鐘內做完50道題目。\n"); new Thread(new MyThread()).start(); } } @SuppressLint("HandlerLeak") final Handler handler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case 1: if (recleantime == 0) { if (minute == 0) { // 處理時間到了之後的跳轉 ----一個dialog textView Clock.setText("00:00"); preBtn.setEnabled(false); nextBtn.setEnabled(false); subBtn.setEnabled(false); DialogType(); break; } recleantime = 59; minute--; } recleantime--; if (recleantime < 10)// 時間格式 00:00 { if (minute > 11) Clock.setText("" + minute + ":0" + recleantime); else Clock.setText("" + 0 + minute + ":0" + recleantime); } else { if (minute < 10) Clock.setText("" + 0 + minute + ":" + recleantime); else Clock.setText("" + minute + ":" + recleantime); } } super.handleMessage(msg); } }; class MyThread implements Runnable { @Override public void run() { while (true) { try { Thread.sleep(1000); Message message = new Message(); message.what = 1; handler.sendMessage(message); } catch (InterruptedException e) { e.printStackTrace(); } }// while 的右耳朵. } } /** 處理點選事件 上一題、下一題、以及提交 **/ public void onclick(View v) { switch (v.getId()) { // 注意處理 沒填寫答案提交的情況. case R.id.submitButton: if (subBtn.getText().equals("Submit")) { // 跳轉至一個評分介面! Toast.makeText(this, "finish !", Toast.LENGTH_LONG).show(); Intent intentScore = new Intent(TestView.this, Score.class); Bundle bundleScore = new Bundle(); bundleScore.putString("rightnumber", String.valueOf(right) .toString()); bundleScore.putString("wrongnumber", String.valueOf(wrong) .toString()); intentScore.putExtras(bundleScore); startActivity(intentScore); } else { if (!secondSubmit) { UserAnswer = UserInput.getText().toString(); // 正規表示式來判斷輸入的格式. Pattern pattern = Pattern .compile("^[-+]?[0-9]+(\\.[0-9]+)?$"); Matcher matcher = pattern.matcher(UserAnswer); while (!matcher.find()) { Toast.makeText(TestView.this, "Wrong format ", Toast.LENGTH_LONG).show(); subBtn.setEnabled(false); } if (matcher.find()) subBtn.setEnabled(true); double t = Double.parseDouble(TestTitle.get(Counter) .getAnswer()); double s = Double.parseDouble(UserAnswer); userAnswer[Counter] = s;// 對錯都記錄下來. if (t == s) { Toast.makeText(TestView.this, " Right ", Toast.LENGTH_SHORT).show(); right = right + 1; CorrectAndWrong.setText(right + "/" + total); rightNumber.setText("答對" + right + "題"); } else { wrong = wrong + 1; Explanation.setText(TestTitle.get(Counter) .getExercise() + " = " + TestTitle.get(Counter).getAnswer()); Toast.makeText(TestView.this, "Wrong ", Toast.LENGTH_SHORT).show(); wrongNumber.setText("答錯" + wrong + "題"); } secondSubmit = true; } else Toast.makeText(TestView.this, "已經提交了", Toast.LENGTH_SHORT) .show(); // 做到最後一題之後才會執行這個地方判斷是否可以提交試卷 String lack = "第"; int ifSubmit = 0; for (int j = 0; j < total; j++) if (userAnswer[j] == 0.0) { ifSubmit = j + 1; lack = lack + ifSubmit + "、"; } lack = lack + "題沒做."; if (ifSubmit == 0) { subBtn.setText("Submit"); } else if (Counter == TestTitle.size() - 1)// 只要曾經訪問過最後一題就開始提示未做完. judge = true; if (judge && ifSubmit != 0) Toast.makeText(this, lack, Toast.LENGTH_LONG).show(); } break; case R.id.next: Counter++; // Log.i("info", "" + Counter); if (Counter > TestTitle.size() - 1) { Toast.makeText(TestView.this, "已經是最後一題了 ", Toast.LENGTH_SHORT) .show(); Counter = Counter - 1; } else {// 在最後一題的時候點選下一題. secondSubmit = true; if (userAnswer[Counter] == 0) { secondSubmit = false; UserInput.setEnabled(true); UserInput.setText(""); } else { UserInput.setText(String.valueOf(userAnswer[Counter])); UserInput.setEnabled(false); } // System.out.println( String.valueOf(userAnswer[Counter]) ); TiHao.setText("第" + TestTitle.get(Counter).getCountNumber() + "題"); userquestion.setText(TestTitle.get(Counter).getExercise()); } Explanation.setText(""); break; case R.id.previous: Counter--; // Log.i("info", "" + Counter);在第一題的時候就點選上一題目 if (Counter < 0) { Toast.makeText(TestView.this, "已經是第一題了 ", Toast.LENGTH_SHORT) .show(); Counter = Counter + 1; } else { secondSubmit = true;// 切換題目時假設已經作答了,把提交按鈕置為false. 然後再判斷假設為真還是假 if (userAnswer[Counter] == 0) { secondSubmit = false; UserInput.setEnabled(true); UserInput.setText(""); } else { UserInput.setText(String.valueOf(userAnswer[Counter])); UserInput.setEnabled(false); } TiHao.setText("第" + TestTitle.get(Counter).getCountNumber() + "題"); /** 顯示題號 **/ userquestion.setText(TestTitle.get(Counter).getExercise()); /** 顯示題目 **/ } // UserInput.setText("");// 可以建立一個資料儲存使用者答案,返回時候可以檢視. Explanation.setText(""); break; } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: startActivity(new Intent(TestView.this, APP.class)); break; } return super.onOptionsItemSelected(item); } // 定義一個Dialog 提示時間到 public void DialogType() { Dialog TypeDialog; TypeDialog = new AlertDialog.Builder(this, R.style.dialog) .setTitle("Time out ! ") .setItems(R.array.Choice, new DialogInterface.OnClickListener() { public void onClick( DialogInterface dialoginterface, int select) { switch (select) { case 0: startActivity(new Intent(TestView.this, APP.class)); break; } } }).create(); TypeDialog.show(); } }
package com.app.senior_calculator; import java.math.BigDecimal; import java.util.EmptyStackException; import java.util.Stack; import android.util.Log; // 測試匹配否 // 特殊加減乘除 + - × ÷ // 特殊正負 ﹢﹣ // 普通加減乘除正負 + - * / + - public class MyCalculate { private static String expression; // 字尾式 private String suffix; // 特殊左括號 final static char LEFT_NORMAL = '('; // 特殊右括號 final static char RIGHT_NORMAL = ')'; // 特殊負號 final static char MINUS = '-'; // 特殊加號 final static char ADD = '+'; // 特殊乘法 final static char MUL = 'x'; // 特殊除法 final static char DIV = '/'; // 特殊減法 final static char SUB = '-'; // 特殊等於號 final static char equ = '='; public static String getExpression() { return expression; } // 返回字尾 public String getSuffix() { return suffix; } public void setExpression(String equation) { expression = equation; createSuffix(); } public MyCalculate(String equation) { expression = equation; createSuffix(); } public MyCalculate() { expression = ""; suffix = ""; } /** * 判斷括號有沒有匹配 * 匹配方法:遇到左括號進棧,遇到右括號出棧並且比對出棧的括號 * */ public boolean isBalanced() { Stack<Character> store = new Stack<Character>(); store.clear(); char c; for(int i=0; i<expression.length(); i++) { c = expression.charAt(i); switch(c) { case LEFT_NORMAL: { store.push(expression.charAt(i)); break; } case RIGHT_NORMAL: { if(store.isEmpty() || store.pop()!= LEFT_NORMAL) { return false; } break; } } } if(store.isEmpty()) { return true; } else { return false; } } // /** // * 判斷括號是否合法 ,前提這一步是在括號匹配的情況下才進行 // * 括號合法法則:左括號不能在算式最後一個位置,右括號不能在第一個位置, // * 左括號的位置的下一個位置上的字元不能為運算子, // * 右括號的位置的上一個位置上的字元不能為運算子。 // * @return // */ // public boolean bracketLegal() // { // String[] answer; // if(false == balanced) // { // return false; // } // String str = expression.trim(); // for(int index=0; index<str.length(); index++) // { // // if(str.charAt(index) == LEFT_NORMAL) // 左括號情況 // { // // char c = str.charAt(index+1); // if(!((index<str.length()-1) && // (isNum(c)))) // { // return false; // } // // }else if(str.charAt(index) == RIGHT_NORMAL) // 右括號情況 // { // // char c = str.charAt(index-1); // if(!(index>0 && isNum(c))) // { // return false; // } // // } // // } // return true; // } // // /** // * 運算子不能在第一個位置和最後一個位置 // * 而且運算子不能連著寫 例如:+- // * @return // */ // private boolean operatorLegal() // { // String str = expression.trim(); // for(int index=0; index<str.length(); index++) // { // if(isOperator(str.charAt(index))) // { // if(index==0 || index==(str.length()-1)) // { // return false; // } // if( !isNum(str.charAt(index-1)) && !isNum(str.charAt(index+1))) // { // return false; // } // // } // } // return true; // // } // private static boolean isOperator(char ope) { if(ope == ADD || ope==SUB ||ope == MUL || ope == DIV) { return true; } return false; } private static boolean isNum(char c) { if(c>='0' && c<='9') { return true; } return false; } // 中綴式轉字尾式 public String createSuffix() { Stack<String> stack = new Stack<String>(); String exp = expression.trim(); String suf = ""; int i = 0; char c; while(i < exp.length()) { c = exp.charAt(i); if(c == LEFT_NORMAL) // 左括號 { stack.push(LEFT_NORMAL+""); } else if(isFit(c)) // 符合數字的一部分 { String num = ""; while(i<exp.length() && isFit(exp.charAt(i)) ) { num+=exp.charAt(i); i++; } suf += (num + " "); //字尾 i--; }else if(c == ADD || c == SUB || c == MUL ||c == DIV) // 運算子 { while(true) { if(stack.isEmpty()) { break; } if(stack.peek().equals(""+LEFT_NORMAL)) { break; } if(compare(stack.peek().charAt(0),c)) { break; } suf += (stack.pop()+" "); // 字尾 } stack.push(c+""); } else if(c == RIGHT_NORMAL) { while(!stack.isEmpty()) { if(stack.peek().equals(""+LEFT_NORMAL)) { stack.pop(); break; } suf += (stack.pop() + " "); // 字尾 } } i++; } while(!stack.isEmpty()) { suf += (stack.pop() + " "); // 字尾 } this.suffix = suf; return suf; } /** * 判斷是否符合數字的一部分 * @param digit * @return 符合返回true 否則返回false */ private boolean isFit(char digit) { if(digit>='0' && digit<='9'||digit ==MINUS||digit=='.' ) { return true; } return false; } // 棧中運算子與將要讀取的運算子作比較 // 返回true指示棧中運算子優先順序大於將要讀取運算子 // 其他的低於或等於都返回false private boolean compare(char stackOpe, char nextOpe) { int v1 = value(stackOpe); int v2 = value(nextOpe); if( v1 < v2) { return true; } return false; } // 運算子優先順序 private int value(char ope) { if(ope==ADD || ope==SUB) { return 1; } else if(ope==MUL || ope==DIV) { return 2; } else { return 0; } } /** * @param suffix 字尾式 * @return 利用字尾式算出結果 */ public String getResult() { suffix = suffix.replace(MINUS, '-'); String[] str = suffix.split(" "); Stack<String> valueStack = new Stack<String>(); for(int i=0; i<str.length; i++) { // 遇到運算子出棧 if(str[i].equals(ADD+"") || str[i].equals(SUB+"") || str[i].equals(MUL+"") || str[i].equals(DIV+"")) { String rightNum; String leftNum; try { rightNum = valueStack.pop(); leftNum = valueStack.pop(); String result = calc(leftNum,rightNum,str[i]); valueStack.push(result); }catch(EmptyStackException empty) { return "算式出現異常"; } } else { // 遇到數字進棧 valueStack.push(str[i]); } } if(!valueStack.isEmpty()) { return valueStack.pop(); } return "棧為空 ,出現錯誤!"; } public static String calc(String leftNum, String rightNum, String ope) { BigDecimal bigLeftNum = null; BigDecimal bigRightnum = null; try { bigLeftNum = new BigDecimal(leftNum); bigRightnum = new BigDecimal(rightNum); }catch(NumberFormatException e) { return "算式出現異常"; } switch(ope.charAt(0)) { // 處理加法 case ADD:return bigLeftNum.add(bigRightnum).toString(); // 處理減法 case SUB:return bigLeftNum.subtract(bigRightnum).toString(); // 處理乘法 case MUL:return bigLeftNum.multiply(bigRightnum).toString(); // 處理乘法 case DIV: { if(bigRightnum.doubleValue()==0) { return "除數為零"; } // 20為小數點後的位數 String result = bigLeftNum.divide(bigRightnum,20,BigDecimal.ROUND_DOWN).toString(); int mark = 0; if( (mark = result.indexOf('.'))!=-1) { for(int i=mark; i<result.length(); i++) { if(result.charAt(i)!='0') { mark = i; } } Log.d("mark--1 :", mark+""); if(result.charAt(mark)=='.') { mark -= 1; } Log.d("mark--2 :", mark+""); Log.d("result", result.substring(0,mark+1)); result = result.substring(0,mark+1); return result; } else { return result; } } } return null; } // 測試括號匹配 - — public static void main(String[] s) { String str1 = "﹙5.3+3﹚×﹙3+8﹚"; String str2 = "[{}]{}"; String str3 = "({}{})"; String str4 = "16.2+(6.72-4.25)-3.72"; String str5 = "(((10+7)*(20/30))-(2*40))"; String str6 = "12"; MyCalculate cal = new MyCalculate(str1); System.out.println("匹配:"+cal.isBalanced()); System.out.println("字尾:"+cal.getSuffix()); String reult = cal.getResult(); System.out.println("結果: "+reult); } }
package com.app.senior_calculator; import java.io.Serializable; public class Question implements Serializable{ static final long serialVersionUID = -4320724374354337825L; private String Exercise; private String Answer; private int CountNumber; public Question(String exercise,String answer, int countNumber) { this.Answer=answer; this.Exercise=exercise; this.CountNumber=countNumber; } public Question() { this.Exercise=""; this.Answer=""; this.CountNumber=0; } public String getExercise() { return Exercise; } public void setExercise(String exercise) { this.Exercise = exercise; } public String getAnswer() { return Answer; } public void setAnswer(String answer) { Answer = answer; } public int getCountNumber() { return CountNumber; } public void setCountNumber(int countNumber) { CountNumber = countNumber; } }
package com.app.senior_calculator; import java.math.BigDecimal; import java.util.List; import java.util.Random; public class CreateEFraction { private MyCalculate calculator = new MyCalculate(); public void createYouExercisess(int number, List<Question> question) { for (int i = 0; i < number; i++) { String timu = createOperation(); calculator.setExpression(timu); String daan = calculator.getResult(); daan = adjustResult(daan); question.add(new Question(timu, daan, i + 1)); // Log.i("info", question.get(i).getExercise() + "=" // + question.get(i).getAnswer() + " 第" // +question.get(i).getCountNumber()+"題"); } } /** 比較答案的對錯,精度為0.001 **/ public String adjustResult(String CorrectResult) { BigDecimal correctAnswer = new BigDecimal(CorrectResult); double cAnswer; cAnswer = correctAnswer.doubleValue(); int temp = (int) Math.round(cAnswer * 1000); cAnswer = temp / 1000.0; String answer = String.valueOf(cAnswer); return answer; } public String createOperation() { Random seed = new Random(); final String ADD = "+" + ""; final String MINUS = "-" + ""; final String MULTIPLY = "x" + ""; final String DEVIDE = "/" + ""; // 運算元的個數.而且最多為五個,預設三個運算元 int number = 3; String datas[] = new String[5]; String op[] = new String[5]; /** 生成 運算元個數 **/ int numberSeeder = seed.nextInt(4) + 1; if (numberSeeder == 1) number = 3; else if (numberSeeder == 2 || numberSeeder == 4) number = 4; else if (numberSeeder == 3) number = 5; /** 生成 運算元 跟 符號 **/ for (int i = 0; i < number; i++) { int jud = seed.nextInt(100); if (jud < 20) { datas[i] = fraction(); } else if (jud < 100) { datas[i] = integerCreater(); } if (i < number - 1) { /** 運算元的個數都是比符號的個數多一個 **/ int judp = seed.nextInt(4) + 1; if (judp == 1) op[i] = ADD; else if (judp == 2) op[i] = MINUS; else if (judp == 3) op[i] = MULTIPLY; else if (judp == 4) op[i] = DEVIDE; } } return createBrackets(datas, op, number); } /** create an integer **/ public String integerCreater() { Random seed = new Random(); String data; data = String.valueOf(seed.nextInt(100) + 1); return data; } /** create a fraction **/ public String fraction() { final String DEVIDE = "/" + ""; final String leftear = "(" + ""; final String rightear = ")" + ""; int First = 1, second = 1; Random seeder = new Random(); First = seeder.nextInt(10) + 1;// 分子 second = seeder.nextInt(10) + 1;// 分母 return leftear + First + DEVIDE + second + rightear; } /** brackets block 運算元據陣列 、 操作符 、 個數 **/ public String createBrackets(String datas[], String operator[], int number) { final String leftear = "(" + ""; final String rightear = ")" + ""; Random seeder = new Random(); String bracketOperation = null; switch (number) { case 3: if (seeder.nextInt() / 2 == 0) bracketOperation = leftear + datas[0] + operator[0] + datas[1] + rightear + operator[1] + datas[2]; else bracketOperation = datas[0] + operator[0] + leftear + datas[1] + operator[1] + datas[2] + rightear; break; case 4: int temp = seeder.nextInt(21) + 1; temp = temp % 7 + 1; switch (temp) { case 1:// (a+b)x(a+b) bracketOperation = leftear + datas[0] + operator[0] + datas[1] + rightear + operator[1] + leftear + datas[2] + operator[2] + datas[3] + rightear; break; case 2:// ((a+b)+b)+b bracketOperation = leftear + leftear + datas[0] + operator[0] + datas[1] + rightear + operator[1] + datas[2] + rightear + operator[2] + datas[3]; break; case 3:// (a+(a+b))+b bracketOperation = leftear + datas[0] + operator[0] + leftear + datas[1] + operator[1] + datas[2] + rightear + rightear + operator[2] + datas[3]; break; case 4:// (a+b)+a+b bracketOperation = leftear + datas[0] + operator[0] + datas[1] + rightear + operator[1] + datas[2] + operator[2] + datas[3]; break; case 5:// a+b+(a+b) bracketOperation = datas[0] + operator[0] + datas[1] + operator[1] + leftear + datas[2] + operator[2] + datas[3] + rightear; break; case 6:// a+(a+b)+b bracketOperation = datas[0] + operator[0] + leftear + datas[1] + operator[1] + datas[2] + rightear + operator[2] + datas[3]; break; case 7:// (a+b+c)+a bracketOperation = leftear + datas[0] + operator[0] + datas[1] + operator[1] + datas[2] + rightear + operator[2] + datas[3]; break; } break; case 5: int dicision = seeder.nextInt(33) + 1; dicision = dicision % 9 + 1; switch (dicision) { case 1:// (a+(a+b))+a+b bracketOperation = leftear + datas[0] + operator[0] + leftear + datas[1] + operator[1] + datas[2] + rightear + rightear + operator[2] + datas[3] + operator[3] + datas[4]; break; case 2:// ((a+b)+a)+a+a bracketOperation = leftear + leftear + datas[0] + operator[0] + datas[1] + rightear + operator[1] + datas[2] + rightear + operator[2] + datas[3] + operator[3] + datas[4]; break; case 3:// (a+b)x(a+b)+a bracketOperation = leftear + datas[0] + operator[0] + datas[1] + rightear + operator[1] + leftear + datas[2] + operator[2] + datas[3] + rightear + operator[3] + datas[4]; break; case 4:// (a+b)x(a+b+a) bracketOperation = leftear + datas[0] + operator[0] + datas[1] + rightear + operator[1] + leftear + datas[2] + operator[2] + datas[3] + operator[3] + datas[4] + rightear; break; case 5:// (a+b)x(a+b+c) bracketOperation = leftear + datas[0] + operator[0] + datas[1] + rightear + operator[1] + leftear + datas[2] + operator[2] + datas[3] + operator[3] + datas[4] + rightear; break; case 6:// (a+b)+a+(a+b) bracketOperation = leftear + datas[0] + operator[0] + datas[1] + rightear + operator[1] + datas[2] + operator[2] + leftear + datas[3] + operator[3] + datas[4] + rightear; break; case 7:// ((a+b)+a)X(a+b) bracketOperation = leftear + leftear + datas[0] + operator[0] + datas[1] + rightear + operator[1] + datas[2] + rightear + operator[2] + leftear + datas[3] + operator[3] + datas[4] + rightear; break; case 8:// (((a+b)+c)+d)+e bracketOperation = leftear + leftear + leftear + datas[0] + operator[0] + datas[1] + rightear + operator[1] + datas[2] + rightear + operator[2] + datas[3] + rightear + operator[3] + datas[4]; break; case 9:// a+(a+b+c)+e bracketOperation = datas[0] + operator[0] + leftear + datas[1] + operator[1] + datas[2] + operator[2] + datas[3] + rightear + operator[3] + datas[4]; break; } break; } return bracketOperation; } }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".APP" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:background="@drawable/b1" android:gravity="center" android:orientation="vertical" > <Button android:id="@+id/Help" android:layout_width="140dp" android:layout_height="55dp" android:background="@drawable/button_selector" android:onClick="onclick" android:text="@string/help_text" android:textSize="30sp" /> <Button android:id="@+id/StartTest" android:layout_width="140dp" android:layout_height="55dp" android:layout_marginTop="15dp" android:background="@drawable/button_selector" android:onClick="onclick" android:text="@string/Start_Text" android:textSize="30sp" /> <Button android:id="@+id/Medol" android:layout_width="140dp" android:layout_height="55dp" android:background="@drawable/button_selector" android:onClick="onclick" android:text="@string/Model_Text" android:textSize="30sp" android:layout_marginTop="15dp"/> <Button android:id="@+id/Exit" android:layout_width="140dp" android:layout_height="55dp" android:layout_marginTop="15dp" android:background="@drawable/button_selector" android:onClick="onclick" android:text="@string/Special_Text" android:textSize="30sp" /> </LinearLayout> </RelativeLayout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:background="@drawable/tbg"> <Button android:id="@+id/submitButton" style="?android:attr/borderlessButtonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:onClick="onclick" android:text="@string/userSubmitText" /> <RelativeLayout android:id="@+id/relativeLayout1" android:layout_width="fill_parent" android:layout_height="35dp" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:background="@drawable/button_selector" > <TextView android:id="@+id/tv_timer " android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:drawableLeft="@drawable/clock_gray" android:drawablePadding="2dp" android:gravity="center" android:text="@string/TimeText0000" android:textColor="@color/black" android:textStyle="bold" /> <TextView android:id="@+id/CorrectAndWrong" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/tv_timer " android:layout_alignBottom="@+id/tv_timer " android:layout_alignParentRight="true" android:layout_marginRight="10dp" android:text="@string/rightandwrongText" android:textColor="@color/black" android:textStyle="bold" /> <TextView android:id="@+id/userQuestionNum" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/tv_timer " android:layout_alignParentLeft="true" android:layout_marginLeft="10dp" android:text="@string/questionnumberText" android:textColor="@color/black" android:textStyle="bold" /> </RelativeLayout> <Button android:id="@+id/next" style="?android:attr/borderlessButtonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:onClick="onclick" android:text="@string/nextButtonText" /> <Button android:id="@+id/previous" style="?android:attr/borderlessButtonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:onClick="onclick" android:text="@string/previousButtonText" /> <TextView android:id="@+id/noticeText" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@+id/relativeLayout1" android:ems="10" android:gravity="center" /> <TextView android:id="@+id/Explanation" android:layout_width="fill_parent" android:layout_height="90dp" android:layout_alignParentLeft="true" android:layout_below="@+id/useranswer" android:layout_marginTop="28dp" android:background="@drawable/button_selector" android:ems="10" android:gravity="center" android:hint="@string/explainationText" /> <TextView android:id="@+id/userquestion" android:layout_width="fill_parent" android:layout_height="60dp" android:layout_alignParentLeft="true" android:layout_below="@+id/noticeText" android:layout_marginTop="14dp" android:ems="10" android:gravity="center" android:hint="@string/questionText" /> <TextView android:id="@+id/wrongNumber" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/next" android:layout_alignLeft="@+id/next" android:text="@string/wrongText" android:textColor="@color/black" android:textStyle="bold" /> <EditText android:id="@+id/useranswer" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@+id/userquestion" android:layout_marginTop="46dp" android:background="@drawable/button_selector" android:ems="10" android:gravity="center" android:hint="@string/userInputTips" /> <TextView android:id="@+id/userEqual" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/userquestion" android:layout_centerHorizontal="true" android:text="@string/equalText" android:textSize="30sp" /> <TextView android:id="@+id/rightNumber" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/submitButton" android:layout_toRightOf="@+id/submitButton" android:text="@string/rightText" android:textColor="@color/black" android:textStyle="bold" /> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/bg" > <TextView android:id="@+id/wrong" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginRight="72dp" android:layout_marginTop="79dp" android:text="@string/wrongText" /> <TextView android:gravity="center" android:id="@+id/theEndtext" android:layout_width="fill_parent" android:layout_height="40dp" android:text="@string/terminalText" /> <TextView android:id="@+id/rnumber" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/wrong" android:layout_below="@+id/wrong" android:layout_marginTop="40dp" android:text="@string/rightandwrongText" /> <TextView android:layout_marginLeft="20dp" android:id="@+id/ToatlText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:text="@string/scoreText" /> <Button android:id="@+id/Back" android:onClick="onclick" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/score" android:layout_centerHorizontal="true" android:layout_marginTop="52dp" android:background="@drawable/button_selector" android:text="@string/userSubmitText" /> <TextView android:id="@+id/wnumber" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/rnumber" android:layout_alignBottom="@+id/rnumber" android:layout_alignRight="@+id/right" android:text="@string/rightandwrongText" /> <TextView android:id="@+id/right" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/wrong" android:layout_alignBottom="@+id/wrong" android:layout_marginRight="24dp" android:layout_toLeftOf="@+id/Back" android:text="@string/rightText" /> <TextView android:id="@+id/score" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignRight="@+id/Back" android:layout_below="@+id/ToatlText" android:text="@string/rightandwrongText" /> </RelativeLayout>
APP執行截圖;
主介面
選擇難度
選擇模式
答題介面
答題答對介面
答題答錯介面
考試結束介面
計時結束後
團隊 github 是:https://github.com/be821/MyCat 裡面的little_four_operation就是該專案的程式碼.
心得總結;
這次的課程設計比上學期的好很多,畢竟這學期有一門專門學習Android的課程,當然基於源頭,都是JAVA語言,所以每一門課程之間的聯絡很緊密。
我們班大部分都是做四則運算APP,我們也有去了解其他組的功能,我們也有我們的考慮,我們側重於APP的實用性和簡潔性,比如背景音樂功能,我覺得使用者做題需要思考,背景音樂華而不實。還有錯題冊功能,四則運算是基礎運算,個人覺得沒必要弄一個錯題本,本身APP是隨機出題,鍛鍊的是使用者第一時間的計算邏輯能力,如果反覆的做錯題,意義不大。
我們團隊的APP,解決了助教所說的帶有括號的四則運算,判斷運算的優先順序,感謝我們的隊員陳健同學。讓我們的APP上升了一個檔次。在團隊開發的過程中,我也學到了很多。用部落格園記錄APP開發歷程似乎是一種習慣了,感謝杜雲梅老師。 github這個也是第一次接觸,開闊了視野,長了見識。