结对编程
结对号数:
许晓烽:112号
黄明炜:97号
码云仓库:https://gitee.com/huhulong/JieDuiXiangMu
1.需求分析:
(1)根据参数生成n个四则运算式,并且规定范围
(2)设置语言中文或者英文
(3)有计时功能,并且可以设置最长时间
(4)文件保存题目并且知道答题情况
2.程序设计
3.代码展示:
目录结构:
(1)顶层容器代码(MainFrame):
package main; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import bean.Formula; import param.Param; import menu.MainMenuBar; public class MainFrame extends JFrame{ JPanel jpanel=new JPanel(); MainMenuBar mainMenuBar=new MainMenuBar(this);//菜单 ButtonLabel generatingItemButton=new ButtonLabel(Param.generatingItem);//生成按钮 ButtonLabel beginButton=new ButtonLabel(Param.begin);//开始按钮 TimeProgressBar timeProgressBar=new TimeProgressBar(this); JTextArea subjectArea=new JTextArea();//题目框 JTextArea answerArea=new JTextArea();//答题区 public ButtonLabel submitButton=new ButtonLabel(Param.submit);//提交按钮 //构造函数 public MainFrame(){ init(); mouseEvent(); this.setJMenuBar(mainMenuBar);//添加菜单 this.setTitle(Param.title); this.setSize(700,600); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置默认关闭窗口方式 this.setLocationRelativeTo(null);//设置窗体相对居中 this.setResizable(false);//设置窗口不可调整 this.setVisible(true);//可视化 } //初始化设置 public void init(){ this.setLayout(null);//设置空布局 generatingItemButton.setBounds(20, 20, 100, 30); this.add(generatingItemButton); beginButton.setBounds(130, 20, 100, 30); this.add(beginButton); //进度条 timeProgressBar.setBounds(400, 20, 250, 30); this.add(timeProgressBar); subjectArea.setEditable(false); //给试题框出现滚动条 JScrollPane jssubjectArea=new JScrollPane(subjectArea); jssubjectArea.setBounds(20, 100, 600, 150); this.add(jssubjectArea); answerArea.setEditable(false); //给答题框加设滚动条 JScrollPane jsanswerArea=new JScrollPane(answerArea); jsanswerArea.setBounds(20, 300, 600, 150); this.add(jsanswerArea); submitButton.setBounds(300, 480, 100, 30); this.add(submitButton); jpanel.setBounds(0, 0, 700, 1000); this.add(jpanel); } //给三个label按钮添加监听 public void mouseEvent(){ //生成试题的点击事件 generatingItemButton.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent arg0) { subjectArea.setText(""); File answersFile = new File("file/Answers.txt"); FileWriter answersFw; for(int i=0;i<Param.number;i++){ Formula formula = new Formula(Param.range); String aFormula = formula.getAFormula(); subjectArea.append((i+1)+"."+aFormula+"\r\n"); //将答案写入到答案文件中 try { answersFw = new FileWriter(answersFile, true); BufferedWriter answersBw = new BufferedWriter(answersFw); answersBw.write((i + 1) + "." + formula.getAnswser().toString()); answersBw.newLine(); answersBw.flush(); answersBw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //讲题目写入到文件中 File exercisesFile = new File("file/Exercises.txt"); String stirng=subjectArea.getText(); FileWriter exercisesFw; try { exercisesFw = new FileWriter(exercisesFile, true); BufferedWriter exercisesBw = new BufferedWriter(exercisesFw); exercisesBw.write(stirng); exercisesBw.flush(); exercisesBw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); //开始写题的点击事件 beginButton.addMouseListener(new MouseAdapter(){ @Override public void mousePressed(MouseEvent arg0) { timeProgressBar.restart(); answerArea.setEditable(true); } }); //提交试题的点击事件 submitButton.addMouseListener(new MouseAdapter(){ @Override public void mousePressed(MouseEvent arg0) { File yourFile = new File("file/YourFile.txt"); String string = answerArea.getText(); FileWriter yourFileFw; try { yourFileFw = new FileWriter(yourFile, true); BufferedWriter yourFileBw = new BufferedWriter(yourFileFw); yourFileBw.write(string); yourFileBw.flush(); yourFileBw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } answerArea.setEditable(false); timeProgressBar.stop(); //将对错情况写入到文件里 //先删除文件 File gradeFile = new File("file/Grade.txt"); if (gradeFile.exists()) { gradeFile.delete(); } //定义答案文件和答题文件的输入流 File answersFile = new File("file/Answers.txt"); FileReader answersRd; try { answersRd = new FileReader(answersFile); BufferedReader answersBufferRd = new BufferedReader(answersRd); FileReader yourFileRd = new FileReader(yourFile); BufferedReader yourFileBufferRd = new BufferedReader(yourFileRd); String thisLineAnswer = ""; String yourAnswer = ""; List<Integer> error = new ArrayList<Integer>(); List<Integer> right = new ArrayList<Integer>(); int num = 1; while ((thisLineAnswer = answersBufferRd.readLine()) != null) { yourAnswer = yourFileBufferRd.readLine(); if (yourAnswer.equals(thisLineAnswer)) { right.add(num); } else { error.add(num); } num++; } answersBufferRd.close(); yourFileBufferRd.close(); //将答题结果写入到Grade文件中 FileWriter gradeFw = new FileWriter(gradeFile, true); BufferedWriter gradeBw = new BufferedWriter(gradeFw); gradeBw.write("Correct:"+right.size()+"("); for (int x=0;x<right.size();x++){ gradeBw.write(right.get(x)+","); } gradeBw.write(")"); gradeBw.newLine(); gradeBw.write("Wrong:"+error.size()+"("); for (int y=0;y<error.size();y++){ gradeBw.write(error.get(y)+","); } gradeBw.write(")"); gradeBw.newLine(); //关闭流 gradeBw.flush(); gradeBw.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e){ // TODO Auto-generated catch block e.printStackTrace(); } } }); } //主函数 public static void main(String[] args) { // TODO Auto-generated method stub try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) { // TODO Auto-generated catch block e.printStackTrace(); } new MainFrame(); } }
(2)进度条
package main; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JProgressBar; import javax.swing.Timer; import param.Param; public class TimeProgressBar extends JProgressBar implements ActionListener{ public int maxTime = Param.time;// 设置最大时间 private Timer timer = new Timer(1000, this);// 计时器,int // delay一秒减少一次和ActionListener监听器 public MainFrame mainFrame; public TimeProgressBar(MainFrame mainFrame) { this.mainFrame = mainFrame; // mouseEvent(); this.setMaximum(maxTime); this.setValue(maxTime); this.setBackground(Color.gray); this.setStringPainted(true);// 设置 stringPainted // 属性的值,该属性确定进度条是否应该呈现进度字符串。 this.setString(maxTime + "秒"); } @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub maxTime--; this.setValue(maxTime); this.setString(maxTime + "秒"); //时间一到,计时停下来,不然会进入负数 if(maxTime==0){ this.stop(); mainFrame.answerArea.setEditable(false); } } /** * 开始 */ public void start() { timer.start(); } /** * 暂停 */ public void stop() { timer.stop(); } /** * 重新开始 */ public void restart() { maxTime = Param.time; this.setMaximum(maxTime);// 重新设置JProgress的最大值 this.setValue(maxTime); this.setString(maxTime + "秒"); timer.start(); } }
(3)式子类,包含式子生成和结果生成
package bean; import java.util.ArrayList; import java.util.List; import java.util.Random; /** * Created by Administrator on 2017/9/23. */ public class Formula { private List numberList = new ArrayList();//数列 private List operatorList = new ArrayList();//算符列 //空构造 public Formula() { } //gei与set方法 public List getNumberList() { return numberList; } public void setNumberList(List numberList) { this.numberList = numberList; } public List getOperatorList() { return operatorList; } public void setOperatorList(List operatorList) { this.operatorList = operatorList; } //带参构造,生成r自然数范围内的式子 public Formula(Integer r) { //判断生成的式子有几个运算符 Random random = new Random(); Integer num = random.nextInt(3); StringBuffer formula = new StringBuffer(""); //生成运算符为1个的式子 if (num == 0) { Number number1 = new Number(r); this.numberList.add(number1); Operator operator1 = new Operator(); this.operatorList.add(operator1.getOperator()); Number number2 = new Number(r); this.numberList.add(number2); } else if (num == 1) {//生成运算符为2的式子 Number number1 = new Number(r); this.numberList.add(number1); Operator operator1 = new Operator(); this.operatorList.add(operator1.getOperator()); Number number2 = new Number(r); this.numberList.add(number2); Operator operator2 = new Operator(); this.operatorList.add(operator2.getOperator()); Number number3 = new Number(r); this.numberList.add(number3); } else {//生成运算符为3的式子 Number number1 = new Number(r); this.numberList.add(number1); Operator operator1 = new Operator(); this.operatorList.add(operator1.getOperator()); Number number2 = new Number(r); this.numberList.add(number2); Operator operator2 = new Operator(); this.operatorList.add(operator2.getOperator()); Number number3 = new Number(r); this.numberList.add(number3); Operator operator3 = new Operator(); this.operatorList.add(operator3.getOperator()); Number number4 = new Number(r); this.numberList.add(number4); } } //根据numberList和operatorList生成一个式子 public String getAFormula() { StringBuffer stringBuffer = new StringBuffer(""); stringBuffer.append(numberList.get(0)); for (int i = 0; i < operatorList.size(); i++) { stringBuffer.append(operatorList.get(i)); stringBuffer.append(numberList.get(i + 1)); } return stringBuffer.toString(); } //生成式子答案 public Number getAnswser() { //先对式子的*和÷进行处理 int i = 0; while (i < operatorList.size()) { //如果数列里的数个数是0,则返回该方法 if (numberList.size()==1){ return (Number) numberList.get(0); } //当算符出现*和÷的时候 if (operatorList.get(i).equals("*") || operatorList.get(i).equals("÷")) { //取得运算符两侧的数 Number numberFront = (Number) numberList.get(i); Number numberAfter = (Number) numberList.get(i + 1); //求得运算符两侧数值的分子部分 int numberFrontMolecule = numberFront.getInteger() * numberFront.getDenominator() + numberFront.getMolecule(); int numberAfterMolecule = numberAfter.getInteger() * numberAfter.getDenominator() + numberAfter.getMolecule(); int endMolecule = 0; int endDenominator = 0; //算得两数相乘的分子值和分母值 if (operatorList.get(i).equals("*")) { endMolecule = numberFrontMolecule * numberAfterMolecule; endDenominator = numberFront.getDenominator() * numberAfter.getDenominator(); } if (operatorList.get(i).equals("÷")) { endMolecule = numberFrontMolecule * numberAfter.getDenominator(); endDenominator = numberAfterMolecule * numberFront.getDenominator(); } int endInteger = 0;//初始分子的整数部分为0 if (endMolecule > endDenominator) { endInteger = endMolecule / endDenominator; endMolecule = endMolecule % endDenominator; } //求最大公约数 int smaller = endMolecule > endDenominator ? endMolecule : endDenominator; int maxCommonFactor = 1; for (int j = 1; j <= smaller; j++) { if (endMolecule % j == 0 && endDenominator % j == 0) { maxCommonFactor = j; } } endMolecule = endMolecule / maxCommonFactor; endDenominator = endDenominator / maxCommonFactor; Number endNumber = new Number(endInteger, endMolecule, endDenominator);//约分后的式子 this.numberList.add(i, endNumber); this.numberList.remove(i + 1); this.numberList.remove(i + 1); this.operatorList.remove(i); }else { i++; } } //进行完*÷处理后进行+-处理 while (operatorList.size()!=0){ //取得运算符两侧的数 Number numberFront = (Number) numberList.get(0); Number numberAfter = (Number) numberList.get(1); //求得运算符两侧数值的分子部分 int numberFrontMolecule = numberFront.getInteger() * numberFront.getDenominator() + numberFront.getMolecule(); int numberAfterMolecule = numberAfter.getInteger() * numberAfter.getDenominator() + numberAfter.getMolecule(); //不管两式子的分母一样或不一样,都把两分母相乘 int endDenominator=numberFront.getDenominator()*numberAfter.getDenominator(); //如果为+符,就进行+算 int allMolecule1=numberFrontMolecule*numberAfter.getDenominator(); int allMolecule2=numberAfterMolecule*numberFront.getDenominator(); int endMolecule=0;//定义未约分前的分子部分 if (operatorList.get(0).equals("+")){ endMolecule=allMolecule1+allMolecule2; } if (operatorList.get(0).equals("-")){ endMolecule=allMolecule1-allMolecule2; } int endInteger = 0;//初始分子的整数部分为0 if (endMolecule > endDenominator) { endInteger = endMolecule / endDenominator; endMolecule = endMolecule % endDenominator; } //求最大公约数 int smaller = endMolecule > endDenominator ? endMolecule : endDenominator; int maxCommonFactor = 1; for (int j = 1; j <= smaller; j++) { if (endMolecule % j == 0 && endDenominator % j == 0) { maxCommonFactor = j; } } endMolecule = endMolecule / maxCommonFactor; endDenominator = endDenominator / maxCommonFactor; Number endNumber = new Number(endInteger, endMolecule, endDenominator);//约分后的式子 this.numberList.add(0, endNumber); this.numberList.remove(1); this.numberList.remove(1); this.operatorList.remove(0); } return (Number) numberList.get(0); } }
(4)菜单类,包含按键监听
package menu; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.HashSet; import java.util.Set; import javax.swing.ButtonGroup; import javax.swing.JCheckBoxMenuItem; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import param.Param; import main.MainFrame; public class MainMenuBar extends JMenuBar { MainFrame mainFrame; JMenu menuSet = new JMenu(Param.set);// 设置按钮 JMenuItem menuHistory = new JMenuItem(Param.history);// 查看历史情况 JMenuItem paramSet = new JMenuItem(Param.paramSet);// 参数设置 JMenuItem timeSet = new JMenuItem(Param.timeSet);// 时间设置 JMenu languageSet = new JMenu(Param.languageSet);// 语言设置 public MainMenuBar(MainFrame mainFrame) { this.mainFrame = mainFrame; init(); mouseEvent(); } // 初始化 public void init() { menuSet.add(paramSet); menuSet.add(timeSet); menuSet.add(languageSet); menuSet.add(menuHistory); this.add(menuSet); } public void mouseEvent() { //历史成绩按钮 menuHistory.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub new History(mainFrame); } }); //参数设置 paramSet.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub new ParamSet(mainFrame); } }); //时间设置 timeSet.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub new TimeParamSet(mainFrame); } }); //语言设置 ButtonGroup languageGroup = new ButtonGroup(); Set<String> lgSet = new HashSet<String>(); languageSet.add(Param.chinese); languageSet.add(Param.english); for (String str : lgSet) { final JCheckBoxMenuItem checkBoxMenuItem = new JCheckBoxMenuItem( str); languageGroup.add(checkBoxMenuItem); languageSet.add(checkBoxMenuItem); if (str.equals("中文") || str.equals("chinese")) { checkBoxMenuItem.setSelected(true); checkBoxMenuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub Param.exNumber = "生成题目数"; Param.exRange = "数字范围"; Param.timeConfig = "时间设置(秒)"; Param.determine = "确定"; Param.remaind = "请输入正整数"; Param.title = "四则运算器"; Param.generatingItem = "生成题目"; Param.begin = "开始"; Param.submit = "提交答案"; Param.set = "设置"; Param.history = "历史情况"; Param.timeSet = "时间设置"; Param.paramSet = "参数设置"; Param.languageSet = "语言设置"; Param.chinese = "中文"; Param.english = "英文"; mainFrame.repaint(); } }); } else { checkBoxMenuItem.setSelected(true); checkBoxMenuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub Param.exNumber = "Number of items"; Param.exRange = "range"; Param.timeConfig = "TimeSet(s)"; Param.determine = "determine"; Param.remaind = "Please enter a positive integer"; Param.title = "四则运算器"; Param.generatingItem = "generating Item"; Param.begin = "begin"; Param.submit = "submit"; Param.set = "Set"; Param.history = "History"; Param.timeSet = "TimeSet"; Param.paramSet = "ParamSet"; Param.languageSet = "LanguageSet"; Param.chinese = "Chinese"; Param.english = "English"; mainFrame.repaint(); } }); } } } }
4.程序运行:
主界面: 参数设置:
题目生成: 开始做题,计时开始,并且让答题区变为可编辑:
提交答案,答题区继续变为不可编辑,进度条停止 查看结果:
5.小结感受:
我感觉这次结对编程,真正的发挥了1+1>2的情况,首先是时间上,使用git可以做到进度一起推进的情况,划分好模块,可以两头一起推进,剩下了不少
时间。再者是思路,两个人的思路总是比一个人的思路多很多,思考问题容易进入死角,得到别人的提醒尤为重要。
感觉这次结对编程,首先是要熟悉git的使用,在git上花了很多的时间,然后是出现代码冲突的情况,两个人要在一块找冲突的地方在哪,以前也组队一起
做过项目,同时做到最后合代码时合得眼花缭乱,使用git感觉可以方便许多,然后是GUI编程,有一段时间不用了,感觉现在用起来又生疏了许多,有些细节
也没有去细细扣,比如说答题出现暂停的情况。
6.评价搭档
首先,我的搭档和我一样,有着学习的冲劲和动力,经常在深夜也能够一起思考讨论问题。
再者,我的搭档做得不足的地方,我觉得做得都很好,能够提出有建设性的意见和建议,也能够在没思路的时候指出思路,但是感觉平时白天能做完的事
尽量别拖到晚上,影响睡眠也挺影响第二天的状态。
最后,我感觉我和搭档能够把界面做得更好看一些,可以加一些背景图片之类的。
7.照片摆拍
8.PSP