结对项目——四则运算

一、github地址

https://github.com/kinglc/AutoCalculator

二、PSP

PSP2.1  

   Personal Software Process Stages    

 预估耗时(分钟)

 实际耗时(分钟)

Planning

计划

30

30

扫描二维码关注公众号,回复: 1092361 查看本文章

·Estimate

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

30

30

Development

开发

2010

 2160

·Analysis

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

480

400

·Design Spec

·生成设计文档

60

50

·Design Review

·设计复审

30

30

·Coding Standard

·代码规范

30

60

·Design

·具体设计

240

300

·Coding

·具体编码

900

1080

·Code Review

·代码复审

90

60

·Test

·测试

180

180

Reporting

报告

 70

 70

·Test Report

·测试报告

30

30

·Size Measurement

·计算工作量

10

10

·Postmortem&Process Improvement Plan

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

30

30

 

合计

2110

2260

三、设计思路

  1.整个项目包括生成题目及存储、解题、GUI、倒计时及历史记录功能。(队友博客地址https://home.cnblogs.com/u/shera)

  2.解题:

    按优先级分为小括号、两种乘方、乘除和加减。用while处理完算式中所有包含该运算符的部分,依次往后确定优先级。使用substring获取计算的数字,转为BigDecimal类型提高精度。

    乘方运算中由于pow函数参数为double,为了保证精度此处使用for循环进行计算。

  1  public String getAns(String s) {
  2         try {
  3             while (s.indexOf("(") != -1 && s.indexOf(")") != -1) {//小括号
  4                 int left;
  5                 int right;
  6                 String front;
  7                 String behind;
  8                 left = s.lastIndexOf("(");
  9                 front = s.substring(0, left);
 10                 s = s.substring(left + 1);
 11                 right = s.indexOf(")");
 12                 behind = s.substring(right + 1);
 13                 s = s.substring(0, right);
 14                 s = front + getAns(s) + behind;
 15             }
 16 
 17             while (s.indexOf("^") != -1 || s.indexOf("**") != -1) {//乘方
 18                 String front;
 19                 int mul = (s.indexOf("^") + s.indexOf("**"));
 20                 int num = mul++;
 21                 while (num > 0) {
 22                     if (s.charAt(num) == '+' || s.charAt(num) == '-' || s.charAt(num) == '*' || s.charAt(num) == '÷')
 23                         break;
 24                     num--;
 25                 }
 26                 if(num!=0)
 27                     num++;
 28                 String a = s.substring(num, mul);//底数
 29                 front=s.substring(0,num);
 30                 num = mul + power_form;
 31                 while (num < s.length()) {
 32                     if (s.charAt(num) == '+' || s.charAt(num) == '-' || s.charAt(num) == '*' || s.charAt(num) == '÷')
 33                         break;
 34                     num++;
 35                 }
 36                 String b = s.substring(mul + power_form, num);//
 37                 int b1 = Integer.parseInt(b);
 38 
 39                 String c="1";
 40                 if(a.indexOf('/')!=-1)
 41                 {
 42                     Fraction f1 = new Fraction(a);
 43                     for (int i = 0; i < b1; i++)
 44                     {
 45                         Fraction ft = new Fraction(c);
 46                         c = ft.multiply(f1);
 47                     }
 48                 }
 49                 else {
 50                     BigDecimal a1 = new BigDecimal(a);
 51                     BigDecimal ans = new BigDecimal(1);
 52                     for (int i = 0; i < b1; i++)
 53                         ans = ans.multiply(a1);
 54                     c = "" + ans;
 55                 }
 56                 s = front + c + s.substring(mul + 1 + power_form);
 57             }
 58 
 59 
 60             while (s.indexOf("*") != -1 || s.indexOf("÷") != -1) {
 61                 int multiply = s.indexOf("*");
 62                 int divide = s.indexOf("÷");
 63                 int way;
 64                 if (multiply == -1)
 65                     multiply = 0xfffffff;
 66                 if (divide == -1)
 67                     divide = 0xfffffff;
 68                 if (multiply < divide)//从左向右计算
 69                     way = multiply;
 70                 else way = divide;
 71                 int front = way - 1;
 72                 while (front > 0) {
 73                     if (s.charAt(front) == '+' || s.charAt(front) == '-') {
 74                         front++;
 75                         break;
 76                     }
 77                     front--;
 78                 }
 79                 String a = s.substring(front, way);
 80                 int behind = way + 1;
 81                 while (behind<s.length()) {
 82                     if (s.charAt(behind) == '+' || s.charAt(behind) == '-' || s.charAt(behind) == '*' || s.charAt(behind) == '÷')
 83                         break;
 84                     behind++;
 85                 }
 86                 String b = s.substring(way + 1, behind);
 87                 String c;
 88 
 89                 if(a.indexOf('/')==-1&&b.indexOf('/')==-1) {
 90                     BigDecimal a1 = new BigDecimal(a);
 91                     BigDecimal b1 = new BigDecimal(b);
 92                     if (divide == way)
 93                         c = a1.divide(b1,3, BigDecimal.ROUND_HALF_UP).toString();
 94                     else c = a1.multiply(b1).toString();
 95                 }
 96                 else{
 97                     Fraction f1 = new Fraction(a);
 98                     Fraction f2 = new Fraction(b);
 99                     if (divide == way)
100                         c = f1.divide(f2);
101                     else c = f1.multiply(f2);
102                 }
103                 s = s.substring(0, front) + c + s.substring(behind);
104             }
105 
106 
107             while (s.indexOf("+") != -1 || s.indexOf("-") != -1) {
108                 int plus = s.indexOf("+");
109                 int minus = s.indexOf("-");
110                 int way;
111                 if (plus == -1)
112                     plus = 0xfffffff;
113                 if (minus == -1)
114                     minus = 0xfffffff;
115                 if (plus < minus)
116                     way = plus;
117                 else way = minus;
118                 int front = way - 1;
119                 while (front > 0) {
120                     if (s.charAt(front) == '+' || s.charAt(front) == '-') {
121                         front++;
122                         break;
123                     }
124                     front--;
125                 }
126                 String a = s.substring(front, way);
127                 int behind = way + 1;
128                 while (s.substring(behind).length() > 0) {
129                     if (s.charAt(behind) == '+' || s.charAt(behind) == '-')
130                         break;
131                     behind++;
132                 }
133                 String b = s.substring(way + 1, behind);
134                 String c;
135 
136                 if(a.indexOf('/')==-1&&b.indexOf('/')==-1) {
137                     BigDecimal a1 = new BigDecimal(a);
138                     BigDecimal b1 = new BigDecimal(b);
139                     if (minus == way)
140                         c = a1.subtract(b1).toString();
141                     else c = a1.add(b1).toString();
142                 }
143                 else{
144                     Fraction f1 = new Fraction(a);
145                     Fraction f2 = new Fraction(b);
146                     if (minus == way)
147                         c = f1.substract(f2);
148                     else c = f1.add(f2);
149                 }
150                 s = s.substring(0, front) + c + s.substring(behind);
151             }
152 
153             if(s.indexOf('.')!=-1)
154                 s=s.substring(0,s.length()-1);
155             return s;
156 
157         } catch (Exception e) {
158             return "计算部分出错";
159         }
160     }
View Code

    分数单独开一个类,分为分子,分母进行计算。类中内含加减乘除约分方法,其中约分为private。

 1 public class Fraction {
 2     int nume;//分数的分子
 3     int deno;//分数的分母
 4 
 5     public Fraction() {}
 6 
 7     public Fraction(String s)
 8     {
 9         int frac=s.indexOf('/');
10         if(frac==-1)//若是整数,分母按1算
11         {
12             this.nume=Integer.parseInt(s);
13             this.deno=1;
14         }
15         else{
16             this.nume=Integer.parseInt(s.substring(0,frac));
17             this.deno=Integer.parseInt(s.substring(frac+1));
18         }
19     }
20 
21     public String add(Fraction f)
22     {
23         Fraction ans=new Fraction();
24         ans.deno=this.deno*f.deno/gcd(this.deno,f.deno);//通分
25         this.nume*=ans.deno/this.deno;
26         f.nume*=ans.deno/f.deno;
27         ans.nume=this.nume+f.nume;
28         return reduction(ans);
29     }
30 
31     public String substract(Fraction f)
32     {
33         Fraction ans=new Fraction();
34         ans.deno=this.deno*f.deno/gcd(this.deno,f.deno);//通分
35         this.nume*=ans.deno/this.deno;
36         f.nume*=ans.deno/f.deno;
37         ans.nume=this.nume-f.nume;
38         return reduction(ans);
39     }
40 
41     public String divide(Fraction f)
42     {
43         Fraction ans=new Fraction();
44         ans.deno=this.deno*f.nume;
45         ans.nume=this.nume*f.deno;
46         return reduction(ans);
47     }
48 
49     public String multiply(Fraction f)
50     {
51         Fraction ans=new Fraction();
52         ans.deno=this.deno*f.deno;
53         ans.nume=this.nume*f.nume;
54         return reduction(ans);
55     }
56 
57     static String reduction(Fraction f)//约分
58     {
59         int div=gcd(f.deno,f.nume);
60         f.deno/=div;
61         f.nume/=div;
62         if(f.deno==1)
63             return ""+f.nume;
64         else if(f.nume==0)
65             return "0";
66         else return f.nume+"/"+f.deno;
67     }
68 
69     static int gcd( int x , int y){//最大公约数
70         if( y == 0 )
71             return x;
72         else
73             return gcd(y,x%y);
74     }
75 }
View Code

  3.GUI

    使用自由度相对较高的FlowLayout进行布局,添加JLabel,JButton,JTextField控件。对于乘方的设置:

1 jrb1.setFont(new java.awt.Font("Dialog", 1, 15));
2         jrb2.setFont(new java.awt.Font("Dialog", 1, 15));
3         ButtonGroup bg = new ButtonGroup();
4         bg.add(jrb1);
5         bg.add(jrb2);
6         jrb1.setSelected(true);

  4.倒计时

    使用Thread.sleap(1000)计时,若不提交答案时间结束则重置时间,减少生命,并重置算式。

 1    while (time >= 0) {
 2             jltime.setText( "" + time );
 3             try {
 4                 Thread.sleep(1000);
 5             } catch (InterruptedException e) {
 6                 e.printStackTrace();
 7             }
 8             time--;
 9             if(time==-1) {
10                 time=20;
11                 life--;
12                 jllife.setText("生命"+life);
13                 jltime.setText("时间"+time);
14                 Create c= new Create(power_form);
15                 jlformula.setText(c.formula);
16 
17             }
18         }

  5.历史记录

    新建一个score.txt文件,每次得分为0时FileWriter.writer会在文件末尾写入时间和得分,并弹窗显示最新的十条记录。

 1    try {
 2                                 Calendar c = Calendar.getInstance();
 3                                 FileWriter writer = new FileWriter(scorefile, true);
 4                                 writer.write(c.get(Calendar.MONTH)+1+"月"+c.get(Calendar.DAY_OF_MONTH)+"日"
 5                                                 +c.get(Calendar.HOUR_OF_DAY)+"时"+c.get(Calendar.MINUTE)+"分" +
 6                                                  "  得分:  "+score+"\n");
 7                                 writer.close();
 8                             } catch (IOException e1) {
 9                                 e1.printStackTrace();
10                             }
11                             try {
12                                 time=-2;
13                                 showscores();
14                                 end();
15                             } catch (IOException e1) {
16                                 e1.printStackTrace();
17                             }
 1     public void showscores() throws IOException {
 2         BufferedReader bfr = new BufferedReader(new FileReader(scorefile));
 3         String score[]= new String[1000];
 4         String s,ans="";
 5         int pos=0;
 6         while ((s=bfr.readLine())!=null){
 7             score[pos++]=s;
 8         }
 9         for(i=pos-10;i<pos;i++)
10             if(i>=0){
11             ans+=score[i]+"\n";
12             }
13         JOptionPane.showMessageDialog(null, ans, "历史记录", JOptionPane.INFORMATION_MESSAGE);
14 
15     }
16 
17     public void end(){
18         System.exit(0);
19     }

三、总结

  首先从知识方面,熟悉了java的GUI,对文件的操作,加深了类的认识,更了解了一些此前完全没有接触过的类和方法。

  从项目经验来说,结对项目就存在着交互。项目一共四个类,Fraction和Calculator是我写的,Create是队友写的,Fraction只在Calculator中调用,都没有什么大问题。而MainJF是不断在两个人之间交替,我写完GUI计时计算,队友接着写生成,生成之后两人一起研究历史记录,历史记录有涉及到之前的计时,就会难免杂乱。不过也是由于其他事情比较多没有在一段时间内专心做这一项,没能顺畅地走下一套流程。不过这也是很难得的一次经历了。

猜你喜欢

转载自www.cnblogs.com/emmm666/p/9105069.html