队友使用的是Java语言,主要是分成查重函数和主函数,下面进行部分解析
首先是查重函数,history保存当前文件夹下所有.txt文件中的算式,并且每次生成新题目时都进行添加并且差重,妥善处理异常的两个try函数
private static List<String> history; private static boolean writeFile(StringBuilder tmp, String time, int index) { String path = time + ".txt"; BufferedWriter bufferedWriter = null; if (history.contains(tmp.toString())) { System.out.println("发现重复题目!"); return false; // fail to write } try { history.add(tmp.toString()); bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path, true), "UTF-8")); bufferedWriter.write(String.valueOf(index) + ". "); bufferedWriter.write(tmp.toString()); bufferedWriter.write("\r\n"); bufferedWriter.write("\r\n"); bufferedWriter.flush(); } catch (Exception e) { e.printStackTrace(); } finally { if (bufferedWriter != null) { try { bufferedWriter.close(); } catch (Exception e) { e.printStackTrace(); } } } return true; // succeeded
然后是插入括号的操作,每次生成操作数以及操作符时同时记录可以插入括号的位置,再随机对括号进行插入,是值得我学习的地方
还有就是对操作符与括号的位置进行了操作,避免算式过于单一
if (pos1 != 0 && tmp.charAt(pos1 - 1) == '(') { // possibly change (√ into √( pos1 -= random.nextInt(2); } if (random.nextBoolean()) { tmp.insert(pos1, '√'); flag = true; } int pos2 = valueRightPos.get(random.nextInt(itemNum)); if (pos2 >= pos1 && flag) { pos2++; } if (pos2 < tmp.length() && tmp.charAt(pos2) == ')') { // possibly change ²) into )² pos2 += random.nextInt(2); } if (!flag || random.nextBoolean()) { tmp.insert(pos2, '²'); }
这里对根号和平方与括号的相对位置进行了考虑,使得算式更加多样,也更加贴近现实需求
但还有一些不足的地方,没有面向对象编程,代码重用性差
switch (category) { case "小学": for (int i = 0; i < num; i++) { StringBuilder tmp = new StringBuilder(); int itemNum = random.nextInt(4) + 2; // 2 ~ 5 List<Integer> valueLeftPos = new LinkedList<>(); List<Integer> valueRightPos = new LinkedList<>(); for (int j = 0; j < itemNum; j++) { if (j == 0) { valueLeftPos.add(tmp.length()); tmp.append(String.valueOf(random.nextInt(100) + 1)); valueRightPos.add(tmp.length()); } else { tmp.append(op[random.nextInt(4)]); valueLeftPos.add(tmp.length()); tmp.append(String.valueOf(random.nextInt(100) + 1)); valueRightPos.add(tmp.length()); } } int leftBracketPos = -1, rightBracketPos = -1; if (itemNum > 2) { int leftPosIndex = random.nextInt(itemNum - 1); // leftPosIndex ∈ [0, itemNum - 1) int rightPosIndex = random.nextInt(itemNum - leftPosIndex - 1) + leftPosIndex + 1; // rightPosIndex ∈ [leftPosIndex + 1, itemNum) leftBracketPos = valueLeftPos.get(leftPosIndex); rightBracketPos = valueRightPos.get(rightPosIndex); if (leftBracketPos != 0 || rightBracketPos != tmp.length()) { // avoid meaningless brackets tmp.insert(leftBracketPos, '('); rightBracketPos++; // because last insertion changed the indexes tmp.insert(rightBracketPos, ')'); } }
这一部分在主函数中出现多次,进行封装放入函数中会好很多,代码也不会显得冗长
然后是括号的插入,只解决了一对括号的插入情况,可以进行改进