java 结对编程_结对编程(Java实现)

GitHub地址

https://github.com/Importlif/ARi

PSP表格

PSP2.1

Personal Software Process Stages

预估耗时(分钟)

实际耗时(分钟)

Planning

计划

60

80

· Estimate

· 估计这个任务需要多少时间

60

80

Development

开发

2880

3100

· Analysis

· 需求分析 (包括学习新技术)

240

200

· Design Spec

· 生成设计文档

120

100

· Design Review

· 设计复审 (和同事审核设计文档)

60

100

· Coding Standard

· 代码规范 (为目前的开发制定合适的规范)

120

150

· Design

· 具体设计

240

300

· Coding

· 具体编码

1800

2000

· Code Review

· 代码复审

120

100

· Test

· 测试(自我测试,修改代码,提交修改)

180

150

Reporting

报告

300

280

· Test Report

· 测试报告

120

100

· Size Measurement

· 计算工作量

60

80

· Postmortem & Process Improvement Plan

· 事后总结, 并提出过程改进计划

120

100

合计

3240

3460

效能分析

在讨论如何生成题目的过程中,我们两人有不同的想法,一种是利用字符串类型String去生成并存储生成的题目,另一种想法是通过结合两个数组分别去存储运算数和运算符号,在经过性能分析、运算量分析、实现的复杂度等过程后,我们认为采用第一种方法的效率可能会更高。

同时在做完项目后,通过查阅网上资料,发现在四则运算中可以采用后缀表达式的方法,对比我们的计算方法,后缀表达式的算法在速度上应该是更胜一筹的,但是要占用额外的栈开销,各有各的优点。而且我们的计算方法,可以模拟人的计算过程,给出一步一步的计算过程,有助于使用者分析中间结果

在查重的算法方面,我们的想法是遇到相同结果的题目再拿出来判断是否能通过变换获得,但是后来我们觉得,在混合了整数、分数、真分数的四则运算中,出现重复的概率是极小的只要当给定的范围够大(在10左右就基本不可能重复了),因此我们决定,当出现结果重复时直接重新生成一道题目,减少计算量。

程序结构

82f40a73ab5745ba0781fe77c9f56dc5.png

关键代码说明

计算结果函数

String cuclate(String str)

{while(str.indexOf("÷")!=-1||str.indexOf("×")!=-1)

{intpos;for(pos=0;;pos++)

{if(str.charAt(pos)=='×'||str.charAt(pos)=='÷')

{break;

}

}intmark;

String leftStr="";

mark= pos - 1;while (mark >= 0 && (str.charAt(mark) != '+' && str.charAt(mark) != '-' && str.charAt(mark) != '×' && str.charAt(mark) != '÷'))

{

mark--;

}if (mark > 0)

{

leftStr= str.substring(0,mark+1);

}

mark++;

String sub=str.substring(mark, pos);long i=Long.parseLong(sub.substring(0,sub.indexOf("’")));long i1=Long.parseLong(sub.substring(sub.indexOf("’")+1,sub.indexOf("/")));long i2=Long.parseLong(sub.substring(sub.indexOf("/")+1));

String rightStr="";

mark= pos + 1;while (mark < str.length() && (str.charAt(mark) != '+' && str.charAt(mark) != '-' && str.charAt(mark) != '×' && str.charAt(mark) != '÷'))

{

mark++;

}

mark--;if (mark < str.length()-1)

{

rightStr= str.substring(mark+1);

}

String sub1=str.substring(pos+1, mark+1);long j=Long.parseLong(sub1.substring(0,sub1.indexOf("’")));long j1=Long.parseLong(sub1.substring(sub1.indexOf("’")+1,sub1.indexOf("/")));long j2=Long.parseLong(sub1.substring(sub1.indexOf("/")+1));if (str.charAt(pos)=='×')

{long result[]=multiply(new long[] {i,i1,i2},new long[] {j,j1,j2});

str=leftStr+Long.toString(result[0])+"’"+Long.toString(result[1])+"/"+Long.toString(result[2])+rightStr;

}else{long result[]=devided(new long[] {i,i1,i2},new long[] {j,j1,j2});

str=leftStr+Long.toString(result[0])+"’"+Long.toString(result[1])+"/"+Long.toString(result[2])+rightStr;

}

}while(str.indexOf("+")!=-1||str.indexOf("-")!=-1)

{intpos;for(pos=0;;pos++)

{if(str.charAt(pos)=='+'||str.charAt(pos)=='-')

{break;

}

}intmark;

String leftStr="";

mark= pos - 1;while (mark >= 0 && (str.charAt(mark) != '+' && str.charAt(mark) != '-' && str.charAt(mark) != '×' && str.charAt(mark) != '÷'))

{

mark--;

}if (mark > 0)

{

leftStr= str.substring(0,mark+1);

}

mark++;

String sub=str.substring(mark, pos);long i=Long.parseLong(sub.substring(0,sub.indexOf("’")));long i1=Long.parseLong(sub.substring(sub.indexOf("’")+1,sub.indexOf("/")));long i2=Long.parseLong(sub.substring(sub.indexOf("/")+1));

String rightStr="";

mark= pos + 1;while (mark

{

mark++;

}

mark--;if (mark < str.length()-1)

{

rightStr= str.substring(mark+1);

}

String sub1=str.substring(pos+1, mark+1);long j=Long.parseLong(sub1.substring(0,sub1.indexOf("’")));long j1=Long.parseLong(sub1.substring(sub1.indexOf("’")+1,sub1.indexOf("/")));long j2=Long.parseLong(sub1.substring(sub1.indexOf("/")+1));if (str.charAt(pos)=='+')

{long result[]=add(new long[] {i,i1,i2},new long[] {j,j1,j2});

str=leftStr+Long.toString(result[0])+"’"+Long.toString(result[1])+"/"+Long.toString(result[2])+rightStr;

}else{long result[]=minus(new long[] {i,i1,i2},new long[] {j,j1,j2});if(result[0]<0||result[1]<0)

{return "false";

}

str=leftStr+Long.toString(result[0])+"’"+Long.toString(result[1])+"/"+Long.toString(result[2])+rightStr;

}

}returnstr;

}public String match(String str)//{

Stack stack=new Stack();for(int i=0;i

{if(str.charAt(i)=='(')

{

stack.push(i);

}if(str.charAt(i)==')')

{int tag=(int) stack.peek();

stack.pop();

String check;

check=cuclate(str.substring(tag+1, i));if(check.equals("false"))

{return "false";

}

str=str.substring(0,tag)+cuclate(str.substring(tag+1,i))+str.substring(i+1);//先算括号里面的,从而去掉括号

i=0;

}

}if(str.length()>0 &&str.indexOf("(")==-1){

str=cuclate(str);//没括号的话直接算

}else str =match(str);returnstr;

}

在match函数中,通过使用栈的方法进行括号匹配,实现有括号先算括号,把遇到的左括号的位置压入栈中,当遇到右括号时,取出栈顶元素,将左右括号之间的式子调用cuclate函数进行计算并返回结果。在cuclate函数中,按照四则运算法则进行计算,先乘除,后加减,计算完成后返回结果。同时在cuclate中遇到减法时检测计算结果,如果出现负数则返回false,并舍弃该题目重新生成。

题目生成函数

public String creator(longr)

{//随机决定生成带分数或分数或整数

int decide = (int)(Math.random() * 3) + 1;

String str ;switch(decide){//真分数二又八分之三表示为2’3/8。

case 1:long sumc = (long)(Math.random() * r-1) + 1;long fenmuc = (long)(Math.random() * r-1) + 2;long fenzic = (long)(Math.random() * fenmuc-1) + 1;while(Euclid(fenmuc,fenzic) != 1) {//生成不可约的分数

fenmuc = (long)(Math.random() * r-1) + 2;

fenzic= (long)(Math.random() * fenmuc-1) + 1;

}

str= String.valueOf(sumc)+"’"+String.valueOf(fenzic)+"/"+String.valueOf(fenmuc);break;case 2:long fenmud = (long)(Math.random() * r-1) + 2;long fenzid = (long)(Math.random() * fenmud-1) + 1;while(Euclid(fenmud,fenzid) != 1) {//生成不可约的分数

fenmud = (long)(Math.random() * r-1) + 2;

fenzid= (long)(Math.random() * fenmud-1) + 1;

}

str= String.valueOf(fenzid)+"/"+String.valueOf(fenmud);break;default:long sum = (long)(Math.random() * r-1) + 1;

str= String.valueOf(sum);break;

}//生成第一个数str

int sign_num = (int)(Math.random() * 3) + 1;//随机决定总共生成多少个数

while(sign_num != 0) { //生成后面的式子

int decide2 = (int)(Math.random() * 3) + 1;//随机决定生成带分数或分数或整数

String str2 ;switch(decide2){//真分数二又八分之三表示为2’3/8。

case 1:long sumc2 = (long)(Math.random() * r-1) + 1;long fenmuc2 = (long)(Math.random() * r-1) + 2;long fenzic2 = (long)(Math.random() * fenmuc2-1) + 1;while(Euclid(fenmuc2,fenzic2) != 1) {//生成不可约的分数

fenmuc2 = (long)(Math.random() * r-1) + 2;

fenzic2= (long)(Math.random() * fenmuc2-1) + 1;

}

str2= String.valueOf(sumc2)+"’"+String.valueOf(fenzic2)+"/"+String.valueOf(fenmuc2);break;case 2:long fenmu2 = (long)(Math.random() * r-1) + 2;long fenzi2 = (long)(Math.random() * fenmu2-1) + 1;while(Euclid(fenmu2,fenzi2) != 1) {//生成不可约的分数

fenmu2 = (long)(Math.random() * r-1) + 2;

fenzi2= (long)(Math.random() * fenmu2-1) + 1;

}

str2= String.valueOf(fenzi2)+"/"+String.valueOf(fenmu2);break;default:long sum2 = (long)(Math.random() * r-1) + 1;

str2= String.valueOf(sum2);break;

}int sign_flag = (int)(Math.random() * 4) + 1;switch(sign_flag){//真分数二又八分之三表示为2’3/8。

case 1:

str= str +"+"+str2;break;case 2:

str= str +"-"+str2;break;case 3:

str= str +"×"+str2;break;default:

str= str +"÷"+str2;int bracket = (int)(Math.random() * 2) + 1;if(bracket == 1 && sign_num != 1 && ( str.indexOf("-")!= -1 ||str.indexOf("+")!= -1)) str = "("+str+")";

}

sign_num--;

}returnstr;

}

生成题目思路:

1.先随机生成一个数:用random()方法,随机决定生成一个数(1或2或3),如果是1,则生成一个带分数,如果是2,则生成一个分数;如果是3,则生成一个整数。作为一个字符串。假如生成“5/8”。

2.再随机生成一个数:用random()方法,随机决定生成一个数(1或2或3),如果是1,则生成一个带分数,如果是2,则生成一个分数;如果是3,则生成一个整数。作为一个字符串。假如生成“9”。

3.再随机生成一个符号将上述两个数拼接起来成为一条式子:用random()方法,随机决定生成一个数(1或2或3或4),如果是1,则生成+,如果是2,则生成-;如果是3,则生成×,如果是4,则生成÷。拼接起来作为一个字符串。假如符号是×,生成的是

5/8×9

4.随机决定是否生成括号,假如生成(5/8×9)

5.随机决定是否重复上面1-4,直到结束。从而形成一条式子。

运行测试

运行演示:

出题:

3d0dab099ca38dd139d23df8f83cdd13.gif

对答案:

9e6faf02d437e56e74e33e333b185aec.gif

用例1:测试对答案功能:题目和答案都为空

3e3f2899b1390fdcafb4c4544f4e7bd9.png

89c94eee45aa13f96daa9fb305c3e333.png

用例2:生成一道题

70a91cd6377eef8100e1f108fc469020.png

1c293eba1106f43d6df2b0758e8f369d.png

用例3:测试对答案功能:题目全是带分数形式,答案正确的9道题。

df4fbc7dbc3d4b99b1fc314b91a09e71.png

e3c1dd092f388cde6f507e5235a5bb14.png

用例4:测试对答案功能:题目全是带分数形式,除了第五第九题,其余答案正确的9道题。

eb9e0b23c67eb757bd069233af065437.png

7cc8c4e224ff32cd7a15a5b7cbfc1be8.png

用例5:测试对答案功能:题目全是带分数形式,部分答案能化简但没化简(算作错误),其余答案正确的一万道题。

89f76d85f0ef664d4fe85e18b0cb0092.png

65be6ad54471baf8f1f64a29c3a2cd07.png

说明我们出题功能里实现的输出是符合需求的,即“真分数在输入输出时采用如下格式,真分数五分之三表示为3/5,真分数二又八分之三表示为2’3/8。”并且具有计算10000道题的能力。

用例6:生成题目全是自然数和真分数,答案正确的10道题,测试出题功能

d288f1b39a7ef1fb33c17a8c7200df1a.png

可见我们的出题功能是符合需求的,即“真分数在输入输出时采用如下格式,真分数五分之三表示为3/5,真分数二又八分之三表示为2’3/8。”而且如第九题,能正确生成括号。

用例7:测试对答案功能:测试题目全是自然数和真分数时的对答案功能,其中答案只有前五题5个正确答案, 后五题无答案

a05c54dfc1dbb60338809bd0a2371695.png

45856b56548615e349a6ca323bde7f03.png

用例8:测试对答案功能:测试题目全是自然数和真分数时的对答案功能

e2c92dc7458f75953d4dc98962d3faf2.png

3229ebab4a96ff1d3fdbdc380d6a9b63.png

题目是自然数和真分数的情况下也能正确检测答案正确性。

用例9:生成题目全是自然数和真分数,答案正确的10000道题,测试大量出题功能

点击出题

a908c19614e8e021b0073a5ac24fe5f9.png

ec43f6e17faf7647d9524a677d305c63.png

ce2679c6ef34eec1aeacd57c6ee6ebe5.png

从开始出题提示框点击确定开始到出题完成用时1秒多。能正确生成括号。无重复题。

题目的数字不超过给定参数20。

用例10:用上述生成的10000道题,测试对答案功能

1e1051adc73856ce0b53a900c86b3d52.png

判断10000题用时和出题10000道差不多,用了1秒多的时间。

7.项目小结

通过这次的结对编程,使我们对编程有了新的认识,在双人模式下,一个人一边写代码,一边说思路,另一个人在旁听,旁听的同学通过边听边看,能发现打代码同学可能出现的一些bug进而及时修正,减少错误可能发生的概率,提升了工作效率。

同时在结对编程的过程中,对于同一个问题可能会有不同的解决办法,通过讨论,我们能得出相对较优的算法,进而提升程序的效率。

同时由于常用语言的不同,在转化方面我们更要去认真了解不同语言实现同一个函数功能之间的差异。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值