Github的仓库主页链接地址:https://github.com/Opalus-wangs/Pair-Programming
一、需求分析
任务1:
在《实验二 软件工程个人项目》中,同学们实现了一个命令行四则运算出题小程序,本次实验采用结对编程方式,设计开发一个小学生四则运算练习软件,使之具有以下功能:
(1)由计算机从题库文件中随机选择20道加减乘除混合算式,用户输入算式答案,程序检查答案是否正确,每道题正确计5分,错误不计分,20道题测试结束后给出测试总分;
(2)题库文件可采用实验二的方式自动生成,也可以手工编辑生成,文本格式如下:
(3)程序为用户提供三种进阶四则运算练习功能选择:百以内整数算式(必做)、带括号算式、真分数算式练习;
(4)程序允许用户进行多轮测试,提供用户多轮测试分数柱状图,示例如下:
(5)程序记录用户答题结果,当程序退出再启动的时候,可为用户显示最后一次测试的结果,并询问用户可否进行新一轮的测试;
(6)测试有计时功能,测试时动态显示用户开始答题后的消耗时间。
(7)程序人机交互界面是GUI界面(WEB页面、APP页面都可),界面支持中文简体(必做)/中文繁体/英语,用户可以进行语种选择。
二、软件设计
1.流程图
2.类图
三、核心代码
计时部分:
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;
}
}
}
}
结果计算:
//表达式计算
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;
}
}
柱状图:
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的,因为在实验过程中,我确切的感受到了合作的重要性,当一个人的想法不正确的时候,你的同伴可以很快的提醒你,两个人一起讨论问题,可以更快的解决问题,可以有很多新的想法产生。而且当你遇到困难的时候,你也不会轻易的放弃,因为你的同伴还在努力尝试着。两个人一起编程,你感觉不到编程的枯燥与乏味,反而是很轻松,很愉快,很享受彼此讨论自己想法的过程。