201571030106/201571030116《小学四则运算练习软件》结对项目报告
使用JAVA编程语言,采用结对编程方式实现四则运算出题小程序,软件基本功能要求如下:
- 由计算机从题库文件中随机选择20道加减乘除混合算式,用户输入算式答案,程序检查答案是否正确,每道题正确计5分,错误不计分,20道题测试结束后给出测试总分
- 题库文件可采用实验二的方式自动生成,也可以手工编辑生成
- 程序为用户提供三种进阶四则运算练习功能选择:百以内整数算式(必做)、带括号算式、真分数算式练习
- 程序允许用户进行多轮测试,提供用户多轮测试分数柱状图
- 程序记录用户答题结果,当程序退出再启动的时候,可为用户显示最后一次测试的结果,并询问用户可否进行新一轮的测试
- 测试有计时功能,测试时动态显示用户开始答题后的消耗时间
- 程序人机交互界面是GUI界面(WEB页面、APP页面都可),界面支持中文简体(必做)/中文繁体/英语,用户可以进行语种选择
我的队友:
Github项目地址:
需求分析:
- 程序人机交互界面是GUI界面,界面支持中文简体
- 程序能够随机从题库选择试题,由用户输入答案,自动检查对错,统计成绩
- 题库文件可基于实验二生成,也可自定义题库文件
- 用户可以选择三种四则运算模式:百以内整数算式(结果非负,必须整数),带括号运算,真分数算式练习
- 系统允许用户进行多轮测试,并实现用户测试测试分数的数据可视化(柱状图)
- 测试时提供计时功能
功能设计:
- 采用java Swing编程实现人机交互界面的设计
- 编写运算式生成类
- 编写运算式计算类
- 编写真分数运算类
- 编写文件操作读写类
- 编写数据可视化实现类
设计实现:
类图:
- 运算式的生成基于实验二,改进完成带括号的运算,真分数运算。使得主程序通过参数的不同来调用不同的方法生成不同的题库
- 成绩的存储采用文件的写操作,将每次测试结果以追加的方式写入txt文件,保证不覆盖以前的成绩
- 柱状图的绘制采用jFreeChart图表绘制类库实现,查看成绩时通过读取保存成绩txt文件的最后五行实现最近五次成绩的柱状显示
- 文件操作类的功能应包括,按行写入文件,按行通过追加的方式写入文件,按行读取文件,按行读取文件的最后四行内容
- 普通运算式计算类的功能包括,中缀表达式转后缀,计算后缀表达式
- 分数运算式计算类的功能包括,分数的通分,分数的加操作,分数的减操作,分数的乘操作,分数的除操作
测试运行:
核心代码:
随机产生num个真分数运算式,计算结果,使得结果非负,并存入题库文件
/**
* 生成具有真分数运算式数的非负运算式
* @param num
*/
public void generateExpressionC(int num){
char[] operator=new char[]{'+','-'};
ArrayList<String> expression=new ArrayList<String>();
for(int i=0;i<num;i++){
int n=random.nextInt(3)+2; //3-5个运算符
ProperFraction[] proList=new ProperFraction[n+1];
for(int j=0;j<=n;j++){
proList[j]=new ProperFraction();
}
char[] symbol=new char[n];
String ex=new String();
for(int j=0;j<n;j++){
char sm=operator[random.nextInt(2)];
ex+=proList[j].toString()+sm;
proList[0]=proper.calProperFraction(proList[j], proList[j+1],sm);
}
ex+=proList[n]+"="+proList[0].toString();
if(proList[0].getNuma()/proList[0].getNumb()<0){
i--;
}
else{
expression.add(ex);
}
}
doFile.WriteToFile("ArithmeticExpression.txt",expression);
}
读取文件最后N行
public ArrayList<String> readLastNLine(String path, long numRead)
{
File file=new File(path);
ArrayList<String> result = new ArrayList<String>();
long count = 0;
if (!file.exists() || file.isDirectory() || !file.canRead()){
return null;
}
RandomAccessFile fileRead = null;
try{
fileRead = new RandomAccessFile(file, "r");
long length = fileRead.length();
if (length == 0L){
return result;
}
else{
long pos = length - 1;
while (pos > 0){
pos--;
fileRead.seek(pos);
if (fileRead.readByte() == '\n'){
String line = fileRead.readLine();
result.add(line);
count++;
if (count == numRead){
break;
}
}
}
if (pos == 0){
fileRead.seek(0);
result.add(fileRead.readLine());
}
}
}
catch (IOException e){
e.printStackTrace();
}
finally{
if (fileRead != null){
try{
fileRead.close();
}
catch (Exception e){
}
}
}
return result;
}
通过标准答案和测试结果,计算正确的题数
/**
* 通过标准答案和测试结果,计算正确的题数
* @param resHm
* @param ansHm
* @return
*/
private static int critical(HashMap<Integer, String> resHm,HashMap<Integer, String> ansHm){
int count=0;
for(Map.Entry<Integer, String> resentry:resHm.entrySet()){
String resvalue = resentry.getValue() == null?"":resentry.getValue();
String ansvalue = ansHm.get(resentry.getKey())==null?"":ansHm.get(resentry.getKey());
if(resvalue.equals(ansvalue)){
count++;
}
}
return count;
}
总结:
本程序的主要难点在于生成不同类型的运算式用以满足用户需求,基本上是实验二的拓展部分,即对于真分数四则运算的设计实现
PSP:
PSP | 任务内容 | 计划完成需要的时间(min) | 实际完成需要的时间(min) |
---|---|---|---|
计划 | 50 | 50 | |
Estimate | 需求分析,函数实现 | 50 | 50 |
开发 | 100 | 100 | |
Analysis | 需求分析 | 5 | 10 |
Design Spec | 设计 | 30 | 30 |
Design Review | 设计复审 | 30 | 30 |
Design | 具体设计 | 30 | 30 |
Coding | 具体编码 | 30 | 30 |
Code Review | 代码复审,查找语法错误 | 2 | 2 |
Test | 测试 | 5 | 5 |
报告 | 30 | 30 | |
Test Report | 经测试,程序符合实验要求,但严重脱离实际应用 | 20 | 20 |
Size Measurement | 主要工作量应该在GUI编程这块 | 20 | 20 |
Postmortem | 此程序,确确实实的花了不少时间在Swing编程这块,也是由于第二个程序完成的太过仓促,在计算,生成,扩展功能这块完全重写了之前的。对于java的GUI界面编程到此为止吧,以后不会改进这个没有多大用处的程序 | 20 | 20 |
对合作者的评价:
- 和李玉莹同学的合作过程是非常愉快的过程,算是互相学习吧,她耐心,踏实。在编程的过程中发现了好几处不容易发现的错误,及早地将程序中的BUG扼杀在了摇篮中!
- 当然,金无足赤,人无完人。每个人都有自己的缺点和短板。只有不断的改正,互相进步!才能提升自己!
- 通过本次项目,极大地提升了我们的团队协作意识,在代码风格,注释习惯这方面以后会慢慢改进!
团队协作的重要性
- 团队协作的效果是不言而喻的,雷锋也说:一滴水只有放进大海里才永远不会干涸,一个人只有当他把自己和集体事业融合在一起的时候才能最有力量。
最后,重要的事情,愉快的经历记录如下