软件工程网络15结对编程
链接
1.需求分析
1.弱点分析:
-
启动程序,程序窗口定位在屏幕左上角,操作不是很方便。语言切换也不是以按钮的形式,操作不明显。
-
变量名随意,abcdefg,虽然知道是干什么的,但是进行后续扩写操作逻辑会混乱。
-
测试过程中出现过这种bug,因为源代码没有考虑过1/1的情况。
-
启动复习功能,只是把当前的题目重置一遍,题目不变。并且复习时错题会读入存储错题的文档,导致题目被重复读入。并且这个文档在全程代码中没有被读出(虽然写了读出程序,但是没有能够触发的条件,根本没用)。
-
当前题目支持多符号运算,基本上不是两个数的加减乘除就是分数的加减乘除,重复的概率比较大。难度也基本上,小学初级。
-
题目界面一定要把每个题目都进行回车提交操作才能结束计时,也就是说,即使不会做的题目,也要进行回车操作,非常不便。
2.新开发功能分析
-
优化初始界面,将语言选择功能改为选择框。
-
在题目界面加上“结束”功能,点击时将显示所有未做题目的答案。
-
修改“复习”功能,将复习功能改为从错题中随机读取,并保证每次读取不重复。
-
修改“再一次”功能,将功能设定为重回初始界面。
-
增添括号操作符。
-
增加平方操作。
-
减少重复题目。这个暂时没能做到,只能保证复习题不重复出题。为了相对优化先减小重复出题的概率。
2.程序设计
1.码云提交记录
2.类图
3.覆盖率
需要测试覆盖率,要尝试把所有条件触发。但是因为某些条件触发概率太低,如下:
(1)随机分母为0,测试过程中没触发成功
(2)因为做测试,所以做题时间不长,也就没有触发下列时间的判断,特别是1小时的。
(3)关于文件存储,测试时文件已存在,下图新建文件代码没有触发。
(4)代码中存在必要的异常捕获,没有触发。
4.逻辑图,红色为修改或新增部分
5.内存分析优化
3.代码展示
以下仅暂时主要代码,调用部分可能涉及到类的传参判断,暂时省略。
-
随机生成算式部分(部分)
public String fra_operation(){ this.t1 = new Random().nextInt(10)%(10-1+1) + 1; this.t2 = new Random().nextInt(10)%(10-2+1) + 2; this.t3 = new Random().nextInt(10)%(10-1+1) + 1; this.t4 = new Random().nextInt(10)%(10-2+1) + 2; int fz=1,fm=t2*t4; if(k==1) { if(t2<t1||t4<t3||t2%t1==0||t4%t3==0) { astr=fra_operation(); return astr; } if(k1==0) { fz=t1*t4+t2*t3; } if(k1==1){ fz=t1*t4-t2*t3; if(fz==0) { return astr=("0"); } } if(k1==2) fz=t1*t3; if(k1==3) { fz=t1*t4; fm=t2*t3; } int f=common_divisor(fm,fz); if(f>0){ fm=fm/f; fz=fz/f; } if(f<0){ fm=-fm/f; fz=-fz/f; } astr = (fz+"/"+fm); if(astr.equals("1/1")) astr="1"; if(fm==1) astr = (fz+""); } else if(k==0) { fm=1; if(k1==0) { if(k2==3) fz=t1*(t2+t3)*t4; else fz=t1*t2+t3*t4; } if(k1==1) { if(k2==3) fz=t1*(t2-t3)*t4; else fz=t1*t2-t3*t4; } if(k1==2) { fz=t1*t2*t3*t4; } if(k1==3) { if(k2==1) { if(t1==0||t2==0) return astr=("0"); else if(t3==0||t4==0) { astr=fra_operation(); return astr; } else{ fz=t1*t2; fm=t3*t4; } } else { if(t3==0) { astr=fra_operation(); return astr; } else if(t1==0||t2==0||t4==0) return astr=("0"); else{ fz=t1*t2*t4; fm=t3; } } int f=common_divisor(fm,fz); if(f>0){ fm=fm/f; fz=fz/f; } if(f<0){ fm=-fm/f; fz=-fz/f; } astr = (fz+"/"+fm); } if(k1!=3) astr=fz+""; if(fm==1) astr = (fz+""); } if(astr.equals("1/1")) astr="1"; return astr; }
-
Answer、Question分别存储部分
Question=new ArrayList<String>(); Answer=new ArrayList<String>(); System.out.println(); for(int a=0;a<i;a++) { Runtime.getRuntime().gc(); boolean flag= new Random().nextBoolean(); Arithmetic hh = new Arithmetic(flag); String int_str = hh.int_operation(); String fra_str = hh.fra_operation(); if(flag==true) { Answer.add(int_str); Question.add(hh.toString()); } if(flag==false) { Answer.add(fra_str); Question.add(hh.toString()); } }
-
复习部分
if(Number.getText().matches("\d*")) { Frame.hh.i = Integer.parseInt(Number.getText()); if(Frame.hh.i<=10&&Frame.hh.i>=1) { Frame.hs.Histroy_read(); for(int a=0;a<Frame.hh.i;a++){ int b = new Random().nextInt(Frame.hs.astrlist.size()-1); Frame.hh.Answer.set(a, Frame.hs.astrlist.get(b)); Frame.hh.Question.set(a, Frame.hs.qstrlist.get(b)); List<Integer> count=new ArrayList<Integer>(Arrays.asList(list)); if(count.contains(b)) a--; else list[a]=b; } for(int a=0;a<(10-Frame.hh.i);a++){ Frame.hh.Answer.set(a+Frame.hh.i, ""); Frame.hh.Question.set(a+Frame.hh.i, ""); } } java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new Frame(true).setVisible(true); } }); this.dispose(); i++; try { Frame.hs.History_num(); } catch (FileNotFoundException e) { e.printStackTrace(); } }
4.程序运行
5.小结感受
-
有幸跟原作者交流了一下,果然是万恶之源。
-
结对编程能带来1+1>2的效果。毕竟在编程的时候,当局者迷旁观者清的情况很容易出现。交流过程中能理清思路,一个人在一个问题上纠结太久容易进入死胡同。
-
我和我的队友,经常相隔两地,毕竟我们有不同的学习方向。所以除了在课堂上,基本靠通讯工具交流。(我相信经过Java课设合作我们已经很有默契了。)其实很多事情不需要面对面也能交流清楚。
-
打代码时,特别是在理算法的时候,千万,不要,被打扰!惨痛的教训。(我果然是亲生的,妈妈我爱你。)
-
技术部分还是有很多限制。比如树的最小生成树算法,基本上能看懂c++的算法,虽然只是在特定条件下的触发情况。但是换成java就下不了手,尝试写了一下,对List之类的还不是很熟悉,就暂时没用了。因为这次限制在10题,然后根据出题类里的各种条件换算,重复率算了一下,真的很低。相比之下错题重复的概率较大,所以先解决这个问题。顺便我在找资料的时候链接到了北京大学ACM,感受到了差距。。。
-
选择这个源代码是因为看到了颜文字,感觉,比较亲和。然后,运行一遍发现很多问题,那就先修改这些bug吧,毕竟用户体验感还是很重要的。事实上我们两个可能都有强迫症吧,问题摆在面前不解决就很难受。然后理清楚了我们要做什么,虽然有的设想是在做的过程中突然想到,“这样做会不会比较好?”,但是基本上是按照原有的思路进行下去的。
-
团队合照。附个记录吧。。。
- PSP表格。。因为编码时间比较凌乱,大概估了个实际时间。