GitHub仓库地址:
https://github.com/Sophur/Team-four-operation
一、需求分析
(1)由计算机从题库文件中随机选择20道加减乘除混合算式,用户输入算式答案,程序检查答案是否正确,每道题正确计5分,错误不计分,20道题测试结束后给出测试总分;
(2)题库文件可采用实验二的方式自动生成,也可以手工编辑生成,文本格式如下:
(3)程序为用户提供三种进阶四则运算练习功能选择:百以内整数算式(必做)、带括号算式、真分数算式练习;
(4)程序允许用户进行多轮测试,提供用户多轮测试分数柱状图,示例如下:
(5)程序记录用户答题结果,当程序退出再启动的时候,可为用户显示最后一次测试的结果,并询问用户可否进行新一轮的测试;
(6)测试有计时功能,测试时动态显示用户开始答题后的消耗时间。
(7)程序人机交互界面是GUI界面(WEB页面、APP页面都可),界面支持中文简体(必做)/中文繁体/英语,用户可以进行语种选择。
二、软件设计
程序流程图:
类图:
三、核心功能代码展示
给queding按钮添加监听器,计算本轮分数的核心代码:
1 //确定按钮的点击事件 2 queding.addActionListener(new ActionListener() { 3 public void actionPerformed(ActionEvent e) { 4 5 a1[0]=ans1.getText(); 6 a1[1]=ans2.getText(); 7 a1[2]=ans3.getText(); 8 a1[3]=ans4.getText(); 9 a1[4]=ans5.getText(); 10 a1[5]=ans6.getText(); 11 a1[6]=ans7.getText(); 12 a1[7]=ans8.getText(); 13 a1[8]=ans9.getText(); 14 a1[9]=ans10.getText(); 15 a1[10]=ans11.getText(); 16 a1[11]=ans12.getText(); 17 a1[12]=ans13.getText(); 18 a1[13]=ans14.getText(); 19 a1[14]=ans15.getText(); 20 a1[15]=ans16.getText(); 21 a1[16]=ans17.getText(); 22 a1[17]=ans18.getText(); 23 a1[18]=ans19.getText(); 24 a1[19]=ans20.getText(); 25 26 int sum=0; 27 for(int i=0;i<20;i++){ 28 if(a[i].equals(a1[i])){ 29 sum=sum+5; 30 }else{ 31 sum=sum+0; 32 } 33 } 34 grade1.setText(String.valueOf(sum)); 35 //System.out.println(sum); 36 37 } 38 });
给bu3按钮添加监听器,输出成绩柱状图:
1 bu3.addActionListener(new ActionListener() { 2 public void actionPerformed(ActionEvent e) { 3 Diagram dg = new Diagram(); 4 dg.setVisible(true); 5 } 6 });
Diagram类的具体实现:
1 import java.awt.Color; 2 import java.awt.Graphics; 3 import java.awt.Graphics2D; 4 import java.util.Random; 5 import javax.swing.JFrame; 6 7 public class Diagram extends JFrame{ 8 9 //绘制柱形统计图 10 private Random ran; 11 public Diagram(){ 12 super(); 13 ran = new Random(); 14 setTitle("成绩柱状图"); 15 setBounds(100, 100, 400, 271); 16 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 17 } 18 @Override 19 public void paint(Graphics g){ 20 int Width = getWidth(); 21 int Height = getHeight(); 22 int leftMargin = 20;//柱形图左边界 23 int topMargin = 50;//柱形图上边界 24 Graphics2D g2 = (Graphics2D) g; 25 int ruler = Height-topMargin-5; 26 int rulerStep = ruler/10;//将当前的高度评分为10个单位 27 g2.setColor(Color.WHITE);//绘制白色背景 28 g2.fillRect(0, 0, Width, Height);//绘制矩形图 29 g2.setColor(Color.black); 30 g2.setColor(Color.blue); 31 int grade[]= {60,40,100}; 32 for(int i=0;i<grade.length;i++){//绘制柱形图 33 int value=(grade[i]/10)*rulerStep; //矩形的高 34 int value1=grade[i]; 35 int step = (i+1)*40;//设置每隔柱形图的水平间隔为40 36 //绘制圆角矩形 37 g2.fillRect(leftMargin+step*2, Height-value, 40, value*3); 38 //纵轴的编号 39 g2.drawString("第"+(i+1)+"轮"+grade[i]+"分", leftMargin+step*2, Height-value-5); 40 } 41 } 42 43 }
四、程序运行
程序运行首先出现以下界面:
计时开始,进行答题,点击确定按钮后,答案保存并输出本轮分数:
点击输出柱状图按钮后显示柱状图:
五、结队过程
我和队友此次编程过程比较坎坷,两人编程基础都很差,但是还是没有放弃此次项目的完成。在刚开始进行系统设计的时候我们就出现了分歧,由于编程基础差,我把所有的功能都设计在主类中了,遭到了队友的反对,他说,你这样设计就不是Java了,全程只有一个类和C语言有什么区别,一点也没有体现Java封装的思想。我想了想,既然是结对编程,出现分歧了就应该先思考队友想法的正确性,而不是急着去反驳他。就这样我们重新设计了系统结构,最后设计了四个类,分别是主函数入口类,系统界面实现类,成绩柱状图实现类,计时器类。之后,我们将任务进行分工,由于系统界面我稍擅长,所以系统界面和成绩柱状图类由我来实现,队友负责将计时器类实现并在主函数中处理几个类之间的关系。以为就这样很平和地完成了此次项目?不存在的。在各自实现完负责的任务后,进行类与类之间的对接时,队友嫌弃我在实现界面时代码太过冗余。此次项目需要有20个JLabel和20个JTextField来分别显示题目和对应的答案输入框。我的代码如下:
1 2 JLabel lb1=new JLabel(); 3 JLabel lb2=new JLabel(); 4 JLabel lb3=new JLabel(); 5 JLabel lb4=new JLabel(); 6 JLabel lb5=new JLabel(); 7 JLabel lb6=new JLabel(); 8 JLabel lb7=new JLabel(); 9 JLabel lb8=new JLabel(); 10 JLabel lb9=new JLabel(); 11 JLabel lb10=new JLabel(); 12 JLabel lb11=new JLabel(); 13 JLabel lb12=new JLabel(); 14 JLabel lb13=new JLabel(); 15 JLabel lb14=new JLabel(); 16 JLabel lb15=new JLabel(); 17 JLabel lb16=new JLabel(); 18 JLabel lb17=new JLabel(); 19 JLabel lb18=new JLabel(); 20 21 pan1.add(lb1); 22 pan1.add(lb2); 23 pan1.add(lb3); 24 pan1.add(lb4); 25 pan1.add(lb5); 26 pan1.add(lb6); 27 pan1.add(lb7); 28 pan1.add(lb8); 29 pan1.add(lb9); 30 pan1.add(lb10); 31 pan1.add(lb11); 32 pan1.add(lb12); 33 pan1.add(lb13); 34 pan1.add(lb14); 35 pan1.add(lb15); 36 pan1.add(lb16); 37 pan1.add(lb17); 38 pan1.add(lb18);
在队友的提醒下更改后的代码:
1 JLabel[] quest=new JLabel[20];
2 for(int i=0;i<20;i++){
3
4 quest[i]=new JLabel();
5 quest[i].setPreferredSize(new Dimension(170,30));
6 pan1.add(quest[i]); //将JLabel加入JPanel
7
8 }
更改后顿时觉得整个程序清爽不少,毕竟改之前时38行左右,改之后时8行,效果还是很明显的。但是因为这个问题的更改使得其他的问题接踵而至,我们为确定按钮增加的点击事件失效了,还抛出了异常。包含确定按钮的监听器的代码如下,异常如图1所示:
1 import java.awt.BorderLayout; 2 import java.awt.Dimension; 3 import java.awt.GridLayout; 4 import java.awt.Toolkit; 5 import java.awt.event.ActionEvent; 6 import java.awt.event.ActionListener; 7 8 import javax.swing.JButton; 9 import javax.swing.JFrame; 10 import javax.swing.JLabel; 11 import javax.swing.JPanel; 12 import javax.swing.JTextField; 13 import javax.swing.UIManager; 14 15 public class Main { 16 17 JFrame mw=new JFrame("小学生四则运算"); 18 JPanel pan=new JPanel(); 19 JPanel pan1=new JPanel(); 20 JPanel pan2=new JPanel(); 21 22 JButton queding=new JButton("确定"); 23 JButton onemore=new JButton("再来一轮"); 24 JButton grade=new JButton("本轮分数"); 25 JLabel grade1=new JLabel(); 26 JButton diag=new JButton("输出柱状图"); 27 JButton time=new JButton("开始计时"); 28 29 30 public Main(){ 31 final String a[] = {"573","71","59888","1386","61065","185","136","500544","103","7778","202","4360356","75285","749","1201","219","4383","10386","1349","18"};//,71,59888,1386,61065,185,136,500544,103,7778,202,4360356,75285,749,1201,219,4383,10386,1349,18}; 32 final String a1[]=null; 33 final String question[]={"(47*13)+(96-40)-94=","(68+30)-(89-62)=","48+80*11*68=","50*27+63-27=","((17*79)+14)*45=","(19*13)-(86+70)+94=","75+85-24=","(43+36)*44*(87+57)=","((28+83)-60)+52=","36+(98*79)=","(54+86)+62=","(78*22)*(33*77)=","60*69*18+9*85=","(58*13)-5=","(13*88)+57=","35+2*92=","(43*100)+83=","((64*27)+3)*6=","71*(5+14)=","((92-16)+52)-83-27="}; 34 //题目文本标签 35 JLabel[] quest=new JLabel[20]; 36 for(int i=0;i<20;i++){ 37 quest[i]=new JLabel(); 38 quest[i].setPreferredSize(new Dimension(170,30)); 39 pan1.add(quest[i]); 40 41 } 42 for(int i=0;i<question.length;i++){ 43 quest[i].setText(question[i]); 44 45 } 46 47 //答案文本框 48 final JTextField[] ans=new JTextField[20]; 49 for(int i=0;i<20;i++){ 50 ans[i]=new JTextField(5); 51 pan2.add(ans[i]); 52 } 53 54 pan.add(queding); 55 pan.add(onemore); 56 pan.add(grade); 57 pan.add(grade1); 58 pan.add(diag); 59 pan.add(time); 60 61 mw.add(pan1); 62 mw.add(pan2); 63 mw.add(pan); 64 65 66 67 int w = (Toolkit.getDefaultToolkit().getScreenSize().width - 250) / 2; 68 69 int h = (Toolkit.getDefaultToolkit().getScreenSize().height - 550) / 2; 70 mw.setLocation(w, h); 71 mw.setSize(250, 550); 72 73 74 mw.add(pan1, BorderLayout.WEST); 75 mw.add(pan2,BorderLayout.EAST); 76 mw.add(pan,BorderLayout.SOUTH); 77 78 pan1.setLayout(new GridLayout(0,1)); 79 pan2.setLayout(new GridLayout(0,1)); 80 pan.setLayout(new GridLayout(0,2)); 81 mw.setVisible(true); 82 83 //确定按钮的点击事件 84 queding.addActionListener(new ActionListener() { 85 public void actionPerformed(ActionEvent e) { 86 87 88 for(int m= 0;m<20;m++){ 89 a1[m]=ans[m].getText(); 90 System.out.println(a1[m]); 91 } 92 93 94 int sum=0; 95 for(int j=0;j<20;j++){ 96 if(a[j].equals(a1[j])){ 97 sum=sum+5; 98 }else{ 99 sum=sum+0; 100 } 101 } 102 grade1.setText(String.valueOf(sum)); 103 //System.out.println(sum); 104 } 105 });//end of queding 106 107 //再来一轮 108 onemore.addActionListener(new ActionListener() { 109 public void actionPerformed(ActionEvent e) { 110 111 112 for(int m= 0;m<20;m++){ 113 ans[m].setText(null); 114 } 115 116 117 118 } 119 }); 120 //输出柱状图 121 diag.addActionListener(new ActionListener() { 122 public void actionPerformed(ActionEvent e) { 123 Diagram dg = new Diagram(); 124 dg.setVisible(true); 125 } 126 }); 127 128 129 time.addActionListener(new ActionListener() { 130 public void actionPerformed(ActionEvent e) { 131 Timers fr = new Timers("计时器"); 132 fr.pack(); 133 fr.setVisible(true); 134 } 135 }); 136 137 138 139 140 } 141 142 public void actionPerformed(ActionEvent arg0) { 143 // TODO Auto-generated method stub 144 145 } 146 147 public static void main(String[] args) { 148 // TODO Auto-generated method stub 149 Main mn=new Main(); 150 151 152 } 153 154 }
图1
在上网搜索了相关异常的解决办法后,最终还是没能够解决这个问题,所以不得已我们又将代码改回了冗余阶段的代码。看来还是基础薄弱,在项目完成后继续Java语言的学习。但是初步判定这个问题是没有处理好类与类之间的逻辑关系,在学习Java的类与类之间的关系后会返回来重新解决这个问题,在此先记录下问题。恳请老师的指导。
六、本次PSP展示
PSP2.1 |
任务内容 |
计划共完成需要的时间(day) |
实际完成需要的时间(day) |
Planning |
计划 |
2 |
1.5 |
· Estimate |
· 估计这个任务需要多少时间,并规划大致工作步骤 |
8 |
9 |
Development |
开发 |
7 |
7 |
·· Analysis |
需求分析 (包括学习新技术) |
2 |
2 |
· Design Spec |
· 生成设计文档 |
1 |
0.5 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
2 |
3 |
· Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
1 |
0.5 |
· Design |
具体设计 |
6 |
7 |
· Coding |
具体编码 |
7 |
6 |
· Code Review |
· 代码复审 |
0.5 |
1 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
1 |
2 |
Reporting |
报告 |
2 |
3 |
·· Test Report |
· 测试报告 |
0.5 |
0.3 |
· Size Measurement |
计算工作量 |
0.5 |
0.5 |
· Postmortem & Process Improvement Plan |
· 事后总结 ,并提出过程改进计划 |
0.5 |
0.5 |
七、请使用汉堡评价法给你的小伙伴一些点评。
小伙伴是个很有想法的人,没有因为编程能力有限而放弃代码的优化。希望小伙伴在以后的编程中不要因为项目太过困难而放弃,遇到不会的问题去学习,去问百度,学习别人的解决方法后解决自己的问题是一种很好的策略。连我自己在开始这个项目的时候也是走一步算一步的,所以任何事情坚持下来就会有成果。最后,有幸一起合作,一起努力,一起进步。
八、结对编程真的能够带来1+1>2的效果吗?通过这次结对编程,请谈谈你的感受和体会。
能! 此次项目完成过程中如果不是小伙伴对代码的冗余提出自己的想法的话,我想我是不会去进行代码的优化的。虽然代码的优化最终没能成功反而还引出了一些其他的问题,但是在以后的项目中我会不由自主的想到 代码的优化,这得益于小伙伴的提醒。此次项目的功能其实还没有实现的很全面,没能实现下一轮的功能,只是在用户点击下一轮时将答案文本框置为空。在画出柱状图的时候没能获取到每一轮的分数,但为了实现柱状图的这个功能,我们固定了分数,而不是将每一轮的成绩获取到动态显示。在学习完相关的知识后会返回来改进柱状图部分的内容。