结对编程— —总结、经验及教训 (范济海 徐振杰)

1.项目需求

用户:

小学、初中和高中学生。

功能:

1、用户注册功能。用户提供手机号码,点击注册将收到一个注册码,用户可使用该注册码完成注册;

2、用户完成注册后,界面提示设置密码,用户输入两次密码匹配后设置密码成功。密码6-10位,必须含大小写字母和数字;

3、密码设置成功后,跳转到选择界面,界面显示小学、初中和高中三个选项,用户点击其中之一后,提示用户输入需要生成的题目数量;

4、用户输入题目数量后,生成一张试卷(同一张卷子不能有相同题目),界面显示第一题的题干和四个选项,用户选择四个选项中的一个后提交,界面显示第二题,...,直至最后一题;

5、最后一题提交后,界面显示分数,分数根据答对的百分比计算;

6、用户在分数界面可选择退出或继续做题;

2.问题分析

通过项目需求,我们可以看出这次结对项目就是以上次个人项目为基础,加上界面设计、短信验证注册登录以及显示最终的分为目的。而由于我们两人的代码都是用C++写的,众所周知,用C++做界面的话那是非常不方便的(虽然QT可以支持C++做界面,但是由于没有接触过QT所以放弃了),所以我们决定用java来写。首先我们分工,我主要是做题目的生成及结果计算(过程中遇到了许多困难,通过不断地测试与修改以及跟队友的帮助终于做完了),队友主要是负责短信验证注册、UI设计、登录等功能(队友实力比较强,帮了我很多)。

3.界面设计及结果

用java做界面自然要用java Swing了,通过上网查资料然后再编程我们最终实现的界面以及结果如下

登录界面

注册界面

选题界面

 

做题界面                                                                做题得分

 

4.计算结果代码

  1 import java.util.Collections;
  2 import java.util.Stack;
  3 
  4 /**
  5  *  算数表达式求值 
  6  *  直接调用Calculator的类方法conversion() 
  7  *  传入算数表达式,将返回一个浮点值结果
  8  *  如果计算过程错误,将返回一个NaN
  9  */
 10 public class Calculator {
 11     private Stack<String> postfixStack = new Stack<String>();// 后缀式栈
 12     private Stack<Character> opStack = new Stack<Character>();// 运算符栈
 13     private int[] operatPriority = new int[] { 0, 3, 2, 1, -1, 1, 0, 2 };// 运用运算符ASCII码-40做索引的运算符优先级
 14 
 15     public static double conversion(String expression) {
 16         double result = 0;
 17         Calculator cal = new Calculator();
 18         try {
 19             expression = transform(expression);
 20             result = cal.calculate(expression);
 21         } catch (Exception e) {
 22             // e.printStackTrace();
 23             // 运算错误返回NaN
 24             return 0.0 / 0.0;
 25         }
 26         // return new String().valueOf(result);
 27         return result;
 28     }
 29 
 30     /**
 31      * 将表达式中负数的符号更改
 32      *
 33      * @param expression
 34      *            例如-2+-1*(-3E-2)-(-1) 被转为 ~2+~1*(~3E~2)-(~1)
 35      * @return
 36      */
 37     private static String transform(String expression) {
 38         char[] arr = expression.toCharArray();
 39         for (int i = 0; i < arr.length; i++) {
 40             if (arr[i] == '-') {
 41                 if (i == 0) {
 42                     arr[i] = '~';
 43                 } else {
 44                     char c = arr[i - 1];
 45                     if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == 'E' || c == 'e') {
 46                         arr[i] = '~';
 47                     }
 48                 }
 49             }
 50         }
 51         if(arr[0]=='~'||arr[1]=='('){
 52             arr[0]='-';
 53             return "0"+new String(arr);
 54         }else{
 55             return new String(arr);
 56         }
 57     }
 58 
 59     /**
 60      * 按照给定的表达式计算
 61      *
 62      * @param expression
 63      *            要计算的表达式例如:5+12*(3+5)/7
 64      * @return
 65      */
 66     public double calculate(String expression) {
 67         Stack<String> resultStack = new Stack<String>();
 68         prepare(expression);
 69         Collections.reverse(postfixStack);// 将后缀式栈反转
 70         String firstValue, secondValue, currentValue;// 参与计算的第一个值,第二个值和算术运算符
 71         while (!postfixStack.isEmpty()) {
 72             currentValue = postfixStack.pop();
 73             if (!isOperator(currentValue.charAt(0))) {// 如果不是运算符则存入操作数栈中
 74                 currentValue = currentValue.replace("~", "-");
 75                 resultStack.push(currentValue);
 76             } else {// 如果是运算符则从操作数栈中取两个值和该数值一起参与运算
 77                 secondValue = resultStack.pop();
 78                 firstValue = resultStack.pop();
 79 
 80                 // 将负数标记符改为负号
 81                 firstValue = firstValue.replace("~", "-");
 82                 secondValue = secondValue.replace("~", "-");
 83 
 84                 String tempResult = calculate(firstValue, secondValue, currentValue.charAt(0));
 85                 resultStack.push(tempResult);
 86             }
 87         }
 88             return Double.valueOf(resultStack.pop());
 89     }
 90 
 91     /**
 92      * 数据准备阶段将表达式转换成为后缀式栈
 93      * 
 94      * @param expression
 95      */
 96     private void prepare(String expression) {
 97         opStack.push(',');// 运算符放入栈底元素逗号,此符号优先级最低
 98         char[] arr = expression.toCharArray();
 99         int currentIndex = 0;// 当前字符的位置
100         int count = 0;// 上次算术运算符到本次算术运算符的字符的长度便于或者之间的数值
101         char currentOp, peekOp;// 当前操作符和栈顶操作符
102         for (int i = 0; i < arr.length; i++) {
103             currentOp = arr[i];
104             if (isOperator(currentOp)) {// 如果当前字符是运算符
105                 if (count > 0) {
106                     postfixStack.push(new String(arr, currentIndex, count));// 取两个运算符之间的数字
107                 }
108                 peekOp = opStack.peek();
109                 if (currentOp == ')') {// 遇到反括号则将运算符栈中的元素移除到后缀式栈中直到遇到左括号
110                     while (opStack.peek() != '(') {
111                         postfixStack.push(String.valueOf(opStack.pop()));
112                     }
113                     opStack.pop();
114                 } else {
115                     while (currentOp != '(' && peekOp != ',' && compare(currentOp, peekOp)) {
116                         postfixStack.push(String.valueOf(opStack.pop()));
117                         peekOp = opStack.peek();
118                     }
119                     opStack.push(currentOp);
120                 }
121                 count = 0;
122                 currentIndex = i + 1;
123             } else {
124                 count++;
125             }
126         }
127         if (count > 1 || (count == 1 && !isOperator(arr[currentIndex]))) {// 最后一个字符不是括号或者其他运算符的则加入后缀式栈中
128             postfixStack.push(new String(arr, currentIndex, count));
129         }
130 
131         while (opStack.peek() != ',') {
132             postfixStack.push(String.valueOf(opStack.pop()));// 将操作符栈中的剩余的元素添加到后缀式栈中
133         }
134     }
135 
136     /**
137      * 判断是否为算术符号
138      *
139      * @param c
140      * @return
141      */
142     private boolean isOperator(char c) {
143         return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')';
144     }
145 
146     /**
147      * 利用ASCII码-40做下标去算术符号优先级
148      *
149      * @param cur
150      * @param peek
151      * @return
152      */
153     public boolean compare(char cur, char peek) {// 如果是peek优先级高于cur,返回true,默认都是peek优先级要低
154         boolean result = false;
155         if (operatPriority[(peek) - 40] >= operatPriority[(cur) - 40]) {
156             result = true;
157         }
158         return result;
159     }
160 
161     /**
162      * 按照给定的算术运算符做计算
163      *
164      * @param firstValue
165      * @param secondValue
166      * @param currentOp
167      * @return
168      */
169     private String calculate(String firstValue, String secondValue, char currentOp) {
170         String result = "";
171         switch (currentOp) {
172         case '+':
173             result = String.valueOf(ArithHelper.add(firstValue, secondValue));
174             break;
175         case '-':
176             result = String.valueOf(ArithHelper.sub(firstValue, secondValue));
177             break;
178         case '*':
179             result = String.valueOf(ArithHelper.mul(firstValue, secondValue));
180             break;
181         case '/':
182             result = String.valueOf(ArithHelper.div(firstValue, secondValue));
183             break;
184         }
185         return result;
186     }
187 }

由于初中题目及高中题目很难直接算出结果,所以要先将初中及高中题目转化为只含括号和四则运算,这样然后通过栈来计算结果就变得简单多了。

5.经验教训

   通过这次结对项目,我认识到了自身还有很多不足,学海无涯,学无止境,只有不断地学习才能更好的完善自己,而要想学好的最重要的方法就是实践,实践是检验真理的唯一标准,自己去动手做才能使自身获得真正的提高。结对项目的意义就是分工与合作,两个人的工作效率远远大于一个人,更何况以后的小组项目以及以后工作中的项目都不可能是一个人来完成的,所以只有合作才能完成更加艰巨的任务。虽然说做这个过程可能是困难的,会遇到许多许多麻烦包括做完后也有许多bug需要去修改,但是做完一个项目的那种喜悦与快乐是别人体会不到的,希望接下来的动手做的过程中会有更大的进步!

                                                                                                                                                             

                                                                 ——————范济海  徐振杰

 

猜你喜欢

转载自www.cnblogs.com/xuzhenjie/p/9756453.html
今日推荐