本次结对编程让我学到了许多许多知识,受益不浅!在此以前,我没想过我能作出一个双击运行的小程序。html
感谢个人队友与我同心合力,感谢室友宇欣告诉我操做符为“最多多少”而不是“多少”并教我使用效能分析工具,感谢陈杰任劳任怨帮我测试14寸显示屏效果,感谢福孝大佬给我发的安装包!感谢学姐对项目的建议!java
代码仓库地址:https://git.coding.net/Siamese_miao/team.gitgit
本人:庄莉,学号:2016012034算法
队友:王璐瑶,学号:2016012095编程
PSP小程序 |
任务内容数组 |
计划共完成须要的时间(h)多线程 |
Planningapp |
计划dom |
0.5 |
Estimate |
估计这个任务须要多少时间,并规划大体工做步骤 |
0.5 |
Development |
开发 |
39.25 |
Analysis |
需求分析 (包括学习新技术) |
0.5 |
Design Spec |
生成设计文档 |
0.25 |
Design Review |
设计复审 (和同事审核设计文档) |
0.25 |
Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
0.25 |
Design |
具体设计 |
2 |
Coding |
具体编码 |
30 |
Code Review |
代码复审 |
1 |
Test |
测试(自我测试,修改代码,提交修改) |
5 |
Reporting |
报告 |
4 |
Test Report |
测试报告(包括博客) |
3 |
Size Measurement |
计算工做量 |
0.5 |
Postmortem & Process Improvement Plan |
过后总结, 并提出过程改进计划 |
0.5 |
Information hiding is part of the foundation of both structured design and object-oriented design. In structured design, the notion of “black boxes” comes from information hiding. In object-oriented design, it gives rise to the concepts of encapsulation and modularity, and it is associated with the concept of abstraction.
在《代码大全》中列出了两类须要隐藏的内容:
第一类信息是复杂化的信息。对于咱们的项目,咱们的main函数只有一个对gui的实例化,使用者并不知道内部的运行方式。内部的算法实现封装起来,外部只有调用的接口,只能够调用方法,不能够改变内部变量,作到了信息隐藏。
对于第二类,是指变更的信息。好比在用户的输入需求中出现了错误,提示并返回,这个错误在类中进行了适当的处理,错误没有扩散,这样能够提升程序的容错性。
在本项目设计接口过程当中,按需求新建接口,使用明确的命名方式使接口的功能清晰化,加强了可读性;接口与接口之间互相独立,使用方便。
耦合的强度依赖于:(1)一个模块对另外一个模块的调用;(2)一个模块向另外一个模块传递的数据量;(3)一个模块施加到另外一个模块的控制的多少;(4)模块之间接口的复杂程度。等等。
模块内子程序(下一个层次上)应共享数据(有必定的耦合度),而减小全局变量能下降子程序性间的耦合性。
类与类之间一般经过接口的契约实现服务提供者/服务请求者模式,这就是典型的松耦合。
耦合程度越高,模块与模块之间的联系性就更高,系统的灵活性就越低,报错率就更高。在咱们的项目中,计算模块的调用都比较单一,没有双向调用,使用之间互不干扰,增长了灵活性。
通过商讨,咱们决定基于个人我的项目修改。我先删除了原来的分数运算,在将普通四则运算与括号四则运算拆分,变成简单加减、四则运算、有括号加减与有括号四则运算。如图我分为5个类(test为单元测试)。
其中,有条件生成操做符与后一位数我较为满意,它大大的下降了运行效率,部分代码可看第5模块的性能改进模块。
基于原来的我的项目代码,因为出现了运算过程以及运算结果数值范围的限制,本来的result(String temp)再也不使用,改用了栈运算。
1 // 计算结果 2 public static Object result(String temp) { 3 ScriptEngineManager sem = new ScriptEngineManager(); 4 ScriptEngine se = sem.getEngineByName("js"); 5 Object last = 0; 6 try { 7 last = se.eval(temp); 8 } catch (ScriptException e) { 9 e.printStackTrace(); 10 } 11 return last; 12 }
在栈的运算中加入判断
1 if (Math.abs(sresulat) > upper || Math.abs(sresulat) < lower) 2 { 3 return 0; 4 }
而对于简单加减无括号全程不改变优先级的运算则不过栈,直接边生成数字便运算,减小了运算时间。
另外,本来的操做符是一开始随机生成好的再判断选择后一个数,而后再判断符号是否合法,再修改符号,若是仍是有小数或负数,则从新运行生成算式的函数,这样使得代码运行有些慢且屡次运行。再加上数值范围的限定以及能够存在负数,我改变了想法。
由于负数的存在,使得加减号并无数字的限制,而乘法有上限限制,除法有下限限制。因此在只有加减的运算中,符号随机生成,后一个数根据运算符以及数值范围生成合法的数。
1 // 相加不超过范围 2 public static int decide0(int x, int min, int max) 3 { 4 int y; 5 int temp = 0; 6 if (x > 0) 7 { 8 temp = max - min - x + 1;// 加一个正整数范围 9 } else 10 { 11 temp = max - (min - x) + 1;// 加至正整数的范围 12 } 13 if (temp < 0) 14 {// 范围小于0 15 if (x > 0) 16 { 17 temp = Math.abs(x) - min * 2 + 1;// 正整数过大,需加负数 18 y = 0 - (int) (Math.random() * temp) - min; 19 } else 20 { 21 temp = Math.abs(x) - 2 * min + 1;// 负数太小,越值,加小整数至负数范围 22 y = (int) (Math.random() * temp) + min; 23 } 24 } else 25 { 26 y = (int) (Math.random() * temp + min); 27 } 28 return y; 29 } 30 31 // 相减不小于最小 32 public static int decide1(int x, int min, int max) 33 { 34 int temp = 0; 35 int y = 0; 36 if (x > 0) 37 { 38 temp = x - 2 * (min - 1) - 1; // 减一个正数范围 39 } else 40 { 41 temp = max + x - min + 1;// 减一个正数范围 42 } 43 if (temp > 0) 44 { 45 if (x < 0 && temp < min) 46 { 47 temp = Math.abs(x) - 2 * min + 1;// 负数太小,需减负数 48 y = 0 - (int) (Math.random() * temp) - min; 49 } else 50 { 51 y = (int) (Math.random() * temp + min); 52 } 53 } else 54 { 55 temp = max - x - min + 1;// 只有x>0的状况会出现,正数太小,需减负数 56 y = 0 - (int) (Math.random() * temp) - min; 57 } 58 return y; 59 }
当有乘除时,则根据上一个数生成操做符,再根据操做符生成合法的后一位数。
1 // 操做符的选定 2 public static int operator(int num, int middle2, int middle3) 3 { 4 if (Math.abs(num) <= middle2) 5 {// 除法下界 6 if (Math.abs(num) < middle3) 7 { 8 return 3; 9 } else 10 { 11 return 0; 12 } 13 } else if (Math.abs(num) >= middle3) 14 {// 乘法上界 15 return 2; 16 } else 17 { 18 return (int) (Math.random() * 4); 19 } 20 } 21 // 下一位数字的选定 22 public static int[] numberB(int key, int num, int lower, int upper) 23 { 24 int[] find = new int[] { 0, lower }; 25 if (key == 0) 26 { 27 find[1] = decide0(num, lower, upper); 28 return find; 29 } else if (key == 2) 30 { 31 int[] judge = new int[2]; 32 judge = decide2(num, lower);// 确保可以整除,并不低于下限 33 if (judge[0] == 0) 34 { 35 find[1] = judge[1]; 36 return find; 37 } else 38 { 39 find[0] = 1; 40 } 41 } else if (key == 3) 42 { 43 find[1] = decide3(num, lower, upper); 44 if (find[0] == 0) 45 { 46 return find; // 乘法不超过上限 47 } 48 } 49 find[1] = decide1(num, lower, upper); 50 return find; 51 }
这样大大减小了从新调用函数的问题,而且实现了运算过程与数值皆在范围内的功能。
在附加题记录用户模块,一开始使用contains(name)函数判断用户,后来发现这样会出现abc与abcabc被认为同一我的而的状况,通过思考,咱们使用字符串的断开。
1 String[] arrays = txt.split(" ");
再使用equals(String)函数判断用户,解决了这个问题。
其中,生成有括号与乘除的式子生成的函数判断耗时最多,由于它的判断较多,限制较多,优先级易改变,容易生成最终不合法的式子而从新运行。
1 // 带括号的四则运算 2 public static String Bracket(int lower, int upper, int o) { 3 int middle2 = lower * lower;// 除法下界 4 int middle3 = upper / lower;// 乘法上界 5 int brack_left = 0; // 记录未匹配的左括号个数 6 int brack = 0; // 括号个数 7 int j = 0; 8 char[] p = new char[] { '+', '-', '÷', '*' }; 9 String temp1 = ""; 10 int[] num = new int[o + 1]; // 数字 11 int[] key = new int[o]; // 符号所在的下标 12 num[0] = (int) (Math.random() * (upper - lower + 1) + lower); 13 int result; 14 int[] find = new int[2]; 15 for (j = 0; j < (o - 1); j++) { 16 if (num[j] < 0) { 17 temp1 += "(" + String.valueOf(num[j]) + ")"; 18 } else { 19 temp1 += String.valueOf(num[j]); 20 } 21 int tmpcnt = brack_left; 22 for (int i = 0; i < tmpcnt; i++) { // 若当前有未匹配的左括号,则对每个未匹配的左括号,都有必定几率生成相应右括号。 23 if ((int) (Math.random() * 5) > 1) { // 生成右括号几率为0.6 24 brack_left--; 25 temp1 += ")"; 26 } 27 } 28 key[j] = calculate.operator(num[j], middle2, middle3); 29 find = calculate.numberB(key[j], num[j], lower, upper); 30 if (find[0] == 1) { 31 key[j] = 1; 32 } 33 num[j + 1] = find[1]; 34 temp1 += String.valueOf(p[key[j]]); 35 if (((brack * 2) <= o) && (((int) (Math.random() * 2)) == 0)) { // 以必定几率生成左括号,几率为1/2 36 temp1 += "("; 37 brack++; 38 brack_left++; 39 j++; 40 if (num[j] < 0) { 41 temp1 += "(" + String.valueOf(num[j]) + ")"; 42 } else { 43 temp1 += String.valueOf(num[j]); 44 } // 生成左括号后必须生成一个数字和运算符,否则可能出现(15)这样的错误 45 key[j] = calculate.operator(num[j], middle2, middle3); 46 find = calculate.numberB(key[j], num[j], lower, upper); 47 if (find[0] == 1) { 48 key[j] = 1; 49 } 50 num[j + 1] = find[1]; 51 temp1 += p[key[j]]; 52 } 53 } 54 while (j != o) { // 判断是否为最后一个数 55 if (num[j] < 0) { 56 temp1 += "(" + String.valueOf(num[j]) + ")"; 57 } else { 58 temp1 += String.valueOf(num[j]); 59 } 60 key[j] = calculate.operator(num[j], middle2, middle3); 61 temp1 += p[key[j]]; 62 find = calculate.numberB(key[j], num[j], lower, upper); 63 if (find[0] == 1) { 64 key[j] = 1; 65 } 66 j++; 67 num[j] = find[1]; 68 } 69 if (num[o] < 0) { 70 temp1 += "(" + String.valueOf(num[o]) + ")"; 71 } else { 72 temp1 += String.valueOf(num[o]); 73 } 74 while ((brack_left) != 0) { // 补全右括号 75 temp1 += ")"; 76 brack_left--; 77 } 78 result = stack.work(temp1, lower, upper, 1); 79 if (result == 0) { 80 temp1 = Bracket(lower, upper, o); 81 } 82 return temp1; 83 84 } 85 86 }
项目整体分析图,从内存,多线程,CPU等方面分析了计算模块的性能,截图以下:
性能分析过程截图:
按F4,出现如下截图。资源所有被回收。证实没有资源泄露。程序性能良好。
使用单元测试的CPU分析以下图:
使用Command.java的CPU效能分析以下图:
1 @Test 2 public void testWork() { 3 assertEquals(0, stack.work("7-5÷(1*37)÷(1*83)", 1, 900, 1)); 4 assertEquals(30, stack.work("55+(-25)÷5*(20-15)", 2, 300, 1)); 5 assertEquals(80, stack.work("((55+25)÷5)*(20-15)", 2, 300, 1)); 6 assertEquals(0, stack.work("60*(20-15)", 2, 200, 1)); 7 }
第一个断言测试的是没法整除返回错误标志0;
第二个断言测试的是负数运算;
第三个断言测试的是特殊括号位置的运算;
第四个断言测试的是超过数值返回错误标志0。
1 @Test 2 public void testAll() { 3 // 顺序不一样以及异常测试。生成的文件会被覆盖。 4 String[] arg0 = new String[] { "-n", "100", "-m", "5", "100", "-o", "3", "-c", "-b" }; 5 String[] arg1 = new String[] { "-m", "5", "50", "-o", "3", "-n", "100", "-c" }; 6 String[] arg2 = new String[] { "-o", "3", "-m", "5", "50", "-n", "100", "-b" }; 7 String[] arg3 = new String[] { "-n", "100", "-o", "3", "-m", "5", "50" }; 8 Command.main(arg0);// 有括号四则运算测试 9 Command.main(arg1);// 四则运算测试 10 Command.main(arg2);// 有括号加减运算测试 11 Command.main(arg3);// 加减运算测试 12 }
该部分测试的命令行的更改输入顺序的四种出题选择正常运行。输入异常部分请看第七点。
命令行单元测试覆盖率截图以下:
1 @Test 2 public void testDecide2() { 3 int[] find = new int[2]; 4 find = calculate.decide2(20, 2); 5 assertEquals(2, find[1]); 6 find = calculate.decide2(13, 2); 7 assertEquals(1, find[0]); 8 }
decide2(int x, int min)为除法选择除数的函数,函数以下:
1 // 被除数能被除数整除并不低于最小 2 public static int[] decide2(int x, int min) 3 { 4 int[] judge = new int[] { 1, 0 }; 5 int temp = Math.abs(x) / min - min + 1;// 除数的范围 6 for (int i = min; i < (temp + min); i++) 7 { 8 if (Math.abs(x) % i == 0) 9 {// 判断是否整除 10 judge[0] = 0; 11 judge[1] = i; 12 return judge; 13 } 14 } 15 return judge; 16 }
其中,judge[0]用于判断该数可否有可整除的除数,1为没有,0为有,judge[1]为除数的值。该单元测试则测试了一次可产生除数与一次不能产生除数的状况。
1 @Test 2 public void testAll() { 3 String[] arg4 = new String[] { "-o", "3", "-m", "5", "50", "-n" }; 4 String[] arg4_1 = new String[] { "-o", "3", "-n", "-m", "5", "50" }; 5 String[] arg4_2 = new String[] { "-n", "100000", "-m", "5", "50" }; 6 String[] arg4_3 = new String[] { "-o", "3", "-m", "5", "50" }; 7 8 String[] arg5 = new String[] { "-n", "50" }; 9 String[] arg5_1 = new String[] { "-m", "5", "-n", "50", "-o", "3" }; 10 String[] arg5_2 = new String[] { "-n", "50", "-m", "3" }; 11 String[] arg5_3 = new String[] { "-n", "50", "-o", "3", "-m" }; 12 String[] arg5_4 = new String[] { "-m", "-n", "50" }; 13 14 String[] arg6 = new String[] { "-o", "11", "-m", "5", "50", "-n", "100" }; 15 String[] arg6_1 = new String[] { "-n", "100", "-o", "-m", "5", "50" }; 16 String[] arg6_2 = new String[] { "-n", "100", "-m", "5", "50", "-o" }; 17 18 String[] arg7 = new String[] { "-m", "5", "20", "-n", "100", "-c" }; 19 String[] arg7_1 = new String[] { "-m", "5", "50", "-n", "100", "-b" }; 20 21 String[] arg8 = new String[] { "-b", "1", "-o", "3", "-m", "5", "50", "-n", "100" }; 22 String[] arg8_1 = new String[] { "-c", "1", "-o", "3", "-m", "5", "50", "-n", "100" }; 23 String[] arg8_2 = new String[] { "-n", "100", "-m", "5", "50", "-d" }; 24 25 Command.main(arg4);// 缺乏题数值测试 26 Command.main(arg4_1); 27 Command.main(arg4_2);// 题数值过大测试 28 Command.main(arg4_3);// 缺乏题数测试 29 30 Command.main(arg5);// 缺乏数值范围 31 Command.main(arg5_1);// 缺乏数值范围上限测试 32 Command.main(arg5_2); 33 Command.main(arg5_3);// 缺乏数值范围上下限测试 34 Command.main(arg5_4); 35 36 Command.main(arg6);// 操做符数值过大测试 37 Command.main(arg6_1);// 缺乏操做符数值测试 38 Command.main(arg6_2); 39 40 Command.main(arg7);// 乘除须要上界大于下界的平方 41 Command.main(arg7_1);// 括号须要操做符数大于1 42 43 Command.main(arg8);// 输入非法测试之b后有数字 44 Command.main(arg8_1);// 输入非法测试之c后有数字 45 Command.main(arg8_2);// 输入非法测试之无辨识字符 46 }
对于命令行可能出现的异常大概有13个:
设计图以下:
咱们先从选择出题或作题开始。
选择出题则进入出题参数输入界面。
利用MouseListener的mouseEntered(MouseEvent e)与setTitle(String);使得鼠标移到参数上,标题会有提示功能。
输入完毕点击确认后,由输入的参数判断是否有异常并提示直至无异常建立文件。
1 public class submitListener implements ActionListener { 2 public void actionPerformed(ActionEvent e) { 3 String m = "题数与数值上下限为必填项,请按标题提示输入正整数!"; 4 String m2 = "建立文件成功!"; 5 int n0, lower0, upper0, o0, c0, b0; 6 o0 = 1; 7 c0 = 0; 8 b0 = 0; 9 String o1 = ""; 10 try { 11 n0 = Integer.parseInt(n.getText()); 12 lower0 = Integer.parseInt(lower.getText()); 13 upper0 = Integer.parseInt(upper.getText()); 14 if (n0 < 1 || n0 > 10000) { 15 JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), "题数范围为1-10000", "提示", 16 JOptionPane.INFORMATION_MESSAGE); 17 return; 18 } 19 if (lower0 < 1 || lower0 > 100) { 20 JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), "下界范围为1-100", "提示", 21 JOptionPane.INFORMATION_MESSAGE); 22 return; 23 } 24 if (upper0 < 50 || upper0 > 1000) { 25 JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), "上界范围为50-1000", "提示", 26 JOptionPane.INFORMATION_MESSAGE); 27 return; 28 } 29 if (upper0 < (2 * lower0)) { 30 JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), "上界必须大于两倍下界", "提示", 31 JOptionPane.INFORMATION_MESSAGE); 32 return; 33 } 34 } catch (NumberFormatException e2) { 35 JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), m, "提示", JOptionPane.INFORMATION_MESSAGE); 36 return; 37 } 38 try { 39 o1 = o.getText(); 40 o0 = Integer.parseInt(o1); 41 } catch (NumberFormatException e2) { 42 if (!o1.equals("")) { 43 JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), "请输入1-10的正整数或不输入保持默认,默认为1", "提示", 44 JOptionPane.INFORMATION_MESSAGE); 45 return; 46 } 47 } 48 if (c.isSelected()) { 49 c0 = 1; 50 } 51 if (b.isSelected()) { 52 b0 = 1; 53 } 54 if (o0 == 1 && b0 == 1) { 55 JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), "括号须要操做符数量大于1", "提示", 56 JOptionPane.INFORMATION_MESSAGE); 57 return; 58 } 59 if (c0 == 1 && upper0 < (lower0 * lower0)) { 60 JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), "乘除法须要上界数值大于下界的平方", "提示", 61 JOptionPane.INFORMATION_MESSAGE); 62 return; 63 } 64 createFile.fileCreate(n0, lower0, upper0, o0, c0, b0); 65 JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), m2, "提示", JOptionPane.INFORMATION_MESSAGE); 66 System.exit(0); 67 } 68 }
选择作题则先输入作题人名字(在这里建议使用英文,中文名字没法很好的记录)。
接着上传文件,在这里使用了txt文件过滤器,使之仅可上传txt文件。
1 FileFilter filter = new FileNameExtensionFilter("Text file", "txt"); 2 JFileChooser fileChooser = new JFileChooser(); 3 fileChooser.setAcceptAllFileFilterUsed(false); 4 fileChooser.addChoosableFileFilter(filter); 5 FileSystemView fsv = FileSystemView.getFileSystemView();
另外,出题与作题都统一为utf-8编码,免去执行文件编码错误。
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true), "UTF-8"));
InputStreamReader read = new InputStreamReader(new FileInputStream(file), "utf-8");
上传成功后开始计时作题,并于最后结果中显示用时。
通过后面JTextPane控件的启发,我考虑到出题时题目长度有长短,为了更加美观显示,应该须要自动换行,我一样采用了HTML编辑文本的想法,作出改进。
1 public static void JlabelSetText(JLabel jLabel, String longString) throws InterruptedException { 2 StringBuilder builder = new StringBuilder("<html>"); 3 char[] chars = longString.toCharArray(); 4 FontMetrics fontMetrics = jLabel.getFontMetrics(jLabel.getFont()); 5 int start = 0; 6 int len = 0; 7 while (start + len < longString.length()) { 8 while (true) { 9 len++; 10 if (start + len > longString.length()) 11 break; 12 if (fontMetrics.charsWidth(chars, start, len) > jLabel.getWidth()) { 13 break; 14 } 15 } 16 builder.append(chars, start, len - 1).append("<br/>"); 17 start = start + len - 1; 18 len = 0; 19 } 20 builder.append(chars, start, longString.length() - start); 21 builder.append("</html>"); 22 jLabel.setText(builder.toString()); 23 }
计时方面我本来采用秒数计时,后来考虑到当作题时间较长时,秒数很难清晰明确的表达,因此改用了 hh:mm:ss 法显示。
1 public static String getTimeStrBySecond(long second) { 2 if (second <= 0) { 3 return "00:00:00"; 4 } 5 int hours = (int) second / HOUR_SECOND; 6 if (hours > 0) { 7 8 second -= hours * HOUR_SECOND; 9 } 10 int minutes = (int) second / MINUTE_SECOND; 11 if (minutes > 0) { 12 second -= minutes * MINUTE_SECOND; 13 } 14 return (hours > 10 ? (hours + "") 15 : ("0" + hours) + ":" + (minutes > 10 ? (minutes + "") : ("0" + minutes)) + ":" 16 + (second > 10 ? (second + "") : ("0" + second))); 17 }
自动换行处理与秒数转换被我写入新类——dataDeal类中。
最终作完题目后除了显示用时,还显示题数、分数、错题以及该题正确答案,非首次用户会显示历史分数以及最高分数。
本来该部分使用了JTextArea控件,但学姐建议正确答案部分对齐显示会更加美观,并提出了C#中的ListView控件,但很遗憾,Java中彷佛并无。JTextArea控件是纯文本显示,很难作到不一样的对齐方式,因此我删除了该类。通过多方学习比较,我最终选择了JTextPane控件,该控件简单易用,可将文本显示为HTML文本,大大提升了编辑的样式性。我最终采起了表格法对齐,另外对重点突出的地方加粗变红显示,达到强调与必定视觉冲击效果,可从后文看到对比图。
1 String text = "<p style='font-family:楷体; font-size:19'>" + name + " 本次用时<span style='color:red'><strong> " 2 + dataDeal.getTimeStrBySecond(spentTime) + " </strong></span>,得分<span style='color:red'><strong> " 3 + goal + " </strong></span>分。<br>"; 4 if (size0 == 0) { 5 text += "你总共答了<span style='color:red'><strong> " + size 6 + " </strong></span>道题,并所有答对!<span style='color:red'><strong>恭喜!</strong></span></p>"; 7 } else { 8 text += "你总共答了<span style='color:red'><strong> " + size 9 + " </strong></span>道题,答对<span style='color:red'><strong> " + size1 10 + " </strong></span>道,答错<span style='color:red'><strong> " + size0 11 + " </strong></span>道,分别为:</p><p><table border=0>"; 12 for (int i = 0; i < (size0 * 2); i++) { 13 text += "<tr><td style='font-family:楷体; font-size:19'><strong>" + wrong.get(i++) 14 + " </strong></td><td width='180' style='font-family:楷体; font-size:19;color:red'><strong> " 15 + wrong.get(i) + "</strong></td></tr>"; 16 } 17 } 18 text += "</table></p>"; 19 text += "<p style='font-family:楷体; font-size:19'>" + createFile.record(name, goal) + "</p>"; 20 21 JTextPane textarea = new JTextPane(); 22 textarea.setContentType("text/html"); 23 textarea.setText(text); 24 textarea.setEditable(false); 25 JScrollPane textAreascrollPane = new JScrollPane(textarea); 26 add(textAreascrollPane, BorderLayout.CENTER);
如图所示
在界面模块选择出题输入参数以后调用fileCreate类,再由fileCreate类调用计算模块,建立result.txt
在界面模块选择作题输入名字、上传文件、作题。作题时调用计算模块的stack类计算判断正确性,记录错题。最终结果由计算模块中的fileCreate类的record(String name, int goal)记录,由界面模块显示。
实现的功能大体有12个,而且为了提升用户体验,修改了图标并增长了背景,将操做符数修改成下拉框选择,默认选择为1,避免输入非数字错误:
出题参数输入(先后对比图)
输入参数有误提醒(见第七点异常)
生成文件
记录用户
上传文件(只容许txt文件)
判断文件是否为空或非练习题
计时
一道一道作题而且题目过长时自动换行
评分
根据学姐给的建议作出了修改,如下为先后对比图,正确答案对齐,使之更加美观。另外我修改了作题时间的显示形式,这样当作题时间较长时能够更加清晰的看出时间状况。而作题时间、得分状况、错题与正确答案皆加粗甚至标红,使之更加显眼,提升用户体验。
记录历史分数与最高分数
咱们先一块儿分析了需求与功能的实现,并提出了一些有实质性的方法,并确认数据的传递方式。再分析各自的我的项目代码,指出了双方优劣性,在综合考虑选择基础代码加以改进。
咱们根据本身较为擅长的方面分工,如相对之下,我对gui较为熟悉,而她对字符串处理较为熟悉,则我负责界面展现而她负责命令行的分析。各自写完以后咱们再复审双方代码,对代码不理解之处询问并补充注释,以及对双方异常状况补充。最后在一块儿整合双方代码,使之成为完整项目。
在此过程当中咱们互相帮助、互相学习、能力上获得互补,而代码和产品质量提升,有效地减小bug而且考虑到更多方面的状况。有两台电脑能够测试程序效果,如她的电脑比我小,个人gui显示不一样,她的部分算式被遮挡,最终我选择了将按钮部分的面板设为透明,解决了这个问题。
不足之处在于队友之间的进度相互影响,不一样的代码风格之间的磨合也花费了必定时间。
双方优缺点:
庄莉 | 王璐瑶 | |
优势 | 认真细心,有责任心 |
不辞辛苦 |
代码能力高 |
对字符串以及字符串数组的处理十分熟练 |
|
动手能力强 |
颇有想法,有好点子 |
|
缺点 | 有时候对于小问题过于钻牛角尖 |
因生病而不在状态,没注意到比较细的地方,时间较少 |
PSP |
任务内容 |
实际完成须要的时间(min) |
Planning |
计划 |
0.5 |
Estimate |
估计这个任务须要多少时间,并规划大体工做步骤 |
0.5 |
Development |
开发 |
53.25 |
Analysis |
需求分析 (包括学习新技术) |
0.5 |
Design Spec |
生成设计文档 |
0.25 |
Design Review |
设计复审 (和同事审核设计文档) |
0.25 |
Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
0.25 |
Design |
具体设计 |
1 |
Coding |
具体编码 |
40 |
Code Review |
代码复审 |
1 |
Test |
测试(自我测试,修改代码,提交修改) |
10 |
Reporting |
报告 |
9 |
Test Report |
测试报告 |
8 |
Size Measurement |
计算工做量 |
0.5 |
Postmortem & Process Improvement Plan |
过后总结, 并提出过程改进计划 |
0.5 |
本次结对编程真的让我学到不少知识,尤为是各类操做,就像上一篇博客的连接同样,我查了许许多多这样的连接,学习了一种有一种的方法,与队友配合,完成了此次项目。而每次写博客,都能从新总结个人思路,受益良多。
虽然真的很辛苦,但能作出来也就够了。
如下部分因为时间与精力关系,咱们小组并无完成,仅提供思路参考,有想法的同窗可加以尝试。
附加题多语言思路参考:程序国际化
https://blog.csdn.net/zhuxinquan61/article/details/51540806
http://www.javashuo.com/article/p-gdfjqelb-me.html
思路注意点参考: