四则运算结对作业

1、代码地址:https://git.coding.net/sixtyseven/Twinning.git

2、PSP表格

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

       信息隐藏是软件的首要技术使命中格外重要的一种启发式方法,因为它强调的就是隐藏复杂度。信息隐藏有着独特的启发力,它能够激发出有效的设计方案。信息隐藏同样有助于设计类的公开接口。代码模块应该采用定义良好的接口来封装,这些模块的内部结构应该是程序员的私有财产,外部是不可见的。

Interface Design

设计接口 design interface是传统的后勤保障的一种要素也是一种后勤功能。

接口要符合rest、命名要规范优雅、单一性、扩展性。

接口命名规范:命名以英文或者英文缩写并以驼峰命名法命名

                         返回字段中表示同一个含义的字段在不同接口中命名尽量一致

Loose Coupling

松耦合的基本概念是:允许改变或者当问题发生在“电线的一端时”来避免影响到其他的端点。也就是说,改变或者供应者或者服务的问题不能影响到用户----或者用户的问题不应影响到供应者或者服务。作为提供松耦合的必备基本要素,Web服务管理代理经常使用在用户和供应者之间。

4、计算模块接口的设计与实现过程

共四个类:Background类、Fraction类、Integer类、MyWindows类。

Background类:testNum 题目数量、question 储存题目的数组、result 储存答案的数组

Fraction类:qstr储存题目的字符串、astr 储存答案的字符串

Integer类:qstr储存题目的字符串、astr 储存答案的字符串

MyWindows类:testNum 题目数量、question 储存题目的数组、result 储存答案的数组、rightNum 文件读出的正确数量、errorNum 文件读出的错误数量、rightNum2 本次正确数量、errorNum2  本次错误数量、answers 储存用户的回答

5、计算模块接口部分的性能改进

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();
    }

6、计算模块部分单元测试展示

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) {
        
    }

 

7、计算模块部分异常处理说明

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();
                }
                                                
            }
        });
                    
    }

8、界面模块的详细设计过程

 

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]);
        }

9、界面模块与计算模块的对接

做题

        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();
                    }
                }
                
            }

 

10、描述结对的过程

 

11、结对编程

优点:知识共享,协同合作、思维开阔、互相督促、学习促进。

缺点:对于队友擅长的领域了解不多的话,容易产生设计分歧。

           沟通不到位,考虑不全面两个人的设计,容易失败,这次本来的设计是网页版,后来发现在交互和服务器上出现很大问题,不得已废弃,浪费了时间和精力。

           需要大量的交流,但是因为非职业原因,时间不好统一。

个人评价:

杨思琦:优点:善于学习,想法独到,沟通耐心,流程规划完善

            缺点:时间规划不完善、有点拖延

刘士齐(我):

            优点:比较有时间观念,善于总结问题,乐于沟通

            缺点:对于项目方向有点佛系,喜欢纠结于不必要的细节,浪费时间,对于此次作业所使用语言基础太薄弱,因此进行的很吃力。

12、PSP表格(请见上文2)

posted @ 2018-04-10 08:33  荷月既生魄  阅读(228)  评论(1编辑  收藏  举报