湖南大学结对编程之个人项目互评
作者:互联网
本篇博客为对结对编程搭档邹同学的个人项目(中小学数学卷子自动生成程序)的评价。该代码使用语言为Java,与我的个人项目语言一致,本次评价旨在总结反省,共同进步。
此次评价主要基于三个方面:
一、代码结构
mathpaper包:
-
Create类主要用来出题
-
User类用来对用户类型定义
-
Begin类包括对输出页面的一系列操作,对用户的输入类型做判断
-
Database类主要用来对保存并判断用户信息。
-
调用Main类来运行整个项目
结构较为清晰。在组织类的结构时充分考虑面向对象的特点进行书写。
二、功能完成
-
登录功能
-
退出功能
-
生成试卷功能
-
切换功能
操作均在操作台实现,我们去看一下生成的文件:
基本功能验证完毕!均已实现。
三、代码分析
1. User类:
未使用到定义的setName、setPassword、setType函数。
2. Database类
逻辑简单,便于理解。经检验,功能正常;
但可复用性不高,当且仅当账户信息不变时使用正常,如需修改账户信息,则代码结构也必须随之发生变化;
3. Create类
(1)createProblem函数
点击查看代码
public static String createProblem(String type) throws IOException{
String[] signs={"+","-","*","/","²","√","sin","cos","tan"};
Random random=new Random();
String prob=""; //题目,目前还是空的
int opNumber=random.nextInt(5)+1; //操作数数量1~5
if(type.equals("小学")) {
opNumber= random.nextInt(4)+2; //小学2~5
}
int[] operand1=new int[opNumber];
String[] oprand=new String[opNumber];
int[] flag=new int[opNumber]; //标记是否成为了特殊数
for(int i=0;i<opNumber;i++){ //给数赋值
operand1[i]=random.nextInt(100)+1; //取值范围1~100
oprand[i]=String.valueOf(operand1[i]); //将数变为字符串类型
flag[i]=0; //如果这个数字有改动,会被标记
}
if(type.equals("小学")){
String[] opsign=new String[opNumber-1]; //小学题目的符号比数字少一个
int[] index=new int[opNumber-1];
for(int i=0;i<opNumber-1;i++) {
index[i]=random.nextInt(4);
opsign[i]=signs[index[i]];
}
prob=Add(opNumber,opsign,oprand);
}
else if(type.equals("初中")){
int a= random.nextInt(opNumber)+1; //有a个被平方或开根号了
//处理a个特殊的数
for(int i=0;i<a;i++) {
int signIndex= random.nextInt(2)+4; //选择操作符下表4或5,平方或开根号
int changeIndex=0; //改变的数字下标
while(true){
changeIndex=random.nextInt(opNumber); //选择要改变的数字的下标
if(flag[changeIndex]==0) {
flag[changeIndex]++;
break;
}
}
if(signIndex==4){ //平方
oprand[changeIndex]=oprand[changeIndex]+"²";
} else if(signIndex==5){ //开根号
oprand[changeIndex]="√"+oprand[changeIndex];
}
}
//加上+-*/运算符
String[] opsign=new String[opNumber-1]; //初中题目的符号比数字少一个
int[] index=new int[opNumber-1];
for(int i=0;i<opNumber-1;i++) {
index[i]=random.nextInt(4);
opsign[i]=signs[index[i]];
}
prob=Add(opNumber,opsign,oprand);
}
else if(type.equals("高中")){
//处理b个sin,cos,tan
int b=random.nextInt(opNumber)+1; //有b个数是有sin,cos,tan,至少有一个
for(int i=0;i<b;i++) {
int signIndex = random.nextInt(3) + 6; //选择操作符下表6或7或8
int changeIndex = 0; //改变的数字下标
while (true) {
changeIndex = random.nextInt(opNumber); //选择要改变的数字的下标
if (flag[changeIndex] == 0) {
flag[changeIndex]++;
break;
}
}
oprand[changeIndex] = signs[signIndex] + oprand[changeIndex];
}
//如果还有的数未被sin,cos,tan标记,可以加上平方或开根号
if(b<opNumber) {
int a = random.nextInt(opNumber - b);
for (int i = 0; i < a; i++) {
int signIndex2 = random.nextInt(2) + 4; //选择操作符下表4或5,平方或开根号
int changeIndex2 = 0; //改变的数字下标
while (true) {
changeIndex2 = random.nextInt(opNumber); //选择要改变的数字的下标
if (flag[changeIndex2] == 0) {
flag[changeIndex2]++;
break;
}
}
if (signIndex2 == 4) { //平方
oprand[changeIndex2] = oprand[changeIndex2] + "²";
} else if (signIndex2 == 5) { //开根号
oprand[changeIndex2] = "√" + oprand[changeIndex2];
}
}
}
//加上+-*/运算符
String[] opsign=new String[opNumber-1]; //初中题目的符号比数字少一个
int[] index=new int[opNumber-1];
for(int i=0;i<opNumber-1;i++) {
index[i]=random.nextInt(4);
opsign[i]=signs[index[i]];
}
prob=Add(opNumber,opsign,oprand);
}
return prob;
}
程序逻辑是小学、初中、高中各自用一个函数去写,里面不但复用的代码很多,而且如果有别的运算符比如大学难度,也要重新写一个大学的......扩展与修改难度大,其实仔细阅读后小学、初中、 高中,三者区别不大,一个判断语句足以......函数的作用更多应该是去实现一个独立的功能,而不是将程序部分代码变成一个函数。
(2)Add函数
点击查看代码
public static String Add(int opNumber,String[] opsign,String[] oprand){
String prob="";
Random random=new Random();
if(random.nextBoolean()&&opNumber>2){ //加括号
//Left
int leftBracket= random.nextInt(opNumber-1);
//Right
int rightBracket=random.nextInt(opNumber-leftBracket-1)+leftBracket+1;
if(leftBracket==0&&rightBracket==opNumber-1){
rightBracket--;
}
for(int i=0;i<opNumber-1;i++){
if(i==leftBracket){
prob=prob+"("+oprand[i]+opsign[i];
} else if(i==rightBracket) {
prob=prob+oprand[i]+")"+opsign[i];
} else {
prob=prob+oprand[i]+opsign[i];
}
}
if(rightBracket==opNumber-1){
prob=prob+oprand[opNumber-1]+")";
} else{
prob=prob+oprand[opNumber-1];
}
}
else{ //不加括号
for(int i=0;i<opNumber-1;i++){
prob=prob+oprand[i]+opsign[i];
}
prob=prob+oprand[opNumber-1];
}
return prob;
}
将括号设置这一函数单独设置,增加代码的复用性,让结构更加明朗
在处理表达式时可以增加一些功能:除号右边不能为0,括号可不可以设置不止一对。
(3)checkRepeat函数
点击查看代码
public static boolean checkRepeat(String name,String problem) throws IOException{
File filePaper=new File("math_problems\\"+name);
File[] paperList=filePaper.listFiles(); //获取指定目录下的所有文件或者文件目录的File对象数组
int len=paperList.length;
InputStream fileRead; //字节输入流,将文件中的数据读取到java中
for(int i=0;i<len;i++) {
fileRead=new FileInputStream(paperList[i]);
byte[] problems=new byte[2048];
fileRead.read(problems); //获取当前试卷文件的所有题目,输入流会把读取到的内容放入到这个字节数组中
String content=new String(problems,"utf-8");
if(content.indexOf(problem)!=-1) { //看看字符串content中有无problem这个字符串,没有返回-1
return true;
}
fileRead.close();
}
return false;
}
查重算法简单易懂。能有效实现查重
查重算法采用直接循环遍历,在题目大量出现的情况下,查重效率低
(4)获取文件路径
题目要求将对应的试题存在账号的文件夹内,并且对于相应的地址位置,大部分同学都是单纯的提前设置好在自己电脑的文件夹,若是在别人的电脑就得重新修改代码,而队友则是采用了getAbsolutePath()获取绝对路径的方式,动态的去创建文件,灵活高效。
四、代码规范
代码规范比较好,缩进,空格,包括在文件前面的包头声明都是非常明确且清晰的,可读性高,并且类、类函数等都做了充分的注解,让我看着并不会很吃力,命名比较规范,能够清楚得知道每个变量和函数具体在起什么作用。
总结:
邹同学的代码有很多值得我学习的地方,以上列出的优点只是可以看出来的结构,其中蕴含的思想需要我之后多多学习。在此次个人项目中再一次熟悉了Java语言,对之后的项目开始可能大有裨益。
标签:代码,结对,String,int,opNumber,random,互评,new,湖南大学 来源: https://www.cnblogs.com/chenx11/p/chenx11.html