201571030314/201571030316《小学生四则运算练习软件》结对项目
结对编程实现小学生四则运算练习软件
前言:按照结对编程的原则,我和邻宿舍的小伙伴进行了两人结对编程,我们开发的结对项目的是小学生四则运算练习软件,具体就是随机生成n道题,供学生答题并返回正误记录答题结果,进行多轮。具体需求分析以及功能设计与实现如下。
github代码地址:https://github.com/mqqgd/Experiment2
一、需求分析
本次实验采用结对编程方式,设计开发一个小学生四则运算练习软件,使之具有以下功能:
- 由计算机从题库文件中随机选择20道加减乘除混合算式,用户输入算式答案,程序检查答案是否正确,每道题正确计5分,错误不计分,20道题测试结束后给出测试总分;
- 题库文件可采用实验二的方式自动生成,也可以手工编辑生成,文本格式如下:
- 程序为用户提供三种进阶四则运算练习功能选择:百以内整数算式(必做)、带括号算式、真分数算式练习;
- 程序允许用户进行多轮测试,提供用户多轮测试分数柱状图,示例如下:
- 程序记录用户答题结果,当程序退出再启动的时候,可为用户显示最后一次测试的结果,并询问用户可否进行新一轮的测试;
- 测试有计时功能,测试时动态显示用户开始答题后的消耗时间。
- 程序人机交互界面是GUI界面(WEB页面、APP页面都可),界面支持中文简体(必做)/中文繁体/英语,用户可以进行语种选择。
二、功能设计与实现
- 软件设计类图
- 核心功能代码展示
import java.util.Random; public class GetRandomDigit { private Random random; public GetRandomDigit(){ random=new Random(); } int oprator(){ return random.nextInt(4)+1; } int Time(){ return random.nextInt(3)+3; } int randomDigit(){ return random.nextInt(100); } int probabilityQuestion(){ return random.nextInt(200); } int BracketsIndex(int time){ return random.nextInt(time-2); } } 随机出题
public class LinkSql { private static final String url = "jdbc:mysql://127.0.0.1:3306/mqqgd"; private static final String user = "root"; private static final String password = "root"; private static ResultSet ret = null; private static final String name = "com.mysql.jdbc.Driver"; public Connection conn = null; public PreparedStatement pst = null; public LinkSql() { try { Class.forName(name);//指定连接类型 conn = DriverManager.getConnection(url, user, password);//获取连接 System.out.println("数据库链接成功"); } catch (Exception e) { e.printStackTrace(); } } public void changeMySqlDate(String sql) { try { pst=conn.prepareStatement(sql); pst.executeUpdate(); System.out.println("接收到修改数据库命令"+sql); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public ResultSet selectSqlDate(String sql) { try { System.out.println("接收到查询数据库命令"+sql); pst=conn.prepareStatement(sql); ret = pst.executeQuery(); return ret; } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } public void closeMySql() { try { this.conn.close(); } catch (SQLException e) { e.printStackTrace(); } } @SuppressWarnings("static-access") public void closeChart() { try { this.pst.close(); this.ret.close(); } catch (SQLException e) { e.printStackTrace(); } } } 链接数据库
import java.util.HashMap; import java.util.Stack; public class ArithmeticResult { public Double Result(String formula) { Stack<Double> s1 = new Stack<Double>(); Stack<String> s2 = new Stack<String>(); HashMap<String, Integer> hashMap = new HashMap<String, Integer>(); hashMap.put("(", 0); hashMap.put("+", 1); hashMap.put("-", 1); hashMap.put("×", 2); hashMap.put("÷", 2); for (int i = 0; i < formula.length();) { StringBuffer digit = new StringBuffer(); char c = formula.charAt(i); while (Character.isDigit(c) || c == '.') { digit.append(c); i++; c = formula.charAt(i); } if (digit.length() == 0) { switch (c) { case '(': { s2.push(String.valueOf(c)); break; } case ')': { String stmp = s2.pop(); while (!s2.isEmpty() && !stmp.equals("(")) { double a = s1.pop(); double b = s1.pop(); double sresulat = calcDouble(b, a, stmp); s1.push(sresulat); stmp = s2.pop(); } break; } case '=': { String stmp; while (!s2.isEmpty()) { stmp = s2.pop(); double a = s1.pop(); double b = s1.pop(); double sresulat = calcDouble(b, a, stmp); s1.push(sresulat); } break; } default: { String stmp; while (!s2.isEmpty()) { stmp = s2.pop(); if (hashMap.get(stmp) >= hashMap.get(String.valueOf(c))) { double a = s1.pop(); double b = s1.pop(); double sresulat = calcDouble(b, a, stmp); s1.push(sresulat); } else { s2.push(stmp); break; } } s2.push(String.valueOf(c)); break; } } } else { s1.push(Double.valueOf(digit.toString())); continue; } i++; } return s1.peek(); } public double calcDouble(double a, double b, String stmp) { double res = 0f; char s = stmp.charAt(0); switch (s) { case '+': res = a + b; break; case '-': res = a - b; break; case '×': res = a * b; break; case '÷': res = a / b; break; } return res; } } 计算过程
//从这里开始 CategoryPlot plot=chart.getCategoryPlot();//获取图表区域对象 CategoryAxis domainAxis=plot.getDomainAxis(); //水平底部列表 domainAxis.setLabelFont(new Font("黑体",Font.BOLD,14)); //水平底部标题 domainAxis.setTickLabelFont(new Font("宋体",Font.BOLD,12)); //垂直标题 ValueAxis rangeAxis=plot.getRangeAxis();//获取柱状 rangeAxis.setLabelFont(new Font("黑体",Font.BOLD,15)); chart.getLegend().setItemFont(new Font("黑体", Font.BOLD, 15)); chart.getTitle().setFont(new Font("宋体",Font.BOLD,20));//设置标题字体 //到这里结束,虽然代码有点多,但只为一个目的,解决汉字乱码问题 //这里也可以用chartFrame,可以直接生成一个独立的Frame frame1=new ChartPanel(chart,true); } private CategoryDataset getDataSet() { DefaultCategoryDataset dataset = new DefaultCategoryDataset(); System.out.println(times); for(int i=0;i<times;i++){ System.out.println("lalal"); dataset.addValue(result[i],"第"+(i+1)+"轮","第"+(i+1)+"轮"); } return dataset; } public ChartPanel getChartPanel(){ return frame1; } } 绘制柱状图
import javax.swing.JFrame; @SuppressWarnings("serial") public class Tongji extends JFrame{ PieChart pic; int time; int [] result; public Tongji(int[] result,int time){ this.time=time; this.result=result; setFrame(); } //登陆界面 private void setFrame(){ System.out.println(time); pic=new PieChart(result,time); this.setTitle("您最终的得分统计"); this.setSize(600,400); this.setLocationRelativeTo(null); this.setResizable(false); this.setVisible(true); this.add(pic.getChartPanel()); } } 统计分数
- 测试运行
1.登录界面
2.数据库
3.做题界面
4.答题结束时,自动显示柱状图
三、结对过程
我的小伙伴:马兰
她的学号:201571030316
她的博客地址:http://www.cnblogs.com/mqqgd/p/8708953.html
以下就是我们讨论时的照片啦~
四、PSP
PSP2.1 |
任务内容 |
计划共完成需要的时间(min) |
实际完成需要的时间(min) |
Planning |
计划 |
20 |
16 |
· Estimate |
· 估计这个任务需要多少时间,并规划大致工作步骤 |
20 |
16 |
Development |
开发 |
1838 |
1736 |
·· Analysis |
需求分析 (包括学习新技术) |
20 |
20 |
· Design Spec |
· 生成设计文档 |
25 |
25 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
10 |
10 |
· Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
3 |
3 |
· Design |
具体设计 |
300 |
240 |
· Coding |
具体编码 |
1440 |
1400 |
· Code Review |
· 代码复审 |
10 |
8 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
30 |
30 |
Reporting |
报告 |
33 |
30 |
·· Test Report |
· 测试报告 |
3 |
2 |
· Size Measurement |
计算工作量 |
10 |
8 |
· Postmortem & Process Improvement Plan |
· 事后总结 ,并提出过程改进计划 |
20 |
20 |
五、用汉堡评价法给小伙伴的点评
我的小伙伴是一个学习能力很强的人,在整个合作过程中合作非常愉快,她的优点是想到什么了就会去做去学,很细心。刚开始拿到这个题目,两个人都比较苦恼,不知道如何去实现,后来小伙伴给的建议是分工合作,突然有了紧迫感,我们查阅了相关的资料,感觉时间越来越近的时候就会督促她。当正式着手去做的时候并没有按之前分工好的去做,因为两人的编程能力都不是很强(她比我好很多),而是把彼此的想法都提出来进行了汇总,最后一起一步一步进行了实现。她是一个很有趣的人,在合作的过程中也不会感到乏味。在写这篇博客的时候,有遗漏的地方她也会提醒我加上。
六、结对编程真的能够带来1+1>2的效果吗?通过这次结对编程,请谈谈你的感受和体会
这次与另外同学的结对编程,发现自己某些方面的不足,某些考虑不全面,结对小伙伴都可以一针见血的指出,同时两个人同时编程感觉更高效考虑的更全面,如果是很多人同时开发,几个人之间的沟通就成很大问题,不一定就有结对编程的效率高。真正体会到1+1>=2的效果了,在项目进行的初期阶段分工明确,使得我们互相督促,之后因为程序的问题,然后就一起做并解决问题。由于是邻舍,讨论问题也很方便,一人在负责自己分工的同时,另一人则也出谋划策,遇到困难的地方在彼此的帮助下也都迎刃而解了。在这次项目的过程中,我们也通过不断的请教大神,学到了很多东西, 通过这次的结对项目觉得终于完成了一次又有趣又有成就感的项目。