一、项目源码
Github的仓库主页链接地址:https://github.com/LilyFuEnLi/Arithmetic_SE.git
二、项目报告
1. 需求分析
(1)由计算机从题库文件中随机选择20道加减乘除混合算式,用户输入算式答案,程序检查答案是否正确,每道题正确计5分,错误不计分,20道题测试结束后给出测试总分;
(2)题库文件可采用实验二(详细内容请查看上一篇博客)的方式自动生成,文本格式如图1所示;
图 1 图 2
(3)程序为用户提供三种进阶四则运算练习功能选择:百以内整数算式、带括号算式、真分数算式练习;
(4)程序允许用户进行多轮测试,提供用户多轮测试分数柱状图,如图2所示;
(5)程序记录用户答题结果,当程序退出再启动的时候,可为用户显示最后一次测试的结果,并询问用户可否进行新一轮的测试;
(6)测试有计时功能,测试时动态显示用户开始答题后的消耗时间;
(7)程序人机交互界面是GUI界面(WEB页面、APP页面都可),界面支持中文简体/中文繁体/英语,用户可以进行语种选择。
2. 软件设计
(1)程序设计图如下所示:
(2)类图如下图所示:
(1)Main( )类:主函数类,弹出登录窗口界面;
(2)Start( )类:产生答题窗口类,利用按钮监听器接口,存储学生答案,显示结果,进行对比分析等操作。
(3)Calculate_SE()类:运算式产生类,结合上次作业,产生整数运算式、分数运算式文件。
(4)Timer()类:包含内部类Timer.CountingThread()类,产生计时窗口。
(5)Chart_H( )类:绘制成绩柱状图。
3. 核心功能代码展示
(1) 答题界面的监听器方法部分代码
1 //---------------------------------------整数------------------------- 2 JRadioButton buttonInteger=new JRadioButton("整数");//JRadioButton 3 buttonInteger.addItemListener(new ItemListener() { 4 public void itemStateChanged(ItemEvent arg0) { 5 frame2.pack(); 6 frame2.setVisible(true); 7 try { 8 CA.calaulate_AE(40); 9 } catch (IOException e) { 10 e.printStackTrace(); 11 } 12 String shizi = CA.IntegerQ.get(number); 13 NUM++; 14 label1.setText(shizi); 15 } 16 }); 17 //--------------------------------分数--------------------------------- 18 JRadioButton buttonFenshu = new JRadioButton("分数"); 19 buttonFenshu.addItemListener(new ItemListener() { 20 public void itemStateChanged(ItemEvent arg0) { 21 frame2.pack(); 22 frame2.setVisible(true); 23 try { 24 CA.fenshu(); 25 } catch (IOException e) { 26 e.printStackTrace(); 27 } 28 String shizi = CA.FractionQ.get(number); 29 NUM++; 30 label1.setText(shizi); 31 } 32 }); 33 //-------------------------------------下一题答案按钮的设定------------------------------------------------------- 34 JButton buttonNext=new JButton("下一题"); 35 buttonNext.addActionListener(new ActionListener() {//定义时间监听器 36 public void actionPerformed(ActionEvent e) { 37 if(buttonInteger.isSelected()) 38 { 39 String question=label1.getText(); 40 String result=text.getText(); 41 String ifRight=""; 42 if((CA.IntegerA.get(number)).equals(result)) 43 { 44 ifRight="正确"; 45 rightSum++; 46 } 47 else 48 { 49 ifRight="错误"; 50 } 51 String message=question+", "+"你的答案:"+result+", "+"正确答案: "+CA.IntegerA.get(number)+", 状态: "+ifRight; 52 list.add(message); 53 text.setText(""); 54 number++; 55 String shizi=CA.IntegerQ.get(number); 56 NUM++; 57 label1.setText(shizi); 58 if(NUM==20) 59 { 60 JOptionPane.showMessageDialog(null, "本题为第20道题,答题结束,请提交答案。", "答题结束", JOptionPane.INFORMATION_MESSAGE); 61 text.setText(result); 62 } 63 } 64 if(buttonFenshu.isSelected()) 65 { 66 String question=label1.getText(); 67 String result=text.getText(); 68 String ifRight=""; 69 if(CA.FractionA.get(number).equals(result)) 70 { 71 ifRight="正确"; 72 rightSum++; 73 } 74 else 75 { 76 ifRight="错误"; 77 } 78 String message=question+", "+"你的答案:"+result+", "+"正确答案: "+CA.FractionA.get(number)+", 状态: "+ifRight; 79 list.add(message); 80 text.setText(""); 81 number++; 82 String shizi=CA.FractionQ.get(number); 83 NUM++; 84 label1.setText(shizi); 85 if(NUM==20) 86 { 87 JOptionPane.showMessageDialog(null, "本题为第20道题,答题结束,请提交答案。", "答题结束", JOptionPane.INFORMATION_MESSAGE); 88 text.setText(result); 89 } 90 } 91 } 92 });
(2)计时器部分代码
1 public void run() { 2 while (true) { 3 if (!stopped) { 4 long elapsed = System.currentTimeMillis() - programStart - pauseCount; 5 label.setText(format(elapsed)); 6 time=label.getText(); 7 File f=new File("time.txt"); 8 BufferedWriter bw; 9 try { 10 bw = new BufferedWriter(new FileWriter(f)); 11 bw.write(time); 12 bw.close(); 13 } catch (IOException e) { 14 // TODO Auto-generated catch block 15 e.printStackTrace(); 16 } 17 } 18 19 try { 20 sleep(1); // 1毫秒更新一次显示 21 } catch (InterruptedException e) { 22 e.printStackTrace(); 23 System.exit(1); 24 } 25 } 26 } 27 28 // 将毫秒数格式化 29 private String format(long elapsed) { 30 int hour, minute, second, milli; 31 32 milli = (int) (elapsed % 1000); 33 elapsed = elapsed / 1000; 34 35 second = (int) (elapsed % 60); 36 elapsed = elapsed / 60; 37 38 minute = (int) (elapsed % 60); 39 elapsed = elapsed / 60; 40 41 hour = (int) (elapsed % 60); 42 43 return String.format("%02d:%02d:%02d:%03d", hour, minute, second, milli); 44 } 45 }
(3)成绩柱状图部分代码
1 public void paint(Graphics g){ 2 //int number=newList.size()-1; 3 int Width = getWidth(); 4 int Height = getHeight(); 5 int leftMargin = 20;//柱形图左边界 6 int topMargin = 50;//柱形图上边界 7 Graphics2D g2 = (Graphics2D) g; 8 g2.setColor(Color.WHITE);//绘制白色背景 9 g2.fillRect(0, 0, Width, Height-100);//绘制矩形图 10 g2.setColor(Color.LIGHT_GRAY); 11 for(int i=0;i<=10;i++) 12 {//绘制灰色横线和百分比 13 g2.drawString((100-10*i)+"", 5, topMargin+30*i);//写下百分比 14 g2.drawLine(5, topMargin+30*i, Width, topMargin+30*i);//绘制灰色横线 15 } 16 g2.setColor(Color.PINK); 17 for(int i=0;i<=number;i++) 18 {//绘制柱形图 19 if(newList.get(i)!="") 20 { 21 int value =Integer.parseInt(newList.get(i)); 22 int step = (i+1)*40;//设置每隔柱形图的水平间隔为40 23 //绘制矩形 24 g2.fillRoundRect(leftMargin+step*2-5,(100-value)*3+50, 40, 300-(100-value)*3, 40, 10); 25 //列出测试轮数 26 g2.drawString(newList.get(i), leftMargin+step*2, (100-value)*3+50); 27 g2.drawString("第"+(i+1)+"轮", leftMargin+step*2, 380); 28 } 29 } 30 }
4. 程序运行截图
(1)运行主函数Main.java文件,进入登录界面,截图如下图所示,输入姓名,学号后,点击确认进入答题初始界面,如图3所示,此时会显示学生的上次成绩,当学生点击选择进行分数或者整数时,弹出计时器界面。此时点击开始,输入题目的答案,并点击下一题进行作答即可。
图 3 答题初始界面
(2)当学生答够20道题后,弹出提示信息,答题结束,如图4所示。学生提交答案,计时器窗口关闭,弹出运算结果窗口,显示学生答题情况(整体分数、答题时间),如图5所示:
图 4 答题结束界面
图 5
在项目后期,我们发现,上图5的总体信息显示情况不太良好,我们又进行了优化,利用Java的Table优化了界面,如下图所示:
(3)得到本轮答题情况后,学生可以点击答题分析按钮,查看几轮测试的柱状图,如图6所示,也可以点击进行下一轮按钮再次测试。
图 6 成绩柱状图
5. 结对编程过程
首先利用老师给出的需求分析,再做详细分析,建立基本的整体软件框架,将项目划分为5个模块。其次,一块修改上次作业的运算式产生程序,通过查找资料,加入了分数运算式。然后,写出窗口的整体布局,详细布局Start()类,通过监听器接口调用运算式类编程,这部分主要是我敲代码,我的小伙伴协助。后来,我的小伙伴主笔编写计时器,调整各个窗口的布局以及其他属性。最后,我们一块加入了柱状图部分,审核代码,做优化。
6. PSP
PSP2.1 | 任务内容 | 计划完成的时间(min) | 实际完成需要的时间(min) |
---|---|---|---|
PLanning | 计划 | 60 | 80 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 30 | 40 |
Developmet | 开发 | 480 | 520 |
Analysis | 需求分析(包括学习新技术) | 30 | 40 |
Design Spec | 生成设计文档 | 10 | 15 |
Design Revie | 设计复审(和同事审核设计文档) | 20 | 30 |
Coding Standard | 代码规范 | 30 | 40 |
Design | 具体设计 | 45 | 60 |
Coding | 具体编码 | 240 | 300 |
Code Review | 代码复审 | 30 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 20 | 30 |
Reporting | 报告 | 30 | 40 |
Test Report | 测试报告 | 20 | 20 |
Size Measurement | 计算工作量 | 5 | 5 |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改机计划 | 20 | 30 |
7. 我的小伙伴
我和我的小伙伴是同宿舍的,马上就一块度过了大学的第三个年头了,彼此都比较了解,她是一个动手能力挺强,很有想法的菇凉。我们俩在对软件需求分析后,基本达成了一个整体的软件框架,将项目划分为5个模块。在接下来的模块编程中,她给出了好几点很不错的建议,尤其是做界面与计时器的过程中。当然,我们俩也会遇到不同想法碰撞的时候,这时,她并不是妥协或者态度比较强硬,我们会对两种想法做出权衡,达成共识。对于项目中我主导编写的模块不理解时,她总会积极询问,就是这样的一个菇凉,我们一同协作完成了我们的初衷。但是我的小伙伴在程序设计的模块划分以及模块间关系处理上存在一定的问题,尤其是模块间的相互联系、调用时,一定要做到数据集的高效共享,希望她可以多练习一下数据结构的内容。
嗯,总的来说呢,很不错的菇凉,期待我们下次的合作。
8. 结对编程的感受和体会
本次结对项目真心感觉到1+1>2的效果,我的小伙伴动手能力也挺强的,我们在做了分析之后,利用周内的三天课余时间来开发软件,时间的利用率还蛮高的,不会出现一个人卡壳的现象。结对编程的过程也挺愉快的,正好赶上实验室的茉莉花开,在淡淡的芳香中,坐下来编几个小时的程序,顺便开发开发大脑,也没有感觉到枯燥。但是,不得不说结对编程能够达到双赢的效果是有前提的,你需要一个负责的伙伴,So,选择伙伴是挺重要的哦。
本次项目开发过程,其实也是一个“捡起”java的过程,以前上课时学的基础好的话,现在复习一下,还是挺好掌握它的。我们做的小学生四则运算软件实现了老师的要求,也做了附加功能,但关于语言的附加功能没有做到,本来想着做成App的,但是由于我们俩都有考研课且近期参加了编程比赛,时间紧张,就用eclipse做了简单的界面,不太美观,希望后期我们可以有所改进。