本篇博客根据软件工程项目创新课程设计的个人项目要求,对黄泽云同学的项目代码进行分析评价。
一、整体评价
-
结构上,该项目代码由两个文件组成。分别是Paper.java和PaperCreate.java。其中,PaperCreate.java定义了用户类和功能性方法,Paper.java定义了主类。
-
功能上,经过测试,可以满足个人项目中所有的需求。
-
编码规范上,采用IDE中自带的编码格式,编码规范。
二、细节分析
项目实现的难点在于出题的随机性、合法性和无重复性。下面具体就产生题目的函数进行分析评价。
-
该同学采用Random实现随机性。并且分两步完成一道题目的生成。首先是生成由操作数和操作符组合成的字符串。
int i = 0;
if (grade.equals("小学")) i = rand.nextInt(4) + 2;
if (grade.equals("初中") || grade.equals("高中")) i = rand.nextInt(5) + 1;
String[] q = new String[2 * i - 1];
for (int j = 0; j < 2 * i - 1; j++) {
q[j] = "";
}
int ss = 1;
for (int j = 0; j < 2 * i - 1; j += 2) {
if (grade.equals("小学")) q[j] = String.valueOf((rand.nextInt(100) + 1));
if (grade.equals("初中")) {
int s = rand.nextInt(3);
if (s == 0) {
q[j] = String.valueOf((rand.nextInt(100) + 1));
} else if (s == 1) {
q[j] = ("√" + (rand.nextInt(100) + 1));
ss = 0;
} else {
q[j] = ((rand.nextInt(100) + 1) + "^2");
ss = 0;
}
}
if (grade.equals("高中")) {
int s = rand.nextInt(6);
if (s == 0) {
q[j] = String.valueOf((rand.nextInt(100) + 1));
} else if (s == 1) {
q[j] = ("√" + (rand.nextInt(100) + 1));
} else if (s == 2) {
q[j] = ((rand.nextInt(100) + 1) + "^2");
} else if (s == 3) {
q[j] = ("sin" + (rand.nextInt(100) + 1));
ss = 0;
} else if (s == 4) {
q[j] = ("cos" + (rand.nextInt(100) + 1));
ss = 0;
} else {
q[j] = ("tan" + (rand.nextInt(100) + 1));
ss = 0;
}
}
if (j == 2 * i - 2) {
if (ss == 1) {
if (grade.equals("初中")) {
q[j] = "√" + q[j];
}
if (grade.equals("高中")) {
q[j] = "cos" + q[j];
}
}
break;
}
}
for (int j = 1; j < 2 * i - 1; j += 2) {
int s = rand.nextInt(4);
if (s == 0) {
q[j] = "+";
} else if (s == 1) {
q[j] = "-";
} else if (s == 2) {
q[j] = "*";
} else {
q[j] = "/";
}
}
-
第二步考虑括号的位置,采用枚举法,先枚举出所有可能的位置写进数组,再从中随机出合法的组合。
for (int j = 1; j < 2 * i - 1; j += 2) {
int s = rand.nextInt(4);
if (s == 0) {
q[j] = "+";
} else if (s == 1) {
q[j] = "-";
} else if (s == 2) {
q[j] = "*";
} else {
q[j] = "/";
}
}
if (i == 1) {
question = q[0];
}
if (i == 2) {
question = q[0] + q[1] + q[2];
}
if (i == 3) {
if (rand.nextInt(2) == 0) {
int r = rand.nextInt(2);
q[n[r][0]] = "(" + q[n[r][0]];
q[n[r][1]] = q[n[r][1]] + ")";
}
question = q[0] + q[1] + q[2] + q[3] + q[4];
}
if (i == 4) {
int brackets = rand.nextInt(3);
if (brackets == 1) {
int r1 = rand.nextInt(5);
q[n[r1][0]] = "(" + q[n[r1][0]];
q[n[r1][1]] = q[n[r1][1]] + ")";
} else if (brackets == 2) {
int r1 = rand.nextInt(5);
q[n[r1][0]] = "(" + q[n[r1][0]];
q[n[r1][1]] = q[n[r1][1]] + ")";
int r2;
while (true) {
r2 = rand.nextInt(5);
if (r2 != r1) {
if (n[r1][0] != n[r2][1] && n[r1][1] != n[r2][0]) {
break;
}
}
}
q[n[r2][0]] = "(" + q[n[r2][0]];
q[n[r2][1]] = q[n[r2][1]] + ")";
}
-
合法性主要由if判断实现且主要体现在括号的选择上,由上面选取括号的代码可以分析出选择的逻辑,这里不再赘述。
-
无重复性通过check函数实现,且该同学采用了一种特殊的方法——哈希码。计算得到每道生成的题的哈希码后再存入txt文件,比对时只需要比对哈希码的异同就行,降低了查重时的空间代价和时间代价。但是牺牲了生成题目时的时间消耗(需要进行额外的哈希码计算)
for (int i = 1; i <= num; i++) {
String Q1 = question();
String H = String.valueOf(Q1.hashCode());
String Q2 = i + ". " + Q1 + "\n\n";
while (!check(H)) {
Q1 = question();
H = String.valueOf(Q1.hashCode());
Q2 = i + ". " + Q1 + "\n\n";
}
三、优缺点评价
优点:该同学代码书写规范,能够较好的将代码模块化,提高了代码的重用性和可维护性。并且运用算法的知识,通过哈希码来实现查重,比较有新意。
缺点:在临时变量的命名上不太合理,没有采用易于理解的命名而是一些单个的字母,给代码的阅读带来了一定的困难,希望下次能进行改善。