结对项目

一、Github

  Githu:https://github.com/tryanddie/teamwork_2

  项目成员:陈创智,3118005041;蔡双浩 3118005040。

二、PSP

 

Planning

计划

 

 

 

· Estimate

· 估计这个任务需要多少时间

40

30

 

Development

开发

 

 

 

· Analysis

· 需求分析 (包括学习新技术)

 200

 240

 

· Design Spec

· 生成设计文档

60

50

 

· Design Review

· 设计复审 (和同事审核设计文档)

 80

           80

 

 

 

· Coding Standard

· 代码规范 (为目前的开发制定合适的规范)

10 

10 

 

· Design

· 具体设计

60 

55 

 

· Coding

· 具体编码

420 

 500

 

· Code Review

· 代码复审

 120

180

 

· Test

· 测试(自我测试,修改代码,提交修改)

100 

150

 

Reporting

报告

 

 

 

· Test Report

· 测试报告

 30

 45

 

· Size Measurement

· 计算工作量

 5

 

· Postmortem & Process Improvement Plan

· 事后总结, 并提出过程改进计划

120 

100

 

合计

 

        1245        1445

 

 

     

 二、题目

       设计一个自动生成四则运算算术题的控制台程序,或者其他类似功能的程序。

  • 支持加减乘除算符,支持括号
  • 支持整数和分数,其中,当分数的分子的绝对值大于分母时,采用带分数形式,如11/4应显示为2`3/4;
  • 生成的题目中计算过程不能产生负数,也就是说算术表达式中如果存在形如e1− e2的子表达式,那么e1≥ e2。
  • 每道题目中出现的运算符个数不超过3个。
  • 程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。例如,23 + 45 = 和45 + 23 = 是重复的题目,6 × 8 = 和8 × 6 = 也是重复的题目。3+(2+1)和1+2+3这两个题目是重复的,由于+是左结合的,1+2+3等价于(1+2)+3,也就是3+(1+2),也就是3+(2+1)。但是1+2+3和3+2+1是不重复的两道题,因为1+2+3等价于(1+2)+3,而3+2+1等价于(3+2)+1,它们之间不能通过有限次交换变成同一个题目。
  • 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件。
  • 程序应能支持一万道题目的生成。
  • 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计。
  • 统计结果输出到文件Grade.txt

三、困难与解决方案

 控制生成题目的个数,控制题目中数值的范围

用循环次数来控制生成的个数,用ran来控制随机生成的范围

 

每道题目中出现的运算符个数不超过3个

用随机数来生成决定运算符个数

 

其他各种问题等

四、代码说明

主函数代码

public class index {
    static     String   wenTi = "Exercises.txt";   //对照答案时问题的路径,未选取的时候默认为Exercises.txt文件
    static     String  daAn = "Answers.txt";   //对照答案时问题的路径,未选取的时候默认为Exercises.txt文件
    static String sizi = new String();
    static char[] fuhao = {'+','-','*','÷'};
    static String str[][] = new String[10000][7];
    public static void main(String[] args)  {
        
        
        
        
        
        sizi=""; 
    
        
        
        
        //设置主界面
        JFrame mainFrame= new JFrame("题目自动生成器");
          mainFrame.setSize(410,400);
          mainFrame.setLocation(200, 200);
          mainFrame.setLayout(new GridLayout(3, 1));
          mainFrame.setLayout(null);
          mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        
          
          
          
         // 创建输入框
          
          JPanel Input = new JPanel();
          Input.setBounds(10, 10, 375, 120);
          Input.setLayout(new GridLayout(4,3,10,10));
          
          JLabel geshu = new JLabel("生成题目个数:");
          final JTextField geshuText = new JTextField();
          
          
          JLabel  fanwei= new JLabel("生成数值范围:");
          final JTextField fanweiText = new JTextField();

JButton b = new JButton("生成随机题目");
final JButton wenti = new JButton("选择题目文件");
final JButton daan= new JButton("选择答案文件");
JButton jieguo = new JButton("判断对错");
wenti.setLayout(null);    
daan.setLayout(null);        
b.setLayout(null);        
jieguo.setLayout(null);    
        Input.add(geshu);
        Input.add(geshuText);
        Input.add(fanwei);
        Input.add(fanweiText);
  
  
        //文本域
                
                b.setBounds(120, 120 + 30, 160, 30); 
                wenti.setBounds(10, 220, 160, 30);   
                daan.setBounds(210, 220 , 160, 30);
                jieguo.setBounds(120,250, 160, 30);
              
            //主界面加入文本域,按钮和输入框    
                
                mainFrame.add(Input);
                mainFrame.add(b);
                mainFrame.add(wenti);
                mainFrame.add(daan);
                mainFrame.add(jieguo);
                mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        
                wenti.addActionListener(new ActionListener() {      //选择问题的文件
                        public void actionPerformed(ActionEvent e) {
                            JFileChooser chooser = new JFileChooser(); //设置选择器
                            chooser.setMultiSelectionEnabled(true); //设为多选
                            int returnVal = chooser.showOpenDialog(wenti); //是否打开文件选择框
                            System.out.println("returnVal="+returnVal);
                            if (returnVal == JFileChooser.APPROVE_OPTION) { //如果符合文件类型

                             wenTi=  chooser.getSelectedFile().getAbsolutePath();
                            }

                        }
                        });
                
            
                
            daan.addActionListener(new ActionListener() {      //选择问题的文件
                    public void actionPerformed(ActionEvent e) {
                        JFileChooser chooser = new JFileChooser(); //设置选择器
                        chooser.setMultiSelectionEnabled(true); //设为多选
                        int returnVal = chooser.showOpenDialog(daan); //是否打开文件选择框
                        System.out.println("returnVal="+returnVal);
                        if (returnVal == JFileChooser.APPROVE_OPTION) { //如果符合文件类型
                daAn=  chooser.getSelectedFile().getAbsolutePath();
                        }

                    }});
            
                
                
            
            
            
            
            jieguo.addActionListener(new ActionListener() {      //选择问题的文件
                public void actionPerformed(ActionEvent e) {
                   
                    try{ String daan=result(wenTi);
                    saveAsFileWriter(daan,"Answer1.txt");         //将问题的答案放入答案文件
                    }
                    catch(IOException h)
                    {h.printStackTrace();}
                        
                    try{judge("Answer1.txt",daAn);}
                    catch(IOException k)
                    {k.printStackTrace();}
                    
                    
                    
                }
                });
                
                

    //点击按钮,开始生成题目
                 b.addActionListener(new ActionListener() {
                     boolean checkedpass = true;
                      public void actionPerformed(ActionEvent e) {

                            checkedpass = true;
                         //检验是否有数值没有填
                          checkNumber(geshuText,"题目个数");
                          checkNumber(fanweiText,"题目范围");  
                        
                      String     Strnum =    geshuText.getText();
                      String    Strscope = fanweiText.getText();
                      //将输入的值转化为整型
                        int  num  = Integer.parseInt(Strnum);
                        int scope = Integer.parseInt(Strscope);
                      create(scope,num);
                    saveAsFileWriter(sizi,"Exercises.txt"); //生成问题存进文件
                    
                    
                  try{ String daan=result("Exercises.txt");
                saveAsFileWriter(daan,"Answers.txt");         //将问题的答案放入答案文件
                }
                catch(IOException h)
                {h.printStackTrace();}
                    
                    
                    
                  JOptionPane.showMessageDialog(null,"随机生成题目成功\n题目与答案已经保存");
                       }
                      
                 
                    //检验输入数值是否为整数
                        private void checkNumber(JTextField tf, String msg){
                            if(!checkedpass)
                                return;
                            String value = tf.getText();
                            try {
                                Integer.parseInt(value);
                            } catch (NumberFormatException e) {
                                JOptionPane.showMessageDialog(null, msg + "必须是整数");
                                tf.grabFocus();
                                checkedpass = false;
                            }
                        }

        
                      
                      
                 
                 
                 });//按钮结束位置
          
                  mainFrame.setVisible(true);
          
    } 
          
          

将字符串放入文件

     private static void saveAsFileWriter(String content,String filePath) {
         //content为写入的字符串,filepath为写入文件的路径
    
            FileWriter fwriter = null;
            try {
                
                fwriter = new FileWriter(filePath);
                fwriter.write(content);
            } catch (IOException ex) {
                ex.printStackTrace();
            } finally {
                try {
                    fwriter.flush();
                    fwriter.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
        

随机生成题目

 static void create(int r,int p) {    //随机生成题目,r为生成范围,p为生成个数
            
            for( int n=0 ; n<p  ;){   //开始循环
            Random ran = new Random();
            int flag=ran.nextInt(3)+1;
              String [] array=new String[2*flag+1];
            char[] a = new char[flag];
            //char[] c = new char[flag];
            int[] number = new int[flag+1];
            // int[]   paixu=new int[flag+1];
            
            for(int i=0;i<flag+1;i++) {
                number[i]=ran.nextInt(r)+1;//创建三个随机数
    
            }
            
            
            
            for(int j=0;j<flag;j++) {
                a[j]=fuhao[ran.nextInt(4)];
                switch(a[j]) {
                //  '-'对数有特殊要求
                case '-': if(number[j]>number[j+1])
                            break;
                          else {j--;break;}
                          
                case '÷': if(number[j]%number[j+1]==0)
                    break;
                  else {j--;break;}

                case '+':
                case '*':break;
            }
            
            }//该括号为生成字符结束
            
        
            
            for(int i=0; i < flag ; i++)
                array[i] =  String.valueOf(a[i]);
            for(int i=0; i < flag+1; i++)
                array[flag+i]=String.valueOf(number[i]); //将字符都放进array中
        int biaoji=0;
            for(int i=0 ; i< p; i++)
                {if(Arrays.equals(str[i],array))
                    {biaoji =1;            //如果与已有式子一样,重新生成题目
                    break;}
                }
            
            
            
            String shizi = new String();
            //对运算数和运算符进行连接
            shizi=String.valueOf(number[0]);
            for(int k=0;k<flag;k++) {
                shizi=shizi+a[k]+String.valueOf(number[k+1]);
            }
            if(count(shizi)==false)
        biaoji = 1;
            
            
            
            
            
                        
        
            if(biaoji == 0){
                str[n] = array;
                
            n++;    
      
            for(int k=0;k<flag;k++) {
            
                sizi=sizi+String.valueOf(number[k])+a[k];
            }
            
            sizi =sizi + String.valueOf(number[flag])+'=' + '\n';
            
            }    
            }

     }

对答案进行判断

     
     
    static //对答案进行判断        
            void judge(String exe,String answer) throws IOException {
                String correct=" ";//用于存储正确的题目的编号,即(2,3)这样的
                int correct_=0;        //用于存储正确的题目总数
                String wrong=" ";    //用于存储错误题目的编号
                int wrong_=0;        //用于存储错误的题目总数
                
                //读取回答文件,若不存在则抛出异常 
                File myexe=new File(exe);
                String exe2=null;        //用于存储读取的回答
                 if(!myexe.exists()||myexe.isDirectory())
                     throw new FileNotFoundException();
                 
               //读取答案文件,若不存在则抛出异常  
                 File answer_1=new File(answer);
                 String answer_2=null;     //用于存储读取的答案
                 if(!answer_1.exists()||answer_1.isDirectory())
                     throw new FileNotFoundException();
               
                 BufferedReader exe1=new BufferedReader(new FileReader(myexe));
                 BufferedReader answer_3=new BufferedReader(new FileReader(answer_1));
               
                 //exe2和answer_3用于存储读取的行  
                 for(int i=1;((exe2=exe1.readLine())!=null && (answer_2=answer_3.readLine())!=null);i++) {
                //如果文件没读完,循环继续
                     if(exe2.equals(answer_2)) {
                         //字符相同,说明答案一样
                         if(correct==" ")
                             correct=correct+String.valueOf(i);    ////纯粹为了保持 “,”的数目正常
                         else
                             correct=correct+','+String.valueOf(i);    //将正确的编号接入字符串
                         correct_++;                                //正确的题目数+1
                     }
                     else { 
                         if(wrong==" ")
                             wrong=wrong+String.valueOf(i);        //纯粹为了保持 “,”的数目正常
                         else
                             wrong=wrong+','+String.valueOf(i);    //将错误的编号接入字符串
                         wrong_++; 
                     }
                 }
                 //如果你要测试的话,main函数中的路径记得改
            JOptionPane.showMessageDialog(null,"correct:"+String.valueOf(correct_)+'('+correct+" )"+"\nwrong:"+String.valueOf(wrong_)+'('+wrong+" )");
                // System.out.println("wrong:"+String.valueOf(wrong_)+'('+wrong+" )");
                 exe1.close();
                 answer_3.close();
                 
            }
     
     
     
     
     
     
    
    
    
    
    static boolean count(String str) {            //单个判断正负
        str=remove(str, '=');
        str=str.replace('÷','/');
  ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine se = manager.getEngineByName("js");
        Double result = null;

        try {
            result = Double.valueOf(se.eval(str).toString());
            if (result == null) {
                result = new Double(0);
            }
        } catch (ScriptException e) {
            e.printStackTrace();
        }

       if(result>0) return true;
       else return false;
 }
    

计算生成题目答案

 static String result(String Lujin) throws IOException {
            File answer_1=new File(Lujin);
                  String str=null;     //用于存储读取的答案
                  if(!answer_1.exists()||answer_1.isDirectory())
                      throw new FileNotFoundException();
                  
                  String result_0="";
                
                  BufferedReader answer_3=new BufferedReader(new FileReader(answer_1));
                  while((str=answer_3.readLine())!=null) {
                 str=remove(str, '=');
                 str=str.replace('÷','/');
           
           ScriptEngineManager manager = new ScriptEngineManager();
                 ScriptEngine se = manager.getEngineByName("js");
                 Double result = null;

                 try {
                     result = Double.valueOf(se.eval(str).toString());
                     if (result == null) {
                         result = new Double(0);
                     }
                 } catch (ScriptException e) {
                     e.printStackTrace();
                 }
                 if(result.equals(Math.floor(result))) {
                  double result1=result;
                  int i= (int)result1;
                  result_0=result_0+String.valueOf(i)+"\n";
                  }
                  }
                  answer_3.close();
                  return result_0;
          }
    
    
    
    

五、测试运行

生成10000道题目

 

 

 修改几个答案并比较结果

 

 与预期效果一致

 

六、两人总结

这次项目做起来比起上一次更加有规划性了,通过两人合作,各自互补,学到了许多新的知识,也学会了如何合作才能更快的完成项目。但是,

在提前准备方面,我们做的还有些不足,对于项目的一些“坑”没有提前谈论清楚,导致项目进展缓慢,以及在协调方面有了一些问题,将一部分时间花费在了解同伴需求的身上,下次应该能更进一步。

posted @ 2020-04-01 21:02  Edward爱德华  阅读(163)  评论(0编辑  收藏  举报