やっとできた!!
一、预估与实际
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
• Estimate | • 估计这个任务需要多少时间 | 600 | 805 |
Development | 开发 | 300 | 450 |
• Analysis | • 需求分析 (包括学习新技术) | 30 | 40 |
• Design Spec | • 生成设计文档 | 20 | 20 |
• Design Review | • 设计复审 | 20 | 10 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 10 | 15 |
• Design | • 具体设计 | 40 | 50 |
• Coding | • 具体编码 | 60 | 90 |
• Code Review | • 代码复审 | 30 | 40 |
• Test | • 测试(自我测试,修改代码,提交修改) | 40 | 50 |
Reporting | 报告 | ||
• Test Repor | • 测试报告 | 20 | 20 |
• Size Measurement | • 计算工作量 | 10 | 10 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 20 | 10 |
合计 | 805 |
二、需求分析
我通过百度文库、百度优课堂的方式了解到,小学一年级数学有如下的几个特点:
- 特点1:教学重点为10以内的加减法
- 特点2:20以内的进位加法
- 特点3:20以内的退位减法
- 特点4:不涉及负数
- 特点5:做题速度每分钟在6-10个
经过分析,我认为,这个程序应当:
- 使用的数字小于20
- 减法时大数减小数
- 题量一次最多100道题
三、设计
1. 设计思路
说明你如何设计这个程序
比如:
这个程序有1个类,6个函数,从主函数中用while循环调用checkNum()方法,checkNum()方法又调用input进行传参。循环true之后,即输入的数据为符合条件的整型,而后调用mathGrade()函数,传入n,grade两个参数进行出题并输出至output.txt文件中,其中还涉及文件的创建及I/O流。
算法的关键的关键是什么?
通过定义运算符字符数组常量static char[] symb = new char[] {'+','-','*','/'};
,通过随机数控制随机出加法减法乘法除法的计算题。 通过数组来存储随机数 字符串如何转为整型
2. 实现方案
写出具体实现的步骤
比如:
- 准备工作:先在Github上创建自己的仓库learngit,安装下载Github Desktop
- 技术关键点:
- 如何通过String[] args数组进行输入
- 字符串与整型的转换
- 如何判断是不是整型
- try{} catch{}
- 如何排除减法的负数
- 如何输出到output.txt
- 设置日期样式
- 一二年级区分的实现
- 除法的除数不为0
- 除不尽时显示商和余数
- ...
四、编码
请说明你如何按照设计思路进行编码,并记录你在开发中遇到的问题,与解决过程
1. 调试日志
记录编码调试的日志,请记录下开发过程中的 debug 历程
比如:在通过命令行运行
javac MathExam6242.javaJava MathExam6242 20 2
时经常出现:错误: 找不到或无法加载主类 MathExam6242
- 在代码的什么位置,代码出现了什么问题,问题会导致什么结果,怎么解决的 出现过
Java MathExam6242 a 1
或
Java MathExam6242 1 a
时程序会运行一半。
是由于刚开始设计时在checkNum()中有着这样的漏洞if(grade == 1 || grade == 2){ return true;}
经过
2. 关键代码
public static void mathGrade(int n,int grade) {//出题方法 int fristNum,secondNum,t; Random ra = new Random(); for (int i=0;i<2*n;i++) { c[i]=symb[ra.nextInt(2*grade)]; //一次性获取所有题目的随机运算符(+、-、*、/) }//-------------------------------------------创建IO流 FileWriter fw = null; try { String address = "output.txt"; File file = new File(address); fw = new FileWriter(file,true); } catch(IOException e){ e.printStackTrace(); } PrintWriter pw =new PrintWriter(fw); // --------------------------------- for (int i = 0,j = 0; i< 2*n;i = i + 2, j++) { switch(c[j]) { case'+': fristNum = ra.nextInt(21); a[i] = fristNum; secondNum = ra.nextInt(21); a[i+1] = secondNum; result[j] = a[i] + a[i+1]; System.out.println("("+(j+1)+") "+a[i]+" "+c[j]+" "+a[i+1]+" ="); pw.println("("+(j+1)+") "+a[i]+" "+c[j]+" "+a[i+1]+" ="); //输出到output.txt pw.flush(); break; case'-': fristNum = ra.nextInt(21); a[i] = fristNum; secondNum = ra.nextInt(21); a[i+1] = secondNum; if (a[i] < a[i+1]) { t = a[i];a[i] = a[i+1];a[i+1] = t; } result[j] = a[i] - a[i+1]; System.out.println("("+(j+1)+") "+a[i]+" "+c[j]+" "+a[i+1]+" ="); pw.println("("+(j+1)+") "+a[i]+" "+c[j]+" "+a[i+1]+" ="); //输出到output.txt pw.flush(); break; case'*': fristNum = ra.nextInt(11); a[i] = fristNum; secondNum = ra.nextInt(11); a[i+1] = secondNum; result[j] = a[i] * a[i+1]; System.out.println("("+(j+1)+") "+a[i]+" "+c[j]+" "+a[i+1]+" ="); pw.println("("+(j+1)+") "+a[i]+" "+c[j]+" "+a[i+1]+" ="); //输出到output.txt pw.flush(); break; case'/': fristNum = ra.nextInt(11); a[i] = fristNum; secondNum = ra.nextInt(11); while(secondNum == 0) { secondNum = ra.nextInt(11); } a[i+1] = secondNum; result[j] = a[i] / a[i+1]; System.out.println("("+(j+1)+") "+a[i]+" "+c[j]+" "+a[i+1]+" ="); pw.println("("+(j+1)+") "+a[i]+" "+c[j]+" "+a[i+1]+" ="); //输出到output.txt pw.flush(); break; } } System.out.println("-----------------标准答案--------------------"); pw.println("-----------------标准答案--------------------"); //输出到output.txt pw.flush(); for(int i = 0,j = 0;i < 2*n; i = i + 2, j++) { if(c[j]=='/') { if(a[i]%a[i+1]!=0) { System.out.println("("+(j+1)+") "+a[i]+" "+c[j]+" "+a[i+1]+" = " + result[j]+"..."+(a[i]%a[i+1])); pw.println("("+(j+1)+") "+a[i]+" "+c[j]+" "+a[i+1]+" = " + result[j]+"..."+(a[i]%a[i+1])); //输出到output.txt pw.flush(); continue; } } System.out.println("("+(j+1)+") "+a[i]+" "+c[j]+" "+a[i+1]+" = " + result[j]); pw.println("("+(j+1)+") "+a[i]+" "+c[j]+" "+a[i+1]+" = " + result[j]); //输出到output.txt pw.flush(); } System.out.println(" 211406242 杨长元 "+getTime()); //输出到屏幕 pw.println(" 211406242 杨长元 "+getTime()); //输出到output.txt pw.flush(); try { fw.flush(); pw.close(); fw.close(); } catch(IOException e) { e.printStackTrace(); }}
3. 代码规范
请给出本次实验使用的代码规范:
- 第一条:代码中的命名均不能以下划线或美元符号开始,也不能一下划线或美元符号结束
- 第二条:方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵循驼峰形式。
- 第三条:左小括号和字符之间不出现空格;同样的,有小括号和字符之间也不出现空格。详见第5条下面正例提示。
- 第四条:if/for/while/switch/do等保留字与括号之间都必须加空格。
- 第五条:类型与中括号紧挨相连来定义数组。
- 第六条:包名统一是用小写,点分隔符之间有且仅有一个自然语义的英语单词。
- 第七条:大括号的使用约定。如果是大括号内为空,则简介地写成{}即可,不需要换行;如果是非空代码块则:
- 左大括号前不换行。
- 左大括号后换行。
- 右大括号前换行。
- 右大括号后还有 else 等代码则不换行;
- 表示终止的右大括号后必须换行。
- 第八条:采用4个空格缩进
并人工检查代码是否符合规范
五、测试
//测试命令 //预期结果 //实际情况Java MathExam6242 a //题数错误提示 //符合预期Java MathExam6242 a 1 //题数错误提示 //程序运行一半后异常,由于检查年级时 return true 所致Java MathExam6242 a b //题数错误提示 //符合预期Java MathExam6242 010 3 //年级错误提示 //符合预期Java MathExam6242 -1 2 //题数错误提示 //符合预期Java MathExam6242 2 -2 //班级错误提示 //符合预期Java MathExam6242 0 2 //题数错误提示 //符合预期Java MathExam6242 -0 2 //题数错误提示 //符合预期Java MathExam6242 10 2 //程序正常运行 //符合预期
六、总结
对于这种需求开发,第一次上手,还是保留着之前输出结果对就ok的思想。第一次上传V1.0的代码完全没有考虑需求,题量小于1000,100以内的加减法,出现负数。这是对软件使用者的不负责任。在进行V2.0的开发的时候,仔细查询了一二年级的特点,加减法在20以内,不出现负数。乘除法在10以内。针对一二年级学生的注意力和学习效率,计算题量在100内,作业时间约10分钟。针对以上特点,进行了二次开发。针对开发中出现的问题、测试中出现的问题也进行了思考。栋哥说的有道理,第一眼好难啊不会写,但不能有这样不写了,完成任务的想法。不然是不会体验到小小成功的喜悦(感觉代码写的不是很好)能做到,就会想去做的更好!