Coding代码地址:https://git.coding.net/huyifeng1998/Week2_homework2.git
需求分析:
1、本程序为小学生四则运算练习程序
2、程序可接收一个输入参数n,然后随机产生n道加减乘除练习题
3、为了让小学生得到充分锻炼,每个数字必须在 0 到 100 之间,运算符在3个到5个之间
4、由于小学生没有分数与负数的概念,所以程序出的练习题在运算过程中不得出现负数与非整数
5、最后将学号与生成的n道练习题及其对应的正确答案输出到文件“result.txt”中
功能设计:
程序能接收一个输入参数n,然后根据题目要求随机产生n道加减乘除练习题,并将学号与生成的n道练习题及其对应的正确答案输出到文件“result.txt”中,方便查看和使用。
设计实现:
我在本次的作业中使用了一个类Main,四个方法:
main方法:用于接收输入的题目数sum,判断是否是合法输入,然后随机生成运算符数量和运算数的数量,拼接成一个字符串形式的题目,并通过for和if循环避免运算过程中出现负数。
division方法:由于运算过程中出现小数只可能由除法造成,所以使用这个方法来避免除法中出现小数,只生产整数。
calculate方法:通过使用JS中的ScriptEngine接口ScriptEngineManager类,计算之前main方法生成的题目。
write方法:将calculate方法中生成的结果存入“result.txt”。
算法详解:
题目生成:
我先使用了两个数组number和operator存放random类随机生成的运算数和运算符。运算符的数量为3到5个,所以运算数的数量为4到6个。然后为了避免运算中出现负数、小数和一系列可能出现的错误,我使用了如下代码:
if(k!=0 && (operator[k-1]=='*'||operator[k-1]=='/')) { //乘除不连续出现避免出错 OP=random.nextInt(2); operator[k]=op[OP]; }
if(operator[k]=='-'){ //消除负数 if(number[k+1]>number[k]){ if(number[k]==0) number[k]++; number[k+1]=random.nextInt(number[k]); } }
private static int division(int x,int y){ //整除函数 if(x%y!=0 && y>1){ y--; return division(x,y); } else{ return y; }
}
题目计算:
使用了JS中的ScriptEngine接口ScriptEngineManager类,该方法能直接计算之前生成的字符串形式的算术表达式,得出答案。使用JS的脚本功能需要导入如下三个包:
import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException;
测试运行:
进入src文件夹下,输入 javac Main.java 编译出相应的class文件,再输入java Main 进行测试
代码展示:
我使用了两个数组number和operator分别存放随机生成的运算数和运算符,其中运算数数量比运算符数量多一个
String result = new String(); int opnumber =random.nextInt(3)+3; //随机生成题目中的运算符数量 int[] number=new int[opnumber+1]; int[] operator=new int[opnumber]; for(int j=0;j<=opnumber;j++){ number[j]=(random.nextInt(100)+1); //随机生成题目中的运算数 }
通过调用这个递归函数,来避免运算过程中出现负数:两个数相除,如果不能整除,将除数减一,直到能整除为止
private static int division(int x,int y){ //整除函数 if(x%y!=0 && y>1){ y--; return division(x,y); } else { return y; }
}
通过使用JS中的ScriptEngine接口ScriptEngineManager类,直接计算之前生成的字符串形式的算术表达式
static ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript"); private static ArrayList<String> calculate(ArrayList<String> arrayList){ //calculate方法 ArrayList<String> calculateResult=new ArrayList<String>(); for(String p:arrayList){ try { p=p+"="+jse.eval(p); System.out.println(p); calculateResult.add(p); }
catch(ScriptException e){ e.printStackTrace(); } } return calculateResult; }
使用BufferedWriter、FileWriter,将文本写入字符输出流,在result.txt输出学号和生成的题目加答案
public static void write(String path,ArrayList<String> content){ //将题目集以文本形式输出
try { BufferedWriter bw = new BufferedWriter(new FileWriter(path)); bw.write("2016011994"); //输出学号 bw.newLine(); for(String con:content){ bw.write(con); //输出题目 bw.newLine(); } bw.close(); }
catch (IOException e1){ e1.printStackTrace(); } }
总结:
这次我很早就开始着手思考这个作业了,我花了一段时间来回顾java知识点,然后花了很长时间来构思算法。我用了四个方法实现了四个功能,分别是:接收用户输入的题目数,生成题目;避免题目解题中出现小数和负数;计算出所有题目的答案;将题目集和相应答案输出到“result.txt”文本文件中。完成了作业的基本要求。但同时我在修改我的代码时也发现了问题:我只使用了一个类。虽然每个方法分工明确,但是在代码有几百行的情况下,有时候不能准确的找到要修改的地方。所以我应该将每个方法单独的写成一个类,通过类之间的相互调用,提高代码的可读性、可移植性和可维护性。我也会在日后逐渐完善我的代码,在实践中成长。
PSP展示:
PSP2.1 |
任务内容 |
计划共完成需要的时间(min) |
实际完成需要的时间(min) |
Planning |
计划 |
30 |
20 |
· Estimate |
· 估计这个任务需要多少时间,并规划大致工作步骤 |
30 |
20 |
Development |
开发 |
1383 |
2060 |
· Analysis |
· 需求分析 (包括学习新技术) |
60 |
130 |
· Design Spec |
· 生成设计文档 |
30 |
30 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
10 |
15 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
5 |
5 |
· Design |
· 具体设计 |
20 |
15 |
· Coding |
· 具体编码 |
1200 |
1800 |
· Code Review |
· 代码复审 |
30 |
15 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
30 |
50 |
Reporting |
报告 |
60 |
110 |
· Test Report |
· 测试报告 |
30 |
60 |
· Size Measurement |
· 计算工作量 |
5 |
10 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
25 |
40 |