Github的仓库主页链接地址:https://github.com/Opalus-wangs/Pair-Programming
一、需求分析
(1)由计算机从题库文件中随机选择20道加减乘除混合算式,用户输入算式答案,程序检查答案是否正确,每道题正确计5分,错误不计分,20道题测试结束后给出测试总分; (2)题库文件可采用实验二的方式自动生成,也可以手工编辑生成,文本格式如下图:
(3)程序为用户提供三种进阶四则运算练习功能选择:百以内整数算式、带括号算式、真分数算式练习;
(4)程序允许用户进行多轮测试,提供用户多轮测试分数柱状图,如下图所示;
(5)程序记录用户答题结果,当程序退出再启动的时候,可为用户显示最后一次测试的结果,并询问用户可否进行新一轮的测试;
(6)测试有计时功能,测试时动态显示用户开始答题后的消耗时间;
(7)程序人机交互界面是GUI界面(WEB页面、APP页面都可),界面支持中文简体/中文繁体/英语,用户可以进行语种选择。
二、软件功能设计及实现
a、流程图
b、类图
三、程序运行截图
a、主界面:可以选择简单算式运算和复杂(带括号)算式运算,也可以查看所有答题学生的得分情况
b、学生信息界面:输入学生编号及姓名
c、答题界面:界面显示学生姓名及学号,学生在此界面进行答题(根据此前选择的算式的难易程度出题),点击“开始计时”按钮,进行计时功能,学生输入算式答案,答题完毕点击“确定提交”按钮提交答案。
d、得分及柱状图界面:该界面显示答题学生成绩以及错误题号,点击“继续”按钮可以进行多轮测试
点击“查看”按钮可以查看所有答题学生的信息以及分数
四、关键代码
a、答题界面的算式获取方法及监听
1 //文件路径 2 File file = new File("F:\小学生四则运算\小学生四则运算\Text.txt");//Text文件 3 BufferedReader br = new BufferedReader(new FileReader(file));//构造一个BufferedReader类来读取文件 4 String s = null; 5 while((s = br.readLine())!=null) 6 { 7 READ[i]=s; 8 i++; 9 } 10 br.close();; 11 /*String s1 =READ[1].toString(); 12 name1.setText(s1);*/ 13 try { 14 15 name1.setText(READ[0].toString()+"="); 16 name2.setText(READ[1].toString()+"="); 17 name3.setText(READ[2].toString()+"="); 18 name4.setText(READ[3].toString()+"="); 19 name5.setText(READ[4].toString()+"="); 20 name6.setText(READ[5].toString()+"="); 21 name7.setText(READ[6].toString()+"="); 22 name8.setText(READ[7].toString()+"="); 23 name9.setText(READ[8].toString()+"="); 24 name10.setText(READ[9].toString()+"="); 25 name111.setText(READ[10].toString()+"="); 26 name12.setText(READ[11].toString()+"="); 27 name13.setText(READ[12].toString()+"="); 28 name14.setText(READ[13].toString()+"="); 29 name15.setText(READ[14].toString()+"="); 30 name16.setText(READ[15].toString()+"="); 31 name17.setText(READ[16].toString()+"="); 32 name18.setText(READ[17].toString()+"="); 33 name19.setText(READ[18].toString()+"="); 34 name20.setText(READ[19].toString()+"="); 35 } catch(NullPointerException e) { 36 System.out.println("读入文件有错!"); 37 38 } 39 40 button1.addActionListener(new ActionListener() 41 { 42 public void actionPerformed(ActionEvent event) 43 { 44 45 final time time=new time(); 46 new Thread(new Runnable(){ 47 @Override 48 public void run() { 49 try { 50 for(int i=0;i<1000;i++) { 51 Time.setText(String.format(time.a, i)); 52 Thread.sleep(1000); 53 } 54 } catch (InterruptedException e) { 55 e.printStackTrace(); 56 } 57 } 58 }).start(); 59 //记录开始测试的时间 60 } 61 }); 62 63 64 65 btn.addActionListener(new ActionListener() 66 { 67 String [] S =new String[20]; 68 69 public void actionPerformed(ActionEvent event) 70 { 71 try 72 { 73 S[0] = na1.getText();//得到答案 74 S[1] = na2.getText(); 75 S[2] = na3.getText(); 76 S[3] = na4.getText(); 77 S[4] = na5.getText(); 78 S[5] = na6.getText(); 79 S[6] = na7.getText(); 80 S[7] = na8.getText(); 81 S[8] = na9.getText(); 82 S[9]= na10.getText(); 83 S[10] =na111.getText(); 84 S[11] =na12.getText(); 85 S[12]= na13.getText(); 86 S[13] = na14.getText(); 87 S[14] = na15.getText(); 88 S[15] = na16.getText(); 89 S[16] = na17.getText(); 90 S[17] = na18.getText(); 91 S[18] = na19.getText(); 92 S[19] = na20.getText(); 93 //判空 94 if(S[0].equals("")||S[1].equals("")||S[2].equals("")||S[3].equals("")||S[4].equals("")||S[5].equals("")||S[6].equals("")||S[7].equals("")||S[8].equals("")||S[9].equals("") 95 ||S[10].equals("")||S[11].equals("")||S[12].equals("")||S[13].equals("")||S[14].equals("")||S[15].equals("")||S[16].equals("")||S[17].equals("")||S[18].equals("")||S[19].equals("") 96 97 ) 98 { 99 throw new FormatException1(); 100 101 } 102 } 103 catch(FormatException1 a) 104 { 105 JOptionPane.showMessageDialog(null,"请输入计算结果"); 106 } 107 108 109 //将算式的计算结果保存到数组k1[] 110 for(int k=0;k<20;k++) 111 { 112 k1[k]=calculate.arithmetic(READ[k]); 113 } 114 win.setVisible(false); 115 116 for(int t=0;t<20;t++) 117 { 118 //记录错误题数以及错误题号 119 if(k1[t]!=Integer.parseInt(S[t])) 120 { 121 kk[count]=t; 122 count ++; 123 } 124 } 125 126 Student ug = new Student(name11,number11,kk, count); 127 students.add(ug); 128 129 final JFrame win = new JFrame("小学生四则运算"); 130 final JPanel pan = new JPanel(); 131 new SeeFrame(win,pan,name11,number11,kk,count,students); 132 win.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 133 win.setVisible(true); 134 win.setLocationRelativeTo(null); 135 } 136 137 });
b、计时器代码
1 public class time { 2 public Timer timer=new Timer(); 3 public boolean is_pause=false; 4 public timetask mytimetask=new timetask(); 5 public int hh,mm,ss; 6 String a; 7 public time() 8 { 9 timer.scheduleAtFixedRate(mytimetask, 0, 1000); 10 } 11 public class timetask extends TimerTask{ 12 public int count_time=0; 13 public String date; 14 @Override 15 public void run() 16 { 17 if(!is_pause) 18 { 19 count_time++; 20 hh=count_time/3600; 21 mm=(count_time%3600)/60; 22 ss=count_time%60; 23 date=hh+":"+mm+":"+ss; 24 a=date; 25 } 26 } 27 } 28 }
c、成绩柱状图
1 //绘制柱状图 2 public class Picture extends JFormattedTextField 3 { 4 int [] a=new int[20]; 5 int j=0; 6 int i=0; 7 int x=0; 8 int aa=0; 9 //绘制柱形统计图 10 private Random ran; 11 public Picture(ArrayList<Student> students) 12 { 13 super(); 14 for(Student e: students ) 15 { 16 a[j]=(e.getw()); 17 j++; 18 } 19 ran = new Random(); 20 setName("绘制柱形图"); 21 setBounds(100,85,270,210); 22 } 23 @Override 24 public void paint(Graphics g){ 25 int Width = getWidth(); 26 int Height = getHeight(); 27 int leftMargin = 2;//柱形图左边界 28 int topMargin = 5;//柱形图上边界 29 Graphics2D g2 = (Graphics2D) g; 30 int ruler = Height-topMargin-5; 31 int rulerStep = ruler/10;//将当前的高度评分为10个单位 32 g2.setColor(Color.WHITE);//绘制白色背景 33 g2.fillRect(0, 0, Width, Height);//绘制矩形图 34 g2.setColor(Color.LIGHT_GRAY); 35 for(int i=0;i<=10;i++){//绘制灰色横线和百分比 36 g2.drawString((100-10*i)+"%", 5, topMargin+rulerStep*i);//写下百分比 37 g2.drawLine(5, topMargin+rulerStep*i, Width, topMargin+rulerStep*i);//绘制灰色横线 38 } 39 g2.setColor(Color.RED); 40 41 for(i=0;i<j;i++){//绘制柱形图 42 int value =(20-a[i])*10+5; 43 int step = (i+1)*20;//设置每隔柱形图的水平间隔为40 44 //绘制矩形 45 46 g2.fillRoundRect(leftMargin+step*2, Height-value, 20, value, 20, 20); 47 //列出产品的编号 48 g2.drawString("C"+(i+1)+"-"+(20-a[i])*5+"%", leftMargin+step*2, Height-value-5); 49 50 } 51 } 52 } 53
五、结对编程过程
六、PSP
PSP2.1 | 任务内容 | 计划完成的时间(min) | 实际完成需要的时间(min) |
---|---|---|---|
PLanning | 计划 | 60 | 80 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 60 | 80 |
Developmet | 开发 | 450 | 520 |
Analysis | 需求分析(包括学习新技术) | 30 | 40 |
Design Spec | 生成设计文档 | 10 | 20 |
Design Revie | 设计复审(和同事审核设计文档) | 30 | 30 |
Coding Standard | 代码规范 | 30 | 30 |
Design | 具体设计 | 60 | 60 |
Coding | 具体编码 | 240 | 290 |
Code Review | 代码复审 | 30 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 20 | 20 |
Reporting | 报告 | 40 | 40 |
Test Report | 测试报告 | 20 | 20 |
Size Measurement | 计算工作量 | 5 | 5 |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改机计划 | 15 | 15 |
七、对小伙伴的评价
这次我的结对项目的partner是我再熟悉不过的人了,这不是我们的第一次合作了,在之前其他的课程学习过程中我们一也一起合作过,所以配合起来也是相当的默契。他是一个动手能力很强的人,而且对于细节特别的执着,我们在完成这个结对项目的过程中有的时候在一些细节上在实验室/图书馆没有完成的部分,回到宿舍后也是会继续的来完成,说到这里,为大家安利一个很好用的软件TeamView,一款可以远程访问的软件,这样我们可以利用在宿舍的时间也一起编程,一起思考,就像是在使用同一台计算机,同一个鼠标,完美的解决了空间上的问题,在项目开始的过程中我们互相表达我们各自的想法,提出一些好的建议,在实现的过程中,难免也有意见不合的情况,但是我们都是通过协商最后达成一致,这是一次非常不错的体验,期待下一次的合作。
八、 结对编程真的能够带来1+1>2的效果吗?通过这次结对编程,请谈谈你的感受和体会。
答案是肯定的,1+1肯定是大于2的,为什么呢?举个例子来说,当你手握一根筷子的时候你可以很轻松的把它折断,两根筷子的时候也可能很轻松的做到,但是当筷子的数量增加的时候,你就很难再折断它,这也是群体的力量,一个人的编程设计往往会出现很多的问题,比如一些代码上的漏洞和设计功能等考虑的不全面,当两个人甚至是多个人的智慧集中在一起的时候,往往漏洞就会急剧减少,这就是为什么一个强大的项目后面往往有一个优秀的团队。