结对编程(-java实现)

一 、Github项目地址:https://github.com/mushan520/Four-fundamental-rules-java.git

                                 或   https://github.com/SAH2019/as

 

 

二、PSP表格:

PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning 计划 60   45
· Estimate · 估计这个任务需要多少时间 60 45
Development 开发 1260 1515
· Analysis · 需求分析  60   90  
· Design Spec · 生成设计文档 60 60
· Design Review · 设计复审  30 45
· Coding Standard · 代码规范 30 60
· Design · 具体设计 90 90
· Coding · 具体编码 900 1080
· Code Review · 代码复审 30 30
· Test · 测试(自我测试,修改代码,提交修改) 60 90
Reporting 报告 100 140
· Test Report · 测试报告 30 50
· Size Measurement · 计算工作量 30 50
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 40 40
合计   1420 1700

三:实现过程

      1.因为涉及到分数的相关运算,所以单独设计了一个分数类Fraction,里面实现了分数的加减乘除计算以及分数的显示,以供给其他的类和方法调用

    2.FormulaMaker中展示了整个项目的实现过程:1)随机生成整数或者分数-->2)随机生成四则运算的符号-->3)将生成的运算数和符号连接成算式-->4)对算式进行结果的计算-->5)分别输出结果和算式到文件中。

      3.我们所做的程序和老师的要求还有一定的差距,比如分数的表示,目前我们的程序生成的结果,都是以分数形式表示的,比如0/2  ,2/1或者是8/3这种本该用2‘2/3表示的结果,无法正确的按要求显示,这是我们技术上的不成熟导致的,很遗憾。

   4.以下的导图显示了程序的方法结构。

 

 

四:代码说明

      1.   FormulaMaker :主要的一个类:用来完成生成随机的算式,以及算式的计算,还有算式和答案的输出

       

复制代码
复制代码
  1 package creater;
  2 
  3 import java.io.File;
  4 import java.io.FileWriter;
  5 import java.io.PrintStream;
  6 import java.util.HashSet;
  7 import java.util.Random;
  8 import java.util.Stack;
  9 
 10 public class FormulaMaker {
 11     private int numRange;
 12     private int questionsNum;
 13 
 14     public FormulaMaker(int numRange, int questionsNum) {
 15         this.numRange = numRange;
 16         this.questionsNum = questionsNum;
 17         makeFormula();
 18         HashSet<String> set = makeFormulas();
 19         Fraction[] arr = getAnswers(set);
 20         outputFormula(set);
 21         outputAnswers(arr);
 22 
 23     }
 24 
 25     // 获取随机整数
 26     public int getRandomNumber() {
 27         Random rand = new Random();
 28         int RandomNum = rand.nextInt(this.numRange);
 29         if (RandomNum == 0)
 30             RandomNum = RandomNum + 1;
 31         return RandomNum;
 32     }
 33   //获取随机分数
 34     public Fraction getRandomFraction() {
 35         Fraction a = new Fraction(getRandomNumber(), getRandomNumber());
 36         return a;
 37 
 38     }
 39 
 40     // 获取随机运算符号
 41     public String getRandomSign() {
 42         Random rand = new Random();
 43         String[] operations = { "+", "-", "*", "/" };
 44         return operations[rand.nextInt(4)];
 45     }
 46 
 47     public String makeFormula() {
 48         String formula = "";
 49         for (int i = 0; i < 4; i++) {
 50             if (i >= 3) {
 51                 {
 52                     Random rand = new Random();
 53                     int a = rand.nextInt(2);
 54                     switch (a) {
 55                     case 0:
 56                         formula += this.getRandomNumber();
 57                         break;
 58                     case 1:
 59                         formula += getRandomFraction();
 60                         break;
 61                     }
 62                 }
 63                 continue;
 64             }
 65             Random rand = new Random();
 66             int a = rand.nextInt(2);
 67             switch (a) {
 68             case 0:
 69                 formula += this.getRandomNumber() + " " + this.getRandomSign() + " ";
 70                 break;
 71             case 1:
 72                 formula += this.getRandomFraction() + " " + this.getRandomSign() + " ";
 73                 break;
 74             }
 75 
 76         }
 77         return formula;
 78     }
 79 
 80     // 生成算式集合
 81     public HashSet<String> makeFormulas() {
 82         HashSet<String> set = new HashSet<String>();
 83         while (set.size() < this.questionsNum) {
 84             String formula = this.makeFormula();
 85             set.add(formula);
 86         }
 87         return set;
 88     }
 89 
 90     
 91     // 比较运算优先级
 92     public int compare(String operator1, String operator2) {
 93         int res = 0;
 94         switch (operator1) {
 95         case "+":
 96         case "-":
 97             if (operator2.equals("+") || operator2.equals("-") || operator2.equals("*") || operator2.equals("/")) {
 98                 res = 1;
 99             } else {
100                 res = -1;
101             }
102             break;
103         case "*":
104         case "/":
105             if (operator2.equals("*") || operator2.equals("/")) {
106                 res = 1;
107             } else {
108                 res = -1;
109             }
110             break;
111         }
112         return res;
113     }
114     
115     
116     // 生成算式结果
117         public Fraction getAnswer(String formula) {
118 
119             int length = 0;
120             String[] formulaArr = formula.split(" ");
121             String operators = "+-*/";
122             Stack<Fraction> opNumbers = new Stack<Fraction>();
123             Stack<String> opOperators = new Stack<String>();
124             opOperators.add("#");// 字符栈中存储个#号,防止栈空
125             while (length < formulaArr.length) {
126                 String op = formulaArr[length++];
127                 if (operators.indexOf(op) > -1) {// 若是运算符,判断优先级
128                     String sign = opOperators.peek();
129                     int priority = compare(op, sign);// 要入栈的跟栈顶的相比
130                     if (priority >= 0) {// 如果要入栈的运算符高或者相等,出栈两个数字,和之前的运算符,计算后,将数字入栈,将字符入栈
131                         opNumbers.add(compute(opOperators, opNumbers));
132                         opOperators.add(op);
133                     } else {// 入栈运算符优先级低,直接入栈
134                         opOperators.add(op);
135                     }
136                     continue;
137                 }
138                 // 若是数字,则入栈 
139                 if (op.matches("\\d+/\\d+")) {
140                     String[] strs = op.split("/"); 
141                     int fenZi = Integer.parseInt(strs[0]);
142                     int fenMu = Integer.parseInt(strs[1]);
143                     opNumbers.add(new Fraction(fenZi, fenMu));
144                 } else {
145                     int fenZi = Integer.parseInt(op);
146                     opNumbers.add(new Fraction(fenZi, 1));
147                 }
148 
149             }
150             while (opOperators.peek() != "#") {
151                 opNumbers.add(compute(opOperators, opNumbers));
152             }
153                 Fraction lastResult = null;
154                 String resultArr = opNumbers.pop()+"";
155                   if (resultArr.matches("-?\\d+/\\d+")) {
156                        String[] strs2 = resultArr.split("/"); 
157                     int lastFenZi = Integer.parseInt(strs2[0]);
158                     int lastFenMu = Integer.parseInt(strs2[1]);
159                      lastResult=changeFraction(lastFenZi,lastFenMu);
160                     
161                     }
162             return lastResult;
163             
164         }
165 
166         
167      //给分数约分        
168         public Fraction changeFraction(int a,int b) {
169                   if(a < 0) {
170                       a = -a;
171                       int min = a < b ? a : b;
172                       for (int i = min;i >= 1;i --) {
173                         if (a % i == 0 && b % i == 0) {
174                           a=a/i;
175                           b=b/i;
176                             break;
177                   }
178                   
179                    }
180                       return new Fraction(-a,b) ;
181                   }
182              
183                   int min = a < b ? a : b;
184                   for (int i = min;i >= 1;i --) {
185                     if (a % i == 0 && b % i == 0) {
186                       a=a/i;
187                       b=b/i;
188                         break;
189               }
190               
191                }
192                       return new Fraction(a,b) ;
193                   
194         }
195                 
196                 
197                 
198     // 算式求值
199     public Fraction compute(Stack<String> opOperators, Stack<Fraction> opNumbers) {
200         Fraction num2 = opNumbers.pop();
201         Fraction num1 = opNumbers.pop();
202         String _op = opOperators.pop();
203         Fraction result = null;
204         switch (_op) {
205         case "+":
206             result = num1.add(num2);
207             break;
208         case "-":
209             result = num1.sub(num2);
210             break;
211         case "*":
212             result = num1.multiply(num2);
213             break;
214         case "/":
215             result = num1.div(num2);
216             break;
217         }
218         return result;
219         }
220     
221     
222     // 生成算式结果数组
223     public Fraction[] getAnswers(HashSet<String> set) {
224         Fraction[] arr = new Fraction[set.size()];
225         int i = 0;
226         for (String str : set) {
227             arr[i++] = getAnswer(str);
228         }
229         return arr;
230     }
231 
232     // 输出算式到文件
233     public String outputFormula(HashSet<String> set) {
234         File file = new File("Exercises.txt");
235         try {
236             int b = 1;
237             PrintStream ps1 = new PrintStream(file);
238             for (String str : set) {
239 
240                 ps1.println(b + ".  " + str + "=");
241                 b++;
242             }
243             ps1.close();
244         } catch (Exception e) {
245             System.out.println("Error" + e.getMessage());
246             System.exit(0);
247         }
248         return file.getAbsolutePath();
249     }
250 
251     // 输出答案到文件
252     public String outputAnswers(Fraction[] arr) {
253         File file = new File("Answers.txt");
254         try {
255             PrintStream ps2 = new PrintStream(file);
256             for (int i = 0; i < arr.length; i++) {
257                 ps2.print(i + 1 + ". ");
258                 ps2.println(arr[i]);
259             }
260             ps2.close();
261         } catch (Exception e) {
262             System.out.println("Error" + e.getMessage());
263             System.exit(0);
264         }
265         return file.getAbsolutePath();
266     }
267 
268 }
复制代码
复制代码

 

       2.     Fraction  分数类,计算分数的加减乘除以及显示分数:

复制代码
复制代码
 1 package creater;
 2 
 3 public class Fraction {
 4 
 5     int fenzi;
 6     int fenmu;
 7 
 8     public Fraction(int fenzi, int fenmu) {
 9         if (fenmu == 0) {
10             throw new IllegalArgumentException("分母不能为0");
11         }
12         this.fenzi = fenzi;
13         this.fenmu = fenmu;
14     }
15 
16     // 分数的加法
17     public Fraction add(Fraction other) {
18         int fm = this.fenmu * other.fenmu;
19         int fz = this.fenzi * other.fenmu + other.fenzi * this.fenmu;
20         return new Fraction(fz, fm);
21     }
22 
23     // 分数的减法
24     public Fraction sub(Fraction other) {
25         int fm = this.fenmu * other.fenmu;
26         int fz = this.fenzi * other.fenmu - other.fenzi * this.fenmu;
27         return new Fraction(fz, fm);
28     }
29 
30     // 分数的乘法
31     public Fraction multiply(Fraction other) {
32         int fm = this.fenmu * other.fenmu;
33         int fz = this.fenzi * other.fenzi;
34         return new Fraction(fz, fm);
35     }
36 
37     // 分数的除法
38     public Fraction div(Fraction other) {
39 
40         int fm = this.fenmu * other.fenzi;
41         int fz = this.fenzi * other.fenmu;
42         return new Fraction(fz, fm);
43     }
44 
45     // 分数的显示
46     public String toString() {
47         
48         
49         
50         return fenzi + "/" + fenmu;
51     }
52 
53 
54 }
复制代码
复制代码
3.creater  类包含主方法,程序的开始。
复制代码
复制代码
 1 package creater;
 2 
 3 import java.util.Scanner;
 4 
 5 public class creater {
 6 
 7     public interface Fraction {
 8 
 9     }
10 
11     public static void main(String[] args) {
12         // TODO 自动生成的方法存根
13         long startTime = System.currentTimeMillis();   
14         Scanner choose = new Scanner(System.in);
15         System.out.println("************************************欢迎来到四则运算生成器******************************************");
16         System.out.println("请选择生成题目数量:");
17         int questionsNum = choose.nextInt();
18         System.out.println("请输入算术范围:");
19         int numRange = choose.nextInt();
20  
21         new FormulaMaker(numRange, questionsNum);
22         System.out.println("题目文件生成完毕!");
23         long endTime = System.currentTimeMillis();
24         System.out.println("程序运行时间:" + (endTime - startTime) + "ms");    //输出程序运行时间
25     }
26 
27 }
复制代码
复制代码

 

五:测试结果

结果一:测试结果比较小的时候(如生成20道题,算数在10以内)

控制台显示内容:

 

1.生成的算式文件--Exercises.txt

 

 

 

2.生成的答案文件--Answers.txt

 

 

 结果二:程序能支持一万道题目的生成

控制台显示内容:

 

 1.生成的算式文件--Exercises.txt

 

2.生成的答案文件--Answers.txt

 

 

 

六:项目小结

      本次的项目和上次相比有许多不同的地方,在项目完成后,做出以下结论:第一:这一次是两个人一同做一个项目,这样会比一个人单独做会简单一些。毕竟合作的作用就是1+1>2 。但是两个人合作也会有一些弊端,比如两个人的分工合作的调度是一个问题。第二:这是第二次的作业,明显的比上一次有了更多的做项目的经验,但是却发现了新的问题,就是编程知识的不足,这是项目经验弥补不了的,比如在大脑中构思好了某一个方法的流程和结构,但是总会在一些小细节上卡住,虽然说是小细节,但是影响也是巨大的。毕竟程序这种东西错了一个标点符号都是不可行的。第三:程序的方法之间会有紧密的联系,牵一发而动全身,因此后期的修改工作也是比较复杂。总而言之,提升自己的知识储备是当务之急!

 

 

项目作者:朱伟彬3117004639      商爱虎3117004626

posted @ 2019-10-16 16:37  木杉呀  阅读(175)  评论(0编辑  收藏  举报