團隊成員: 我:陳俊達 201421122076
夥伴:林仙平 201421122079
需求分析:
1、在作業1的基礎上加入GUI。
2、記錄使用者的對錯總數,程式退出再啟動的時候,能把以前的對錯數量儲存并在此基礎上增量計算。
3、有計時功能,能顯示使用者開始答題後的消耗時間。
4、使用者可以根據自己需要選擇語言(隻有中文簡體與英文兩種可選)。
思維導圖:

package GUI;
public class CountExp {
//計算表達式答案
public static String countAnswer(String exp) {
int result = 0;
int a1 = 0, a2 = 0;
int b = 0;// 為0說明符号後面的數為負數,1 為正數
int bb = 0;// 符号後面的數字長度-1
int w = 0;// w用來表示符号前面打數字打位數-1
int ww = 0;// ww為0說明算術符号前面的數是正數,為1說明是負數
String exp1 = "";// 接收去括号後的表達式
String exp2 = "";// 接收去乘除号後打表達式
String exp3 = "";// 用來接收分數
// 去括号
for (int i = 0; i < exp.length(); i++) {
if (exp.charAt(i) == '(') {
int i1 = 0;
int i2 = 0;
// 判斷算術符号前面的數是否多位
if (exp.charAt(i + 2) != '-' && exp.charAt(i + 2) != '+') {
i1 = i1 + 1;
if (exp.charAt(i + 3) != '-' && exp.charAt(i + 3) != '+')
i1 = i1 + 1;
}
// 判斷算術符号後面的數是否多位
if (exp.charAt(i + i1 + 4) != ')') {
i2 = i2 + 1;
if (exp.length() > (i + i1 + 5)
&& exp.charAt(i + i1 + 5) != ')')
i2 = i2 + 1;
}
a1 = Integer.parseInt(exp.substring(i + 1, i + 2 + i1));
a2 = Integer.parseInt(exp
.substring(i + 3 + i1, i + 4 + i1 + i2));
if (exp.charAt(i + 2) == '+')
exp1 = exp1 + (a1 + a2);
else
exp1 = exp1 + (a1 - a2);
i = i + 4 + i1 + i2;
} else
exp1 = exp1 + exp.charAt(i);
}
// 循環先算公式裡的乘跟除
for (int j = 0; j < exp1.length(); j++) {
if (exp1.charAt(j) == '*') {
w = 0;// w用來表示符号前面打數字的位數-1
ww = 0;// ww為0說明算術符号前面的數是正數,為1說明是負數
if ((j - 2) > 0 && exp1.charAt(j - 2) != '-'
&& exp1.charAt(j - 2) != '+'
&& exp1.charAt(j - 2) != '*'
&& exp1.charAt(j - 2) != '÷') {
w = w + 1;
if ((j - 2 - w) > 0 && exp1.charAt(j - 2 - w) != '-'
&& exp1.charAt(j - 2 - w) != '+'
&& exp1.charAt(j - 2) != '*'
&& exp1.charAt(j - 2) != '÷')
w = w + 1;
}
if ((j - 2 - w) > 0
&& exp1.charAt(j - 2 - w) == '-'
&& ((j - 3 - w) > 0 && exp1.charAt(j - 3 - w) == '-' || (exp1
.charAt(j - 3 - w) == '+')))
ww = ww + 1;
a1 = Integer.parseInt(exp1.substring(j - w - 1, j));
if (ww == 1)
a1 = 0 - a1;
b = 0;// 為0說明符号後面的數為負數,1 為正數
bb = 0;// 符号後面的數字長度-1
// 判斷算術符号後面的數是否是負數
if (exp1.charAt(j + 1) == '-')
b = b + 1;
// 判斷算術符号後面的數是否多餘一位
if (exp1.length() > (j + 2 + b)
&& (exp1.charAt(j + 2 + b) != '-'
&& exp1.charAt(j + 2 + b) != '+'
&& exp1.charAt(j + 2 + b) != '*' && exp1
.charAt(j + 2 + b) != '÷')) {
bb = bb + 1;
if (exp1.length() > (j + 3 + b)
&& (exp1.charAt(j + 3 + b) != '-'
&& exp1.charAt(j + 3 + b) != '+'
&& exp1.charAt(j + 3 + b) != '*' && exp1
.charAt(j + 3 + b) != '÷'))
bb = bb + 1;
}
a2 = Integer
.parseInt(exp1.substring(j + 1 + b, j + 2 + b + bb));
if (b == 1)
a2 = 0 - a2;
exp2 = exp2.substring(0, j - 1 - w - ww);
exp2 = exp2 + (a1 * a2);
exp2 = exp2 + exp1.substring(j + 2 + b + bb, exp1.length());
exp1 = exp2;
exp2 = "";
j = -1;
continue;
} else if (exp1.charAt(j) == '÷') {// 遇到除号 ,則進行除法運算,結果為分數
w = 0;// w用來表示符号前面打數字打位數-1
ww = 0;// ww為0說明算術符号前面的數是正數,為1說明是負數
if ((j - 2) > 0 && exp1.charAt(j - 2) != '-'
&& exp1.charAt(j - 2) != '+') {
w = w + 1;
if (exp1.charAt(j - 2 - w) != '-'
&& exp1.charAt(j - 2 - w) != '+')
w = w + 1;
}
if ((j - 2 - w) > 0
&& exp1.charAt(j - 2 - w) == '-'
&& (exp1.charAt(j - 3 - w) == '-' || (exp1.charAt(j - 3
- w) == '+')))
ww = ww + 1;
a1 = Integer.parseInt(exp1.substring(j - w - 1, j));
b = 0;// 為0說明符号後面的數為負數,1 為正數
bb = 0;// 符号後面的數字長度-1
// 判斷算術符号後面的數是否是負數
if (exp1.charAt(j + 1) == '-')
b = b + 1;
// 判斷算術符号後面的數是否多餘一位
if (exp1.length() > (j + 2 + b)
&& (exp1.charAt(j + 2 + b) != '-'
&& exp1.charAt(j + 2 + b) != '+'
&& exp1.charAt(j + 2 + b) != '*' && exp1
.charAt(j + 2 + b) != '÷')) {
bb = bb + 1;
if (exp1.length() > (j + 3 + b)
&& (exp1.charAt(j + 3 + b) != '-'
&& exp1.charAt(j + 3 + b) != '+'
&& exp1.charAt(j + 3 + b) != '*' && exp1
.charAt(j + 3 + b) != '÷'))
bb = bb + 1;
}
a2 = Integer
.parseInt(exp1.substring(j + 1 + b, j + 2 + b + bb));
if (a1 % a2 == 0) {
exp2 = "" + (a1 / a2);
return exp2;
} else if (a1 < a2) {
exp2 = "" + a1 + "/" + a2;
return exp2;
} else {
int e1 = a1 / a2;
int e2 = a1 - a2 * e1;
exp2 = "" + e1 + "’" + e2 + "/" + a2;
return exp2;
}
} else
exp2 = exp2 + exp1.charAt(j);
}
int fs = 10;// 用來記錄表達式括号的位置
// 進行加減運算
for (int xx = 0; xx < exp2.length(); xx++) {
if (exp2.charAt(xx) == '/')
fs = xx;
}
int aa = 0;// 用來暫a1,a2的值
if (fs == 10) {
for (int fss = 1; fss < exp2.length(); fss++) {
if (exp2.charAt(fss) == '+') {
b = 0;// 符号後面的數字長度-1
bb = 0;// 為0說明符号後面的數為負數,1 為正數
w = 0;// w用來表示符号前面打數字打位數-1
ww = 0;// ww為0說明算術符号前面的數是正數,為1說明是負數
if (exp2.charAt(0) == '-')
bb = bb + 1;
b = fss - bb;
a1 = Integer.parseInt(exp2.substring(0, fss));
if ((fss + 2) < exp2.length()
&& exp2.charAt(fss + 2) != '+'
&& exp2.charAt(fss + 2) != '-') {
w = w + 1;
if ((fss + 3) < exp2.length()
&& exp2.charAt(fss + 3) != '+'
&& exp2.charAt(fss + 3) != '-') {
w = w + 1;
if ((fss + 4) < exp2.length()
&& exp2.charAt(fss + 4) != '+'
&& exp2.charAt(fss + 4) != '-') {
w = w + 1;
}
}
}
a2 = Integer.parseInt(exp2.substring(fss + 1, fss + 2 + ww
+ w));
exp2 = (a2 + a1)
+ exp2.substring(fss + 2 + w + ww, exp2.length());
fss = 0;
if (exp.length() < 2)
break;
} else if (exp2.charAt(fss) == '-') {
if ((fss < exp.length()) && exp2.charAt(fss) == '-') {
b = 0;// 符号後面的數字長度-1
bb = 0;// 為0說明符号後面的數為負數,1 為正數
w = 0;// w用來表示符号前面打數字打位數-1
ww = 0;// ww為0說明算術符号前面的數是正數,為1說明是負數
if (exp2.charAt(0) == '-')
bb = bb + 1;
b = fss - bb;
a1 = Integer.parseInt(exp2.substring(0, fss));
if (exp2.charAt(fss + 1) == '-')
ww = ww + 1;
if ((fss + 2 + ww) < exp2.length()
&& exp2.charAt(fss + 2 + ww) != '+'
&& exp2.charAt(fss + 2 + ww) != '-') {
w = w + 1;
if ((fss + 3 + ww) < exp2.length()
&& exp2.charAt(fss + 3 + ww) != '+'
&& exp2.charAt(fss + 3 + ww) != '-')
w = w + 1;
}
a2 = Integer.parseInt(exp2.substring(fss + 1 + ww, fss
+ 2 + ww + w));
exp2 = (a1 - a2)
+ exp2.substring(fss + 2 + w + ww,
exp2.length());
fss = 0;
if (exp.length() < 2)
break;
}
}
}
}
return exp2;
}
}
package GUI;
import java.util.Random;
public class CreateExp {
public static String CreateAtith(int r1, int leval) {
Random random = new Random();
String[] array = { "+", "-", "*", "÷" };
String exp = "";
int f;// 符号個數
if (leval == 0) {
f = 1;
} else {
f = random.nextInt(2) + 2;
}
int w = 5;
int s = 0;
int ff = 0;
int m = 4;
if (f > 1) {
w = random.nextInt(f);// 随機一個符号生成的位置
}
ff = random.nextInt(m);
if (w == 0 && ff < 2) {
exp = exp + ('(');
s++;
}
exp = exp + (random.nextInt(r1) + 1);
for (int i = 0; i < f; i++) {
exp = exp + (array[ff]);
if (ff > 2)
i = 5;
m = 3;
ff = random.nextInt(m);
// 判斷加括号打位置,如果後面符号為"*", "÷",則不加括号
if (s == 0 && i == (w - 1) && ff < 2) {
exp = exp + ('(');
s++;
}
exp = exp + (random.nextInt(r1) + 1);
if (s == 1 && i == w) {
exp = exp + (')');
s++;
}
}
return exp;
}
}
package GUI;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
public class FileInOut {
// 擷取曆史記錄,傳回數組第1個是對的題數,第2個是錯的題數
public int[] getrecord() throws IOException {
int[] arr = new int[2];
String[] strRead = new String[3];
File userinfo = new File("Record.txt");
try {
InputStream in = new FileInputStream(userinfo);// 檔案對象
InputStreamReader read;
read = new InputStreamReader(in, "GBK");// 設定讀取格式
BufferedReader reader = new BufferedReader(read);
for (int i = 0; i < 3; i++) {
strRead[i] = reader.readLine();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
System.out.println("讀檔案入出錯");
}
arr[0] = Integer.parseInt(strRead[1]);
arr[1] = Integer.parseInt(strRead[2]);
return arr;
}
// 重寫記錄檔案Record.txt
public void recompose(int[] in) {
try {
FileOutputStream out = new FileOutputStream("Record.txt");
OutputStreamWriter outWriter = new OutputStreamWriter(out, "GBK");
BufferedWriter bufWrite = new BufferedWriter(outWriter);
bufWrite.write("對錯記錄:第二行是對的題數、第三行是錯的題數\r\n");
for (int i = 0; i < in.length; i++)
bufWrite.write(in[i] + "\r\n");
bufWrite.close();
outWriter.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
System.out.println("寫入出錯");
}
}
}
package GUI;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
//主視窗
public class GUIcalculator extends JFrame implements ActionListener {
int language;// 記錄選擇的語言
JTextArea quesNumJTA = new JTextArea(1, 10);
JTextArea answerJTA = new JTextArea(1, 10);
JPanel panel = new JPanel();
JPanel languageChoJP = new JPanel();
JPanel quseNumJP = new JPanel();
JPanel difficultyChooseJP = new JPanel();
JPanel answerJP = new JPanel();
JPanel nextJP = new JPanel();
JPanel countJP = new JPanel();
JPanel warningJP = new JPanel();
JLabel numQuizJL = new JLabel("how many questions u want test?");
JLabel difficultyQuizJL = new JLabel("easy or difficult?");
JLabel showQuestionJL = new JLabel();// 放題目label
JLabel resultJudgeJL = new JLabel();
JLabel showCountJL = new JLabel();
JLabel warningJL = new JLabel();
JButton sureJB = new JButton("sure");
JButton easyJB = new JButton("easy");
JButton difficultJB = new JButton("difficult");
JButton nextJB = new JButton("next");
JButton submitJB = new JButton("submit");
JButton reenterJB = new JButton("reenter");
JButton chineseJB = new JButton("中文");
JButton englishJB = new JButton("English");
int trueCount = 0;// 正确題數
int failCount = 0;// 錯誤題數
String questNum;// 題目數量String類型
int expNum;// 題目數量int類型
int explevel;// 記錄表達式難度級别
int expdone = 1;//
int done = 0;//記錄已經計算的題目
long startTime;//結束時間
long endTime;//開始時間
CreateExp create = new CreateExp();//
CountExp count = new CountExp();//
String[] exparr = null;// 放題目的數組
String[] expanswer = null;// 放答案的數組
// 主界面
public GUIcalculator() {
super("四則運算");
setSize(500, 500);
setLocation(450, 350);
super.setResizable(false);
// 放題目的控件
quesNumJTA.setText("");
answerJTA.setText("");
sureJB.setActionCommand("sure");
sureJB.addActionListener(this);
easyJB.setActionCommand("easy");
easyJB.addActionListener(this);
difficultJB.setActionCommand("difficult");
difficultJB.addActionListener(this);
nextJB.setActionCommand("next");
nextJB.addActionListener(this);
submitJB.setActionCommand("submit");
submitJB.addActionListener(this);
reenterJB.setActionCommand("reenter");
reenterJB.addActionListener(this);
chineseJB.setActionCommand("chinese");
chineseJB.addActionListener(this);
englishJB.setActionCommand("english");
englishJB.addActionListener(this);
languageChoJP.add(chineseJB);
languageChoJP.add(englishJB);
// 題目 +答案框+确定按鈕
quseNumJP.add(numQuizJL);
quseNumJP.add(quesNumJTA);
quseNumJP.add(sureJB);
getContentPane().add(panel);
panel.add(languageChoJP);
difficultyChooseJP.add(difficultyQuizJL);
difficultyChooseJP.add(easyJB);
difficultyChooseJP.add(difficultJB);
answerJP.add(showQuestionJL);
answerJP.add(answerJTA);
answerJP.add(submitJB);
nextJP.add(resultJudgeJL);
nextJP.add(nextJB);
countJP.add(showCountJL);
warningJP.add(warningJL);
warningJP.add(reenterJB);
}
// 重繪視窗
public void panelRepaint(JPanel a, JPanel b, JPanel c) {
a.remove(b);
a.add(c);
a.revalidate();
a.repaint();
}
// 點選事件
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("chinese")) {// 設定控件文字為中文
language = 0;
numQuizJL.setText("你想測試多少題?");
difficultyQuizJL.setText("你想測試的難易程度?");
warningJL.setText("請輸入一個大于0的整數!!");
sureJB.setText("确定");
easyJB.setText("容易");
difficultJB.setText("難");
nextJB.setText("繼續");
submitJB.setText("送出");
reenterJB.setText("重新輸入");
panelRepaint(panel, languageChoJP, quseNumJP);
}
// 設定控件文字為英文
if (e.getActionCommand().equals("english")) {
language = 1;
numQuizJL.setText("how many questions u want test?");
difficultyQuizJL.setText("easy or difficult?");
warningJL.setText("please enter a number greater than 0!!");
sureJB.setText("sure");
easyJB.setText("easy");
difficultJB.setText("difficult");
nextJB.setText("next");
submitJB.setText("subnit");
reenterJB.setText("reenter");
panelRepaint(panel, languageChoJP, quseNumJP);
}
// 點确定,确定題目數量
if (e.getActionCommand().equals("sure")) {
this.questNum = quesNumJTA.getText();// 記錄題目數量
this.expNum = Integer.parseInt(questNum);
if (!questNum.matches("[0-9]*[1-9][0-9]*")) {// 比對輸入的是否有錯誤
panelRepaint(panel, quseNumJP, warningJP);
} else {
panelRepaint(panel, quseNumJP, difficultyChooseJP);
}
}
// 點容易,确定題目難度為容易,
if (e.getActionCommand().equals("easy")) {
startTime = System.currentTimeMillis();// 記錄開始時間
exparr = new String[expNum+1];
expanswer = new String[expNum+1];
// 循環生成題目和答案
for (int j = 0; j < expNum; j++) {
String expression = create.CreateAtith(9,0);
exparr[j] = expression;
expanswer[j] = count.countAnswer(expression);
System.out.print(expression + "=");
System.out.println(count.countAnswer(expression));
}
showQuestionJL.setText(exparr[done]);
panelRepaint(panel, difficultyChooseJP, answerJP);
}
// 點困難,确定題目難度為困難
if (e.getActionCommand().equals("difficult")) {
startTime = System.currentTimeMillis();
exparr = new String[expNum+1];
expanswer = new String[expNum+1];
// 循環生成題目和答案
for (int j = 0; j < expNum; j++) {
String expression = create.CreateAtith(30,1);
exparr[j] = expression;
expanswer[j] = count.countAnswer(expression);
System.out.print(expression + "=");
System.out.println(count.countAnswer(expression));
}
showQuestionJL.setText(exparr[done]);
panelRepaint(panel, difficultyChooseJP, answerJP);
}
// 點下一題,判斷是否完成所有題目
if (e.getActionCommand().equals("next")) {
if (expdone < Integer.parseInt(questNum)) {
expdone++;
panelRepaint(panel, nextJP, answerJP);
} else {
// 記錄結束時間
endTime = System.currentTimeMillis();
FileInOut inout = new FileInOut();
int[] in = new int[2];// 擷取曆史對錯題記錄
try {
in = inout.getrecord();
} catch (IOException e1) {
e1.printStackTrace();
}
in[0] = in[0] + trueCount;
in[1] = in[1] + failCount;
if (language == 0) {
showCountJL.setText("正确題數:" + trueCount + " 錯誤題數:"
+ failCount + " 用時: "
+ ((endTime - startTime) / 1000) + " s"
+ " 曆史總正确題數: " + in[0] + " 曆史總錯誤題數: " + in[1]);
} else {
showCountJL.setText("true:" + trueCount + " false:"
+ failCount + " time: "
+ ((endTime - startTime) / 1000) + " s"
+ " totaltrue: " + in[0] + " totalfalse: " + in[1]);
}
inout.recompose(in);
panelRepaint(panel, nextJP, countJP);
}
}
// 點送出,會判斷題目對錯
if (e.getActionCommand().equals("submit")) {
if (answerJTA.getText().equals(expanswer[done])) {
if (language == 0) {
resultJudgeJL.setText("正确");
} else {
resultJudgeJL.setText("true");
}
done++;
trueCount++;
answerJTA.setText("");
showQuestionJL.setText(exparr[done]);
panelRepaint(panel, answerJP, nextJP);
} else {
if (language == 0) {
resultJudgeJL.setText("錯誤 ! 正确答案為: " + expanswer[done]);
} else {
resultJudgeJL.setText("false correct answer is: "
+ expanswer[done]);
}
failCount++;
answerJTA.setText("");
showQuestionJL.setText(exparr[done]);
done++;
panelRepaint(panel, answerJP, nextJP);
}
}
}
}
package GUI;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class Main {
public static void main(String[] args) {
GUIcalculator GUI = new GUIcalculator();
GUI.setVisible(true);
}
}
運作截圖:
小組照片:
耗時估計:
小結:
事實證明結對程式設計真的是可以帶來1+1>2的效果的,以前一個人寫代碼的時候總是會有拖延症,老是覺得還有時間不用急着寫,而現在仙平會一直讓我快點做,不要拖他後腿,而且兩個人一起寫大家可以互相幫忙,不懂的問題可以一起解決,效率可以說是高了很多。
隊友評價:
可以說是一個非常棒的隊友了,會催我寫代碼,會幫我解決不懂的問題。對待程式設計他特别用心,雖然一直叫脖子疼,但還是會坐到電腦前先把代碼敲好,很少見他對一件事情這麼認真。
代碼位址:
https://coding.net/u/chenjunda/p/second/git/tree/master/ArithmeticGUI