首页 > 其他 > 详细

结对编程项目分析与经验总结

时间:2020-10-09 21:14:29      阅读:47      评论:0      收藏:0      [点我收藏+]

结对项目实现

 


前言

本博客对在个人编程的基础上进行的结对编程进行总结,主要包括代码的复用和结对编程中学到的经验教训

结对编程分工:我负责UI界面(登陆界面,出题界面,做题界面,汇报界面,修改密码,弹窗模块),队友负责(验证码注册模块,查重模块,保存账户信息模块,计算模块)


一、结对编程要求

1、所有功能通过图形化界面操作,可以是桌面应用,可以是网站(编程语言和技术不限);
2、用户注册功能。用户提供手机号码,点击注册将收到一个注册码,用户可使用该注册码完成注册;
3、用户完成注册后,界面提示设置密码,用户输入两次密码匹配后设置密码成功。密码6-10位,必须含大小写字母和数字。用户在登录状态下可修改密码,输入正确的原密码,再输入两次相同的新密码后修改密码成功;
4、密码设置成功后,跳转到选择界面,界面显示小学、初中和高中三个选项,用户点击其中之一后,提示用户输入需要生成的题目数量;
5、用户输入题目数量后,生成一张试卷(同一张卷子不能有相同题目,题目全部为选择题),界面显示第一题的题干和四个选项,用户选择四个选项中的一个后提交,界面显示第二题,…,直至最后一题;
6、最后一题提交后,界面显示分数,分数根据答对的百分比计算;
7、用户在分数界面可选择退出或继续做题;

二、代码复用

1.生成试卷

根据用户选择的题目类型和数量生成题目(示例):
给函数增加了返回值,函数返回一个字符串数组,每一个字符串代表一个题目,传入的参数分别是题目类型,题目保存的路径和题目数量

public static String[] GenerateTest(String type, String path, int number)

2.生成后缀表达式

代码如下(示例):

int num = (int) (0 + Math.random() * (4 - 0 + 1));   //获取0-4个 二元运算符
            ArrayList<String> houzhui = new ArrayList<>();
            int operands = (int) (1 + Math.random() * (100 - 1 + 1)); //操作数的取值范围是1-100
            houzhui.add(Integer.toString(operands));

随机生成二元运算符和运算数,然后把他们拼接成后缀表达式。根据题目的类型,随即插入根号等一元运算符


3.把后缀表达式翻译成中缀表达式

通过栈来实现,从后缀表达式中取字符串,根据字符串的内容来决定进行入栈还是出栈的操作

//将后缀表达式翻译成中缀表达式
            Stack<String> stack = new Stack<>();
            int time=0;
            for (String str:houzhui){
                if (str.equals("sin")||str.equals("cos")||str.equals("tan")||str.equals("√")||str.equals("2")){
                    String popB=stack.pop();
                    if (str.equals("√")){
                        stack.push("√"+"("+popB+")");
                    }
                    if (str.equals("2")){
                        stack.push("("+popB+")"+"2");
                    }
                    if (str.equals("sin")){
                        stack.push("sin"+"("+popB+")");
                    }
                    if (str.equals("cos")){
                        stack.push("cos"+"("+popB+")");
                    }
                    if (str.equals("tan")){
                        stack.push("tan"+"("+popB+")");
                    }
                }
                else if(str.equals("+")||str.equals("-")||str.equals("*")||str.equals("/")){
                    String popB=stack.pop();
                    String popA=stack.pop();
                    if (str.equals("+")){
                        if (time==0){
                            temp = temp + "(" + popA + "+" + popB + ")";
                            time++;
                        }
                        else{
                            temp = "(" + temp + "+" + popB + ")";
                        }
                        stack.push(popA+"+"+popB);
                    }
                    if (str.equals("-")){
                        if (time==0){
                            temp = temp + "(" + popA + "-" + popB + ")";
                            time++;
                        }
                        else{
                            temp = "(" + temp + "-" + popB + ")";
                        }
                        stack.push(popA+"-"+popB);
                    }
                    if (str.equals("*")){
                        if (time==0){
                            temp=temp+popA+"*"+popB;
                            time++;
                        }
                        else{
                            temp=temp+"*"+popB;
                        }
                        stack.push(popA+"*"+popB);
                    }
                    if(str.equals("/")){
                        if (time==0){
                            temp=temp+popA+"/"+popB;
                            time++;
                        }
                        else{
                            temp=temp+"/"+popB;
                        }
                        stack.push(popA+"/"+popB);
                    }
                }
                else{
                    stack.push(str);
                }
            }

4.计算后缀表达式

这个很简单,只需要利用栈,然后遍历一次后缀表达式即可。如果遇到操作数,则操作数进栈;如果遇到一元运算符,则取出栈顶元素,运算后重新入栈;如果遇到二元运算符,则从栈中弹出两个元素,计算后重新入栈

public static String[] Calculate(ArrayList<String> houzhui) {
       //str是一个后缀表达式
        Stack<Double> stack = new Stack<Double>();
        Double result;

        for (String str:houzhui) {
            if(str.equals("√")||str.equals("2")||str.equals("sin")||str.equals("cos")||str.equals("tan")){
                double popB = stack.pop();
                if (str.equals("√")){
                    if (popB!=0)
                        stack.push(Math.sqrt(popB));
                    else
                        stack.push(1.0);
                }
                if (str.equals("2")){
                    stack.push(Math.pow(popB,2));
                }
                if (str.equals("sin")){
                    stack.push(Math.sin(popB));
                }
                if (str.equals("cos")){
                    stack.push(Math.cos(popB));
                }
                if (str.equals("tan")){
                    stack.push(Math.tan(popB));
                }
            }
            else if (str.equals("+")||str.equals("-")||str.equals("*")||str.equals("/")){
                double popB = stack.pop();
                double popA = stack.pop();
                if (str.equals("+")){
                    stack.push(popA+popB);
                }
                else if (str.equals("-")){
                    stack.push(popA-popB);
                }
                else if (str.equals("*")){
                    stack.push(popA*popB);
                }
                else {
                    stack.push(popA/popB);
                }
            }
            else{
                stack.push(Double.parseDouble(str));
            }
        }
        result = stack.pop();
        try {
            result = new BigDecimal(result).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        }catch (Exception e){

        }
        System.out.println("结果是: "+result);
        if (result.isNaN()){
            result=1.0;
        }
        if (result.isInfinite()){
            result=2.0;
        }
        String[] finalResult = new String[5];
        finalResult[0]=Double.toString(result);
        for(int j=0;j<3;j++){
            int judge = (int) (0 + Math.random() * (400 - 0 + 1));
            double tempAnswer=0.0;
            try{
                tempAnswer = new BigDecimal(result+judge).setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
            }catch (Exception e){

            }
            if(judge<100){
                finalResult[j+1]=Double.toString(tempAnswer);
            }
            else if (judge<250){
                finalResult[j+1]="√"+Double.toString(tempAnswer);
            }
            else if (judge<300){
                finalResult[j+1]="sin"+Double.toString(tempAnswer);
            }
            else if (judge<350){
                finalResult[j+1]="cos"+Double.toString(tempAnswer);
            }
            else{
                finalResult[j+1]="tan"+Double.toString(tempAnswer);
            }
        }
        for(int j=0;j<3;j++){
            int tempA = (int) (0 + Math.random() * (3 - 0 + 1));
            int tempB = (int) (0 + Math.random() * (3 - 0 + 1));
            String temp = finalResult[tempA];
            finalResult[tempA] = finalResult[tempB];
            finalResult[tempB] = temp;
        }

        String StrResult = Double.toString(result);
        if(finalResult[0].equals(StrResult)){
            finalResult[4]="A";
        }
        else if (finalResult[1].equals(StrResult)){
            finalResult[4]="B";
        }
        else if (finalResult[2].equals(StrResult)){
            finalResult[4]="C";
        }
        else{
            finalResult[4]="D";
        }

        return finalResult;
    }

函数返回值为字符串数组,这是因为函数返回了包括正确答案在内的四个备选答案

5.保存文件

复用了个人项目保存题目为txt文件的代码,将用户名作为路径,这样每一个账户都有一个文件来保存生成的题目

Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy--MM--dd--HH--mm--ss");
        String time = sdf.format(date);

将文本文件的名字设置为当前时间

public static void WriteToFile(String FilePath, String[] temp) throws IOException {
        FileOutputStream fos = null;
        fos = new FileOutputStream(FilePath, true); //不覆盖原内容
        for (int i = 0; i < temp.length; i++) {
            String msg = Integer.toString(i + 1) + " " + temp[i] + ‘\n‘ + ‘\n‘;
            fos.write(msg.getBytes());
        }
        fos.close();
    }

通过文件的输入输出流,将生成的中缀表达式写入txt文档

三、UI界面

1.初始化界面

包括手机号码和验证码输入框、获取验证码按钮和注册按钮等,给按钮添加监听器,点击按钮后发送验证码或启动注册程序,注册成功后将账户信息保存在本地

public void Init(){
        //设置手机号码标签
        JPanel jp1=new JPanel();
        JLabel jl1 = new JLabel("手机号码:");    //用标签来表示文本
        Font font1 = new Font("宋体", Font.BOLD, 16);
        Dimension dm1=new Dimension(200,30);
        jl1.setFont(font1);
        jp1.add(jl1);
        //设置手机号码输入栏
        m_jtf1 = new JTextField();
        m_jtf1.setPreferredSize(dm1);
        jp1.add(m_jtf1);
        //获取验证码 按钮
        JButton jb1 = new JButton("获取验证码");
        jb1.setFont(font1);
        jp1.add(jb1);

        //设置验证码标签
        JPanel jp2=new JPanel();
        JLabel jL2=new JLabel("验证码:");
        jL2.setFont(font1);
        jp2.add(jL2);
        //设置验证码输入栏
        m_jtf2 = new JTextField();
        m_jtf2.setPreferredSize(dm1);
        jp2.add(m_jtf2);

        //设置注册按钮
        JPanel jp3=new JPanel();
        JButton jb2=new JButton("注册");
        jb2.setFont(font1);
        jp3.add(jb2);

        //已有账户直接登录
        JPanel jp4=new JPanel();
        JButton jb3=new JButton("已注册,直接登录");
        jb3.setFont(font1);
        jp4.add(jb3);

        //为按钮添加监听器
        jb1.addActionListener(new CheckAction());
        jb2.addActionListener(new RegsAction());
        jb3.addActionListener(new ChangeAction());

        ///设置面板放置的位置
        jp1.setBounds(325,100,600,40);
        jp2.setBounds(325,150,600,40);
        jp3.setBounds(325,200,600,40);

        this.getContentPane().setBackground(Color.decode("#eeeeee"));

        //把面板加入窗体
        this.add(jp1);
        this.add(jp2);
        this.add(jp3);
        this.add(jp4);

        //设置窗体属性可见
        this.setVisible(true);
        this.setDefaultCloseOperation(3); //窗口关闭时程序自动停止运行
    }

2.登录界面

用户注册后,跳转到设置用户名和密码界面。界面包括用户名和密码输入框以及确认按钮。有一个按钮,点击可以切换隐藏密码和查看密码,此功能是通过一个JTextField和一个JPasswordField切换实现的

public void load(){
        Font font1 = new Font("宋体", Font.BOLD, 16);
        Dimension dm1=new Dimension(200,30);

        //用户名面板
        JPanel jp1 = new JPanel();
        JLabel jl1 = new JLabel("用户名:");
        jl1.setFont(font1);
        jp1.add(jl1);
        m_jtf3 =new JTextField();
        m_jtf3.setPreferredSize(dm1);
        jp1.add(m_jtf3);
        jp1.setBounds(325,100,600,40);

        //密码面板
        JPanel jp2=new JPanel();
        JLabel jl2=new JLabel("密码");
        jl2.setFont(font1);
        jp2.add(jl2);
        m_jpf1 = new JPasswordField();
        m_jpf1.setPreferredSize(dm1);
        jp2.add(m_jpf1);
        jp2.setBounds(325,150,600,40);

        m_temp =new JTextField();
        m_temp.setPreferredSize(dm1);
        m_temp.setVisible(false);
        jp2.add(m_temp);
        m_vis = new JButton("查看密码");
        jp2.add(m_vis);
        m_vis.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (m_vis.getText().equals("查看密码")){
                    m_temp.setText(String.valueOf(m_jpf1.getPassword()));
                    m_temp.setVisible(true);
                    m_jpf1.setVisible(false);
                    m_vis.setText("隐藏密码");
                }
                else {
                    m_temp.setVisible(false);
                    m_jpf1.setVisible(true);
                    m_vis.setText("查看密码");
                }
            }
        });


        //再次确认密码面板
        JPanel jp3=new JPanel();
        JLabel jl3=new JLabel("再次输入密码");
        jl3.setFont(font1);
        jp3.add(jl3);
        m_jpf2 = new JPasswordField();
        m_jpf2.setPreferredSize(dm1);
        jp3.add(m_jpf2);
        JButton jb1=new JButton("确认");
        jb1.setFont(font1);
        jp3.add(jb1);
        jp3.setBounds(325,200,600,40);

        //加入用户名和密码输入规范的提示
        JPanel jp4=new JPanel();
        JPanel jp5 = new JPanel();
        JLabel jl_id = new JLabel("1.用户名不能以数字开头,长度为6-10");
        JLabel jl_password = new JLabel("2.密码至少8个字符,至少1个大写字母,1个小写字母和1个数字,不能包含特殊字符");
        jl_id.setFont(font1);
        jl_password.setFont(font1);
        jp4.add(jl_id);
        jp5.add(jl_password);
        jp4.setBounds(325,400,300,40);
        jp5.setBounds(325,500,300,40);

        jb1.addActionListener(new OKAction());

        this.add(jp1);
        this.add(jp2);
        this.add(jp3);
        this.add(jp4);
        this.add(jp5);

        this.setVisible(true);
        System.out.println("请设置您的用户名和密码");
    }

3.选择题目界面

包含一个单选框和一个数字输入框,用户输入题目类型和数量。题目类型为在(小学、初中、高中)三个选项中单选,数量为10-30之间的数字

public void ChooseType(){
        Font font1 = new Font("宋体", Font.BOLD, 16);
        Dimension dm1=new Dimension(200,30);

        //题目类型面板
        JPanel jp1=new JPanel();
        JLabel jl1 = new JLabel("题目类型(小学、初中、高中)");
        jl1.setFont(font1);
        jp1.add(jl1);

        m_jr1_Type = new JRadioButton("小学");
        m_jr2_Type = new JRadioButton("初中");
        m_jr3_Type = new JRadioButton("高中");
        jp1.setBounds(325,100,600,40);
        jp1.add(m_jr1_Type);
        jp1.add(m_jr2_Type);
        jp1.add(m_jr3_Type);
        ButtonGroup group = new ButtonGroup();
        group.add(m_jr1_Type);
        group.add(m_jr2_Type);
        group.add(m_jr3_Type);

        //题目数量面板
        JPanel jp2=new JPanel();
        JLabel jl2 = new JLabel("题目数量");
        jl2.setFont(font1);
        jp2.add(jl2);
        m_jtf7 =new JTextField();
        m_jtf7.setPreferredSize(dm1);
        jp2.add(m_jtf7);
        JButton jb1 = new JButton("确定");
        jb1.setFont(font1);
        jp2.add(jb1);
        jp2.setBounds(325,150,600,40);

        JPanel jp3=new JPanel();
        JButton jb2=new JButton("修改密码");
        jp3.add(jb2);

        jb1.addActionListener(new TypeAction());
        jb2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                LoginUI.this.setVisible(false);
                LoginUI.this.getContentPane().removeAll();
                LoginUI.this.repaint();
                ChangePwd();
            }
        });

        this.add(jp1);
        this.add(jp2);
        this.add(jp3);
        this.setVisible(true);
        System.out.println("请输入生成的题目类型和题目数量");

    }

4.做题界面

从GenerateTest()函数的返回值得到试卷,然后再用Calculate()函数得到备选答案,把备选答案加入单选按钮,放置在面板上。用户可点击”上一题“”下一题“按钮来切换当前的题目,做过的题目答案会保存

public void show_test(String[] test){
        Font font1 = new Font("宋体", Font.BOLD, 50);
        Dimension dm1=new Dimension(200,30);
        int len=test.length;
        int i = g_index;
        String temp=test[i];
        //题干
        JPanel jp1=new JPanel();
        JLabel jl1 = new JLabel("第"+Integer.toString(i+1)+"题: "+temp+" =");
        jl1.setFont(new Font("宋体",Font.BOLD,20));
        jl1.setBackground(Color.white);
        jp1.add(jl1);
        jp1.setBounds(325,200,600,40);

        //四个备选答案和一个按钮
        //一个函数可以计算答案,并生成四个备选答案
        ArrayList<String> houzhui=Common.map.get(temp);
        result = Common.Calculate(houzhui);        //四个备选答案和正确答案都在这里
        JPanel jp2 = new JPanel();
        JPanel jp6 = new JPanel();

        m_jrA = new JRadioButton("A "+". "+result[0]);
        m_jrB = new JRadioButton("B "+". "+result[1]);
        m_jrC = new JRadioButton("C "+". "+result[2]);
        m_jrD = new JRadioButton("D "+". "+result[3]);
        m_jrA.setBackground(Color.white);
        m_jrB.setBackground(Color.white);
        m_jrC.setBackground(Color.white);
        m_jrD.setBackground(Color.white);
        JButton jb6 = new JButton("下一题");
        jb6.setBackground(Color.blue);
        if(i==len-1){
            jb6.setText("提交");
        }
        JButton jb7 = new JButton("上一题");
        jb7.setBackground(Color.yellow);
        jp2.add(m_jrA);
        jp2.add(m_jrB);
        jp2.add(m_jrC);
        jp2.add(m_jrD);
        if (i!=0){
            jp6.add(jb7);
        }
        jp6.add(jb6);

        ButtonGroup group = new ButtonGroup();
        group.add(m_jrA);
        group.add(m_jrB);
        group.add(m_jrC);
        group.add(m_jrD);

        jp2.setBounds(325,250,600,40);
        jp6.setBounds(325,500,600,40);

        jb6.addActionListener(new NextAction());
        jb7.addActionListener(new FormerAction());

        String userTemp=userAnswer[g_index];
        if (userTemp.equals("#")){
            System.out.println("此题用户还没有做!");
        }
        else if (userTemp.equals(result[0])){
            m_jrA.setSelected(true);
        }
        else if (userTemp.equals(result[1])){
            m_jrB.setSelected(true);
        }
        else if (userTemp.equals(result[2])){
            m_jrC.setSelected(true);
        }
        else {
            m_jrD.setSelected(true);
        }


        this.add(jp1);
        this.add(jp2);
        this.add(jp6);


        this.setVisible(true);
    }

5.汇报界面

在用户做完全部题目后,界面显示分数,用户可选择继续做题或者退出

public void show_score(){
        Font font1 = new Font("宋体", Font.BOLD, 50);
        Dimension dm1=new Dimension(200,30);
        int goal = g_score;
        int len = test.length;

        JPanel jp1 = new JPanel();
        JLabel jl1 = new JLabel("您的分数为");
        JLabel jl2 = new JLabel(goal+"/"+len+"!");
        jl2.setFont(font1);
        JButton jb1 =new JButton("继续做题");
        jb1.setBackground(Color.yellow);
        JButton jb2 = new JButton("退出");
        jb2.setBackground(Color.blue);
        jp1.add(jl1);
        jp1.add(jl2);
        jp1.add(jb1);
        jp1.add(jb2);
        jp1.setBounds(325,150,600,40);

        jb1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                LoginUI.this.setVisible(false);
                LoginUI.this.getContentPane().removeAll();
                LoginUI.this.repaint();
                g_index=0;
                ChooseType();
            }
        });

        jb2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });

        try {
            DataBase.SaveToLoc();
        } catch (IOException e) {
            e.printStackTrace();
        }

        this.add(jp1);
        this.setVisible(true);
    }

6.用户信息

用户信息保存在名为account的txt文件里,在程序开始,程序将account信息存入一个ArrayList链表,在程序结束后,将ArrayList里的内容写回account文件

public static void SaveToLoc()throws IOException {
        FileOutputStream fos = null;
        fos = new FileOutputStream("src/Frame/"   + "account.txt"); //不覆盖原内容
        for (String s : al) {
            String msg = s + ‘\n‘;
            fos.write(msg.getBytes());
        }
        fos.close();
    }
public static void SaveToCur(){
        File file = new File("src/Frame/" + "account.txt");
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        try{
            FileReader fr = new FileReader("src/Frame/"  + "account.txt");
            BufferedReader bf = new BufferedReader(fr);
            String str;
            while ((str = bf.readLine()) != null) {
                al.add(str);
            }
            bf.close();
            fr.close();
        }
        catch (IOException e){
            e.printStackTrace();
        }
    }

总结

以上就是今天要讲的内容,本文仅仅简单介绍了复用的代码块和UI界面的实现,在编程过程中总结了几点经验
  • 刷新当前界面时,可以先设置窗体为不可见,然后去除所有的组件,重绘。
  • 为按钮添加监听器时,可以写一个内部类,这样子内部类可以访问外部类的成员,从而可以很方便的获取文本框或密码框的内容

结对编程项目分析与经验总结

原文:https://www.cnblogs.com/wangchenglong1/p/13785466.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!