201571030124/201571030130《小学生四则运算练习软件》结对项目报
Github的仓库主页链接地址:https://github.com/Opalus-wangs/Pair-Programming
一、需求分析
任务1:
在《实验二 软件工程个人项目》中,同学们实现了一个命令行四则运算出题小程序,本次实验采用结对编程方式,设计开发一个小学生四则运算练习软件,使之具有以下功能:
(1)由计算机从题库文件中随机选择20道加减乘除混合算式,用户输入算式答案,程序检查答案是否正确,每道题正确计5分,错误不计分,20道题测试结束后给出测试总分;
(2)题库文件可采用实验二的方式自动生成,也可以手工编辑生成,文本格式如下:
(3)程序为用户提供三种进阶四则运算练习功能选择:百以内整数算式(必做)、带括号算式、真分数算式练习;
(4)程序允许用户进行多轮测试,提供用户多轮测试分数柱状图,示例如下:
(5)程序记录用户答题结果,当程序退出再启动的时候,可为用户显示最后一次测试的结果,并询问用户可否进行新一轮的测试;
(6)测试有计时功能,测试时动态显示用户开始答题后的消耗时间。
(7)程序人机交互界面是GUI界面(WEB页面、APP页面都可),界面支持中文简体(必做)/中文繁体/英语,用户可以进行语种选择。
二、软件设计
1.流程图
2.类图
三、核心代码
计时部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | import java.util.Timer; import java.util.TimerTask; public class time { public Timer timer= new Timer(); public boolean is_pause= false ; public timetask mytimetask= new timetask(); public int hh,mm,ss; String a; public time() { timer.scheduleAtFixedRate(mytimetask, 0 , 1000 ); } public class timetask extends TimerTask{ public int count_time= 0 ; public String date; @Override public void run() { if (!is_pause) { count_time++; hh=count_time/ 3600 ; mm=(count_time% 3600 )/ 60 ; ss=count_time% 60 ; date=hh+ ":" +mm+ ":" +ss; a=date; } } } } |
结果计算:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | //表达式计算 import java.math.BigDecimal; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Calculate { public static int arithmetic(String exp) { String result = parseExp(exp).replaceAll( "[\\[\\]]" , "" ); return ( int )Double.parseDouble(result); } public static String parseExp(String expression) { expression=expression.replaceAll( "\\s+" , "" ).replaceAll( "^\\((.+)\\)$" , "$1" ); String checkExp= "\\d" ; String minExp= "^((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\+\\-\\*\\/]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))$" ; //最小表达式计算 if (expression.matches(minExp)) { String result=calculate(expression); return Double.parseDouble(result)>= 0 ?result: "[" +result+ "]" ; } //计算不带括号的四则运算 String noParentheses= "^[^\\(\\)]+$" ; String priorOperatorExp= "(((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\*\\/]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\])))" ; String operatorExp= "(((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\+\\-]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\])))" ; if (expression.matches(noParentheses)) { Pattern patt=Pattern.compile(priorOperatorExp); Matcher mat=patt.matcher(expression); if (mat.find()) { String tempMinExp=mat.group(); expression=expression.replaceFirst(priorOperatorExp, parseExp(tempMinExp)); } else { patt=Pattern.compile(operatorExp); mat=patt.matcher(expression); if (mat.find()) { String tempMinExp=mat.group(); expression=expression.replaceFirst(operatorExp, parseExp(tempMinExp)); } } return parseExp(expression); } //计算带括号的四则运算 String minParentheses= "\\([^\\(\\)]+\\)" ; Pattern patt=Pattern.compile(minParentheses); Matcher mat=patt.matcher(expression); if (mat.find()) { String tempMinExp=mat.group(); expression=expression.replaceFirst(minParentheses, parseExp(tempMinExp)); } return parseExp(expression); } public static String calculate(String exp) { exp=exp.replaceAll( "[\\[\\]]" , "" ); String number[]=exp.replaceFirst( "(\\d)[\\+\\-\\*\\/]" , "$1," ).split( "," ); BigDecimal number1= new BigDecimal(number[ 0 ]); BigDecimal number2= new BigDecimal(number[ 1 ]); BigDecimal result= null ; String operator=exp.replaceFirst( "^.*\\d([\\+\\-\\*\\/]).+$" , "$1" ); if ( "+" .equals(operator)) { result=number1.add(number2); } else if ( "-" .equals(operator)) { result=number1.subtract(number2); } else if ( "*" .equals(operator)) { result=number1.multiply(number2); } else if ( "/" .equals(operator)) { result=number1.divide(number2, 2 , BigDecimal.ROUND_HALF_EVEN); } return result!= null ?result.toString(): null ; } } |
柱状图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.util.ArrayList; import java.util.Random; import javax.swing.JFormattedTextField; import javax.swing.JFrame; import javax.swing.JTextArea; //绘制柱状图 public class Picture extends JFormattedTextField { int [] a= new int [ 20 ]; int j= 0 ; int i= 0 ; int x= 0 ; int aa= 0 ; //绘制柱形统计图 private Random ran; public Picture(ArrayList<Student> students) { super (); for (Student e: students ) { a[j]=(e.getw()); j++; } ran = new Random(); setName( "绘制柱形图" ); setBounds( 100 , 85 , 270 , 210 ); } @Override public void paint(Graphics g){ int Width = getWidth(); int Height = getHeight(); int leftMargin = 2 ; //柱形图左边界 int topMargin = 5 ; //柱形图上边界 Graphics2D g2 = (Graphics2D) g; int ruler = Height-topMargin- 5 ; int rulerStep = ruler/ 10 ; //将当前的高度评分为10个单位 g2.setColor(Color.WHITE); //绘制白色背景 g2.fillRect( 0 , 0 , Width, Height); //绘制矩形图 g2.setColor(Color.LIGHT_GRAY); for ( int i= 0 ;i<= 10 ;i++){ //绘制灰色横线和百分比 g2.drawString(( 100 - 10 *i)+ "%" , 5 , topMargin+rulerStep*i); //写下百分比 g2.drawLine( 5 , topMargin+rulerStep*i, Width, topMargin+rulerStep*i); //绘制灰色横线 } g2.setColor(Color.RED); for (i= 0 ;i<j;i++){ //绘制柱形图 int value =( 20 -a[i])* 10 + 5 ; int step = (i+ 1 )* 20 ; //设置每隔柱形图的水平间隔为40 //绘制矩形 g2.fillRoundRect(leftMargin+step* 2 , Height-value, 20 , value, 20 , 20 ); g2.drawString( "C" +(i+ 1 )+ "-" +( 20 -a[i])* 5 + "%" , leftMargin+step* 2 , Height-value- 5 ); } } } |
四、程序运行
1.首先是主界面:
2.点击简单后,出现用户登录的界面,用户登录完成后,点击确定:
3.出现做题界面:
4.点击开始计时时,并开始做题:
5.如果我们没有答完题,提交的时候才能提示信息:
6.做完点击提交,出现成绩和错误题号,并且画出柱状图:
7.点击继续,选择复杂计算:
8.显示结果:
9.点击查看:
五、结对编程过程
六、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,我想说一声谢谢。在本次结对编程中,我们并不是一帆风顺,遇到了很多的困难,但我们都没有选择放弃,而是在互相鼓励中,成功完成了实验。我的partner她是一个动手能力很强,且有自己独特想法的同学,在实验过程中,以其熟练的编程能力,删掉了我冗余代码,使得程序的结构更加清楚明了,代码也更加的规范,这一点值得我去学习,还有一点就是对待事情认真的态度,例如在每添加一个控件的时候,都极力的使其对称整体,可以说是一丝不苟。总的来说,这次的结对编程很快乐,在不知不觉中就完成了实验,没有往日做实验的枯燥,相反,更愿意讨论彼此对问题的想法。这也增加我们解决问题的信心和动力。谢谢我们都不曾放弃无所畏惧自己。
八、 结对编程真的能够带来1+1>2的效果吗?通过这次结对编程,请谈谈你的感受和体会。
通过本次结对编程,我觉得是结对编程1+1>2的,因为在实验过程中,我确切的感受到了合作的重要性,当一个人的想法不正确的时候,你的同伴可以很快的提醒你,两个人一起讨论问题,可以更快的解决问题,可以有很多新的想法产生。而且当你遇到困难的时候,你也不会轻易的放弃,因为你的同伴还在努力尝试着。两个人一起编程,你感觉不到编程的枯燥与乏味,反而是很轻松,很愉快,很享受彼此讨论自己想法的过程。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 数据库服务器 SQL Server 版本升级公告
· 程序员常用高效实用工具推荐,办公效率提升利器!
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)