题目描述:
不知道大家是否尝试过这样一种开发模式:你有一个伙伴,你们坐在一起,并肩作战,面对着同一台显示器,使用着同一键盘,同一个鼠标,你们一起思考,一起分析,一起编程?这次,就让我们来体验一下结对编程的魅力:
http://www.cnblogs.com/xinz/archive/2011/08/07/2130332.html
我们在个人作业1中,用各种语言实现了一个命令行的四则运算小程序。进一步,本次要求把这个程序做成GUI(可以是Windows PC 上的,也可以是Mac、Linux,web,手机上的),成为一个有基本功能、一定价值的程序。在下面的功能需求中实现两个:
- 记录用户的对错总数,程序退出再启动的时候,能把以前的对错数量保存并在此基础上增量计算。
- 有计时功能,能显示用户开始答题后的消耗时间。
- 界面支持中文简体/中文繁体/英语,用户可以选择一种;
从题目要求中我们选择了1和2两个功能,即实现记录用户对错题数和计时功能。
码市地址:https://coding.net/u/lzx84/p/Calculation/git
一、队员组成以及分工情况
队员有: 201421123062(林燕) 201421123084(林至贤)
实现记录用户的对错题数由林至贤完成,我(林燕)实现显示用户开始答题后的消耗时间。整体的一起讨论完成。
编程过程使用了QQ的屏幕共享,一个人写的时候,另一个人在观看,并通过语音互相交流想法。


需求分析(新功能):
- 记录用户的对错总数,程序退出再启动的时候,能把以前的对错数量保存并在此基础上增量计算。(使用session存放统计对象列表的方法,一个对象相当于一次操作(感觉应该使用cookie,可是做了好久没法实现))
- 有计时功能,能显示用户开始答题后的消耗时间。(使用js的计时代码,使用获取两次系统时间相见计算用时。(因为JS不怎么熟,不怎么懂得用JS获取具体用时))
- 界面支持中文简体/中文繁体/英语,用户可以选择一种;(未实现)
二、程序设计过程
我们讨论了两个人的第一次四则运算的代码,考虑到我之前的代码没有很好地封装对象,便决定用至贤的第一次成果来做基础,在他之前的基础上改进,增加了一个新的对象,以便于后面的统计。我们用了jsp来写页面,一共设计了四个页面,具体看图:
新增类:

流程:

三、核心代码展示
index.jsp:
1 <%@ page language="java" import="java.util.*"
2 contentType="text/html; charset=UTF-8"%>
3 <html>
4
5 <head>
6 <meta http-equiv="Content-Language" content="zh-cn">
7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
8 <title>提交</title>
9 </head>
10
11 <body
12 style="background-image: url('images/background.jpg');background-position: center;">
13 <p></p>
14 <p align="center">
15 <font face="华文彩云" size="7">四则运算器</font>
16 </p>
17 <form method="POST" action="show.jsp">
18 <p align="center">
19 请输入需要的题目数量:<input name="n" type="text" onkeyup="this.value=this.value.replace(/D/g,'')"
20 onafterpaste="this.value=this.value.replace(/D/g,'')" /> <!--规定用户只能输入数字-->
21
22 <input type="submit" value="确认"
23 name="B1">
24 </p>
25
26 </form>
27 <P align="center"><a href="showHistory.jsp">查看历史成绩</a></P>
28
29
30
31
32 </body>
33
34 </html>
show.jsp:
1 <%@page import="model.*" import="methods.*"%>
2 <%@page language="java" import="java.util.*"
3 contentType="text/html; charset=UTF-8"%>
4 <%
5 String path = request.getContextPath();
6 String basePath = request.getScheme() + "://"
7 + request.getServerName() + ":" + request.getServerPort()
8 + path + "/";
9 %>
10
11 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
12 <html>
13 <head>
14 <base href="<%=basePath%>">
15
16 <title>My JSP 'show.jsp' starting page</title>
17
18 <meta http-equiv="pragma" content="no-cache">
19 <meta http-equiv="cache-control" content="no-cache">
20 <meta http-equiv="expires" content="0">
21 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
22 <meta http-equiv="description" content="This is my page">
23 <!--
24 <link rel="stylesheet" type="text/css" href="styles.css">
25 -->
26
27 </head>
28
29 <body>
30 <div align="center" >
31 <form method="POST" action="showResult.jsp"><%
32
33 int op = 0;
34 int n = Integer.parseInt(request.getParameter("n"));
35 ArrayList<Fraction> resultlist = new ArrayList<Fraction>();//创建结果列表,存放答案
36 ArrayList<String> titlelist = new ArrayList<String>();//创建题目列表,存放题目
37 String title = "";
38 for (int i = 1; i <= n; i++) {
39 Fraction f1 = Dofrac.CreatFrac();
40 Fraction f2 = Dofrac.CreatFrac();
41 op = (int) (Math.random() * 4 + 1);
42 Fraction result = new Fraction();
43 %><div>
44 <p>
45 <%
46 switch (op) {
47 case 1: {
48 result = Calculate.add(f1, f2);
49 title = "第" + i + "题:" + f1.toString() + "+"
50 + f2.toString() + "=";
51 out.println(title);
52 break;
53
54 }
55 case 2: {
56 if (!Calculate.compare(f1, f2)) {
57 Fraction temp = f1;
58 f1 = f2;
59 f2 = temp;
60 }
61 result = Calculate.sub(f1, f2);
62 title = "第" + i + "题:" + f1.toString() + "-"
63 + f2.toString() + "=";
64 out.println(title);
65 break;
66 }
67 case 3: {
68 result = Calculate.mul(f1, f2);
69 title = "第" + i + "题:" + f1.toString() + "*"
70 + f2.toString() + "=";
71 out.println(title);
72 break;
73 }
74 case 4: {
75 if (f2.getFenzi() == 0) {
76 f2.setFenzi((int) (1 + Math.random() * (10 - 1 + 1)));
77 }
78 result = Calculate.div(f1, f2);
79 title = "第" + i + "题:" + f1.toString() + "÷"
80 + f2.toString() + "=";
81 out.println(title);
82 break;
83 }
84 }
85 resultlist.add(result);
86 titlelist.add(title);
87
88
89
90
91 %>
92 <input type="text" name="s<%out.print(i);%>" size="20"
93 style=" 38px;">
94 <input type="hidden" name="time" value=<%=System.currentTimeMillis() %>
95 style=" 38px;"><!--获得系统时间-->
96
97
98 </p>
99
100 </div>
101 <%
102 }
103 %>
104 <input type="submit" value="提交">
105 </form>
106 </div>
107 <%
108 session.setAttribute("n", n);
109 session.setAttribute("resultlist", resultlist);
110 session.setAttribute("titlelist", titlelist);
111 //将用户输入的n值,结果列表与题目列表存入session
112 %>
113 <div align="center" id="showTimes"></div>
114 <%
115 long current_time = 0;
116 %>
117 <script>
118 var second =
119 <%=current_time / 1000%>
120 ; //秒数
121
122 // 写一个方法,将秒数转换为分钟以及小时
123 var toMinites = function() {
124 var s = second % 60;
125 var mi = (second - s) / 60 % 60; // 分钟
126 var h = ((second - s) / 60 - mi) / 60 % 24; // 小时
127 return h + ":" + mi + ":" + s;
128 }
129 function getTime() {
130 return toMinites;
131 }
132
133 //计时器
134 window.setInterval(function() {
135 second++;
136 document.getElementById("showTimes").innerHTML = toMinites();
137 }, 1000);
138 </script>
139 </body>
140 </html>
showResult.jsp:
<%@page import="org.apache.taglibs.standard.tag.common.core.ForEachSupport"%>
<%@page import="model.*" import="methods.*"%>
<%@page language="java" import="java.util.*"
contentType="text/html; charset=UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'show2.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<%
long nowTime = System.currentTimeMillis();//得到用户做完题目之后的时间
ArrayList<Fraction> resultlist = (ArrayList<Fraction>) session.getAttribute("resultlist");
int n = (Integer) session.getAttribute("n");
ArrayList<String> titlelist = (ArrayList<String>) session.getAttribute("titlelist");
//从session中得到需要的数据
String input;
int flag=0;//错题数
String time=(nowTime-Long.parseLong(request.getParameter("time")))/1000+"秒";//将两个时间相减,得到用时
Fraction result = new Fraction();
ArrayList<String> wrongList = new ArrayList<String>();//新建错题集
Statistics st = new Statistics();
for (int i = 1; i <= n; i++) {
%>
<p>
<%
out.print(titlelist.get(i - 1));
input = (String) request.getParameter("s" + i);
if (Dofrac.check(input)) {
out.print(" (你的答案是:" + input+")");
} else {
out.print("(非法输入,答案作废)");
}
result = resultlist.get(i - 1);
if (input.equals(result.toString())) {
out.print("————恭喜你!回答正确");
} else {
out.print("————回答错误,正确答案是:" + result.toString());
flag++;
wrongList.add(titlelist.get(i - 1));
}
}
%>
</p>
<hr>
<p>
<%
String acciracy=(n-flag+0.0)/n*100+"%";//计算正确率
out.print("你作对了"+(n-flag)+"题,做错了"+flag+"题,正确率为:"+acciracy+",用时为:"+time);
st.setAcciracy(acciracy);
st.setTime(time);
st.setWrongNum(flag);
st.setWrongTitle(wrongList);
ArrayList<Statistics> stList =((ArrayList<Statistics>)session.getAttribute("stList")==null)?new ArrayList<Statistics>():(ArrayList<Statistics>)session.getAttribute("stList");
stList.add(st);
session.setAttribute("stList", stList);
//新建或从session中取得Statistic列表,将此次计算的statistics对象存入。(感觉这里用cookie更合适,不过不会用。。)
%>
</p>
<a href="index.jsp">再做一次</a>
</body>
</html>
showHistory.jsp
1 <%@page import="model.*" import="methods.*"%>
2 <%@page language="java" import="java.util.*"
3 contentType="text/html; charset=UTF-8"%>
4 <%
5 String path = request.getContextPath();
6 String basePath = request.getScheme() + "://"
7 + request.getServerName() + ":" + request.getServerPort()
8 + path + "/";
9 %>
10
11 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
12 <html>
13 <head>
14 <base href="<%=basePath%>">
15
16 <title>My JSP 'show3.jsp' starting page</title>
17
18 <meta http-equiv="pragma" content="no-cache">
19 <meta http-equiv="cache-control" content="no-cache">
20 <meta http-equiv="expires" content="0">
21 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
22 <meta http-equiv="description" content="This is my page">
23 <!--
24 <link rel="stylesheet" type="text/css" href="styles.css">
25 -->
26
27 </head>
28
29 <body>
30
31 <input type="button" value="返回上一级" onclick="javascript:history.back();">
32 <br>
33 <br>
34 <div align="center">
35 <%
36 ArrayList<Statistics> stList = (ArrayList<Statistics>) session
37 .getAttribute("stList");//获取session中的statistics列表。遍历输出。
38 if (stList == null) {
39 out.print("没有记录");
40 } else {
41 for (int i = 0; i < stList.size(); i++) {
42 %>
43 <div>
44 <%
45 out.print("第"+(i+1)+"次做题:");
46
47 %><br>
48 <%
49 out.print("---------------------------------------------------");
50
51 %><br>
52
53 <%
54 out.print("错题数:" + stList.get(i).getWrongNum());
55 %><br>
56 <%
57 out.print("用时:" + stList.get(i).getTime());
58 %><br>
59 <%
60 out.print("正确率:" + stList.get(i).getAcciracy());
61 %><br>
62 <%
63 out.print("错题:");
64 %><br>
65 <%
66 for (int j = 0; j < stList.get(i).getWrongTitle().size(); j++) {
67 out.print(stList.get(i).getWrongTitle().get(j));
68 %><br>
69 <%
70 }
71 %><br>
72 <%
73 out.print("---------------------------------------------------");
74
75 %><br>
76 </div>
77
78 <%
79 }
80 }
81 %>
82 </div>
83 </body>
84 </html>
四、程序展示
做题演示:
功能一(存取用户做题数据)演示:
PSP:
|
PSP2.1 |
Personal Software Process Stages |
Estimated Time (h) |
RealTime(h) |
|
Planning |
计划 |
|
|
|
· Estimate |
估计这个任务需要多少时间 |
|
|
|
Development |
开发 |
8 |
9 |
|
· Analysis |
需求分析 (包括学习新技术) |
1 |
2 |
|
· Design Spec |
生成设计文档 |
0.5 |
0.5 |
|
· Design Review |
设计复审 |
0.5 |
0.5 |
|
· Coding Standard |
代码规范 |
1 |
0.5 |
|
· Design |
具体设计 |
2 |
2.5 |
|
· Coding |
具体编码 |
2 |
2 |
|
· Code Review |
代码复审 |
0.5 |
0.5 |
|
· Test |
测试(自我测试,修改代码,提交修改) |
0.5 |
0.5 |
|
Reporting |
报告 |
0.5 |
0.5 |
|
· |
测试报告 |
|
|
|
· |
计算工作量 |
|
|
|
· |
并提出过程改进计划 |
|
五、小结感受
1、结对感受
- 这次结对编程合作的还不错,因为之前课程设计已经合作过一次,不懂的东西一起讨论解决,配合的还可以。刚开始实现界面的时候,首先讨论的是用NetBeans还是Web,由于之前的java以及数据库可设都有涉及到jsp,所以便一致认为用jsp来写。接下来就是整体架构的问题了,讨论了是否用servlet以及整个存储结构用什么等。随后便开始了具体的编程,过程中我发现自己的编程能力和学习新技能的能力都想对比较弱,能感受到队友的力量比较强大,1+1还是大于2的,有的时候一个小错误,还有想的不周到之处可以由队友发现,假如没有队友就可能要花费很多时间和精力来处理。
- 结对编程的过程中我更像驾驶员,由于编程基础比较弱,总是有着这样或者那样的小错误;至贤充当着领航员的角色,把握整体架构,饥饿的时候给我一块面包,走错方向了及时互相拉回来。感谢队友辛苦地指导我,让我体会到结对编程的力量,两个人刚开始的时候也有着这样活着那样的不同想法,就命名来说,我就是要驼峰式的命名方式,但是他可能没那么大要求,觉得那样麻烦,但最终慢慢磨合也得到了一致的结果。
- 不论是团队还是结对,听取队友的意见非常重要,我们要学会如何与他人合作,避免一意孤行或者整个过程都不提任何想法。
2、过程中遇到的困难
在编程过程中遇到的问题都是先百度的,有时候一个小问题要解决很久,比如在用git Import项目到eclipse里面的时候遇到了问题,百度了挺久,参考了下面两篇文章:http://blog.csdn.net/dongchengrong/article/details/56833173
http://blog.csdn.net/hil2000/article/details/8566456
在做动态显示计时的功能时没多大想法,百度了一下用window.setInterval();调用了计时器。过程中出现了时间显示上的乱码,最后问了一些人才解决。
下次要提高查找问题答案的速度,提高动手能力。
