四则运算结对作业
1、代码地址:https://git.coding.net/sixtyseven/Twinning.git
2、
PSP |
任务内容 |
计划共完成需要的时间(min) |
实际完成需要的时间(min) |
Planning |
计划 |
30 |
30 |
Estimate |
估计这个任务需要多少时间,并规划大致工作步骤 |
10 |
12 |
Development |
开发 |
2234 |
4375 |
Analysis |
需求分析 (包括学习新技术) |
60 |
240 |
Design Spec |
生成设计文档 |
0 |
0 |
Design Review |
设计复审 (和同事审核设计文档) |
0 |
0 |
Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
7 |
10 |
Design |
具体设计 |
80 |
260 |
Coding |
具体编码 |
1800 |
2800 |
Code Review |
代码复审 |
40 |
240 |
Test |
测试(自我测试,修改代码,提交修改) |
80 |
140 |
Reporting |
报告 |
90 |
240 |
Test Report |
测试报告 |
25 |
190 |
Size Measurement |
计算工作量 |
10 |
15 |
Postmortem & Process Improvement Plan |
事后总结, 并提出过程改进计划 |
40 |
240 |
3、Information Hiding
信息隐藏是软件的首要技术使命中格外重要的一种启发式方法,因为它强调的就是隐藏复杂度。信息隐藏有着独特的启发力,它能够激发出有效的设计方案。信息隐藏同样有助于设计类的公开接口。代码模块应该采用定义良好的接口来封装,这些模块的内部结构应该是程序员的私有财产,外部是不可见的。
命名以英文或者英文缩写并以驼峰命名法命名
返回字段中表示同一个含义的字段在不同接口中命名尽量一致
4、
public static List<String> generateExp(int exprCount,int low,int high, int maxOpCount,boolean muldiv,boolean bracket) { List<String> exprList=new ArrayList<>(); Random rand=new Random(); for(int i=0;i<exprCount;++i) { StringBuilder exprBuilder=new StringBuilder(); int opCount=rand.nextInt(maxOpCount)+1; int[] lbs=new int[opCount]; int k=0; for(int j=0;j<opCount;++j) { boolean bracketFlag=false; //以40%概率添加左括号 if(bracket&&rand.nextDouble()<0.4) { exprBuilder.append('('); lbs[k++]=exprBuilder.length()-1; bracketFlag=true; } //添加操作数 exprBuilder.append(rand.nextInt(high+1-low)+low); //以50%的概率添加右括号 if(bracket&&!bracketFlag&&k>0&&rand.nextDouble()<0.5) { exprBuilder.append(')'); k--; } //添加操作符 exprBuilder.append(muldiv?ops[rand.nextInt(4)]:ops[rand.nextInt(2)]); } exprBuilder.append(rand.nextInt(high+1-low)+1); if(k>1) { exprBuilder.append(')'); k--; } //删除多余左括号 for(int m=0;m<k;++m) { exprBuilder.deleteCharAt(lbs[m]); } exprList.add(exprBuilder.toString()); } return exprList; } //比较运算符优先级 private static int cmpPrior(char sign1,char sign2) { @SuppressWarnings("serial") Map<Character,Integer> map=new HashMap<Character,Integer>() {{ put('+',1);put('-',1);put('x',2);put('÷',2);put('#',0);put('(',0);put(')',0); }}; return map.get(sign1)-map.get(sign2); } //进行一次运算 private static int calc(int num1,int num2,char op) { switch(op) { case '+':return num2+num1; case '-':return num2-num1; case 'x':return num2*num1; case '*':return num2*num1; case '/':return num2/num1; case '÷':return num2/num1; default: return 0; } } //判断字符c是否为运算符 private static boolean isOperator(char c) { if(c=='+'||c=='-'||c=='x'||c=='*'||c=='÷'||c=='/'||c=='#') { return true; } else { return false; } } //判断字符c是否为数字 private static boolean isNumber(char c) { return Character.isDigit(c); } public static int calculate(String expr) { Stack<Integer> numStack=new Stack<>(); Stack<Character> opStack=new Stack<>(); expr=expr.concat("#"); int num=0,i=0; while(i<expr.length()) { char ch=expr.charAt(i); if(isOperator(ch)) { if(opStack.isEmpty()||cmpPrior(ch, opStack.getTop())>0) { opStack.push(ch); i++; } else { numStack.push(calc(numStack.pop(),numStack.pop(),opStack.pop())); } } else if(ch=='(') { opStack.push(ch); i++; } else if(ch==')') { while(!opStack.isEmpty()&&opStack.getTop()!='(') { numStack.push(calc(numStack.pop(),numStack.pop(),opStack.pop())); } //表达式括号不匹配处理 if(opStack.isEmpty()) { System.out.println("表达式括号不匹配"); return -1; } else { opStack.pop(); i++; } } else { num=ch-'0'; while(isNumber(expr.charAt(i+1))) { ch=expr.charAt(++i); num=num*10+(ch-'0'); } numStack.push(num); i++; } } return numStack.pop(); }
private class OpNode{ //节点类型(0:运算符节点 1:操作数节点) private int nodeType; private int value; private int interResult=0; private OpNode leftChild,rightChild,parent; public OpNode(int nodeType,int value, OpNode parent) { this.nodeType=nodeType; this.value=value; this.parent=parent; this.leftChild=this.rightChild=null; } //判断是否为操作符节点 public boolean isOperator() { if(nodeType==0) { return true; } else return false; } public int getNodeType() { return nodeType; } public void setNodeType(int nodeType) { this.nodeType = nodeType; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public int getInterResult() { return interResult; } public void setInterResult(int interResult) { this.interResult = interResult; } public OpNode getLeftChild() { return leftChild; } public void setLeftChild(OpNode leftChild) { this.leftChild = leftChild; } public OpNode getRightChild() { return rightChild; } public void setRightChild(OpNode rightChild) { this.rightChild = rightChild; } public OpNode getParent() { return parent; } public void setParent(OpNode parent) { this.parent = parent; } } private OpNode root; public Expression(int maxOpCount,int low,int high, boolean containsMulDiv,boolean containsBracket) { Random rand=new Random(); int opCount=1; root=newOperNode(null,containsMulDiv,rand); while(opCount<=maxOpCount) { int leftNodeType=rand.nextInt(2); int rightNodeType=rand.nextInt(2); //生成二叉树。。。。 } } //随机生成运算符节点 private OpNode newOperNode(OpNode parent,Boolean containsMulDiv,Random rand) { int value=containsMulDiv?rand.nextInt(2):rand.nextInt(4); return new OpNode(0,value,parent); } //随机生成数值节点 private OpNode newNumNode(OpNode parent,int low,int high,Random rand) { int value=rand.nextInt(high-low+1)+low; return new OpNode(1,value,parent); } public Expression(String expr) { }
public void History() { try { reader = new BufferedReader(new FileReader(new File("history.txt"))); rightNum = reader.readLine(); errorNum = reader.readLine(); reader.close(); } catch (IOException e) { e.printStackTrace(); } labRight.setText("历史正确量:"+ rightNum ); labError.setText("历史错误量:"+ errorNum ); } @Override public void actionPerformed(ActionEvent e) { } }
btnSubmit.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { timer.stop(); for (int i = 0; i < Background.testNum; i++) { answers[i]=tfdAnswer[i].getText(); // 提取用户的答案 if(result[i].equals(answers[i])){ labCheck[i].setText("right"); rightNum2++; } else{ labCheck[i].setText("wrong"); errorNum2++; wrong.add(new Integer(i+1).toString()); } } rightNum2 = rightNum2 +Integer.parseInt(rightNum); errorNum2 = errorNum2 +Integer.parseInt(errorNum); Integer a = new Integer(rightNum2); Integer b = new Integer(errorNum2); try { writer = new BufferedWriter(new FileWriter(new File("history.txt"))); writer.write(a.toString()); writer.newLine(); writer.write(b.toString()); writer.newLine(); writer.close(); } catch (IOException e1) { e1.printStackTrace(); } } }); }
try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); } catch (Exception e) { e.printStackTrace(); } background = new Background(); background.createTest(); questions = background.getQuestions(); result = background.getResult(); jpMain = new JPanel(); jpMain.setLayout(null); labRight = new JLabel(); labRight.setBounds(300, 0, 100, 50); jpMain.add(labRight); labError = new JLabel(); labError.setBounds(400, 0, 100, 50); jpMain.add(labError); History(); labTime = new JLabel(); labTime.setFont(new Font("Consolas", 0, 20)); labTime.setBounds(100, 0, 120, 50); jpMain.add(labTime); now.setHours(0); now.setMinutes(0); now.setSeconds(0);
final Timer timer = new Timer(1000, new ActionListener() { public void actionPerformed(ActionEvent e) { Date now2 = new Date(now.getTime() + 1000); now = now2; SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss"); labTime.setText(formatter.format(now)); } });
for (int i = 0; i < Background.testNum; i++) { jpQuestions[i] = new JPanel(); jpQuestions[i].setLayout(null); labQuestions[i] = new JLabel(questions[i], JLabel.CENTER); labQuestions[i].setFont(new Font("Consolas", 0, 20)); jpQuestions[i].add(labQuestions[i]); labQuestions[i].setBounds(0, 0, 200, 25); tfdAnswer[i] = new JTextField(8); tfdAnswer[i].setFont(new Font("Consolas", 0, 20)); jpQuestions[i].add(tfdAnswer[i]); tfdAnswer[i].setBounds(380, 0, 60, 30); labCheck[i] = new JLabel("", JLabel.CENTER); labCheck[i].setFont(new Font("Consolas", 0, 16)); jpQuestions[i].add(labCheck[i]); labCheck[i].setBounds(440, 0, 60, 25); jpTest.add(jpQuestions[i]); }
submitBtn=GuiUtils.newButton(100, 35, "提交答案", new ActionListener() { public void actionPerformed(ActionEvent e) { int ret=JOptionPane.showConfirmDialog(ProblemDoPanel.this, "确定提交答案?"); if(ret==JOptionPane.OK_OPTION) { timer.stop(); List<String> answerList=new ArrayList<>(); for(int i=0;i<sc.getProblemCount();++i) { answerList.add(answerFieldList.get(i).getText()); } sc.setResultAnswers(answerList); StringBuilder wrong=new StringBuilder(); for(int i:sc.getWrongList()) { wrong.append(i+","); } String t=timer.getHour()+"时"+timer.getMinute()+"分"+timer.getSecond()+"秒"; JOptionPane.showMessageDialog(ProblemDoPanel.this, "本次测验得分:"+sc.getScore()+"\n共用时:"+t+"\n做错题号:"+wrong.toString()); inputBtn.setEnabled(true); submitBtn.setEnabled(false); } } });
出题
JPanel btnPanel=new JPanel(); btnPanel.add(GuiUtils.newButton(150, 50, "开始出题", new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { //生成题目文件 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); int ret=chooser.showSaveDialog(ProblemOfferPanel.this); if(ret==JFileChooser.APPROVE_OPTION) { int exprCount=Integer.valueOf(exprCountField.getText()); int opMaxCount=Integer.valueOf(opMaxCountField.getText()); int numLow=Integer.valueOf(numLowField.getText()); int numHigh=Integer.valueOf(numHighField.getText()); boolean containsMulDiv=containsMulDivBox.isSelected(); boolean containsBracket=containsBracketBox.isSelected(); List<String> exprList=Calculator.generateExp(exprCount, numLow, numHigh, opMaxCount, containsMulDiv, containsBracket); BufferedWriter writer=null; try { String filePath=chooser.getSelectedFile().getAbsolutePath()+"/题目.txt"; File file=new File(filePath); if(!file.exists()) { file.createNewFile(); } writer=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))); for(int i=1;i<=exprList.size();++i) { writer.write("("+i+") "); writer.write(exprList.get(i-1)); writer.newLine(); writer.newLine(); } writer.close(); JOptionPane.showMessageDialog(ProblemOfferPanel.this, "生成题目文件成功!"); } catch (IOException e) { JOptionPane.showMessageDialog(ProblemOfferPanel.this, "生成题目文件失败!"); e.printStackTrace(); } } }
优点:知识共享,协同合作、思维开阔、互相督促、学习促进。
缺点:对于队友擅长的领域了解不多的话,容易产生设计分歧。
沟通不到位,考虑不全面两个人的设计,容易失败,这次本来的设计是网页版,后来发现在交互和服务器上出现很大问题,不得已废弃,浪费了时间和精力。
需要大量的交流,但是因为非职业原因,时间不好统一。
个人评价:
杨思琦:优点:善于学习,想法独到,沟通耐心,流程规划完善
缺点:时间规划不完善、有点拖延
刘士齐(我):
优点:比较有时间观念,善于总结问题,乐于沟通
缺点:对于项目方向有点佛系,喜欢纠结于不必要的细节,浪费时间,对于此次作业所使用语言基础太薄弱,因此进行的很吃力。