一. 项目简介
本次项目为设计一个中小学数学卷子的自动生成程序,本文为对我的结对编程对象lhq同学的个人项目进行评价与建议。
二.项目结构
先来看看项目的构成:
如同类名所示,各个类各司其职。
具体来说:
- main类中负责用户的登录和切换出题难度
- Makeallquestion 接口中包含了一个方法makequestion,在makequestion类中得到了具体实现
- Makequestion类中实现了2中接口的方法,对于小学,初中,高中的题目,各给出了具体的题目生成方法。同时实现了整张试卷的生成。
- FileIn类中实现了文件的写入,获取目标路径下所有文件的字符串和将目标文件进行清除的功能
- checkpaper类实现了文件查重的功能
- Teacher类进行了教师基本属性的构建
三.功能测试
- 用户的登录
当输入错误的用户名,密码时,能够自动进行判断
- 题目的生成
小学,初中,高中题目都符合规范
而当输入数量超过限制范围时,能正确地进行提示
3.切换难度出题目
当切换不符合规定时,能够进行正确地提示
四.核心代码分析
Main类:
public class Main { static String[] count = {"张三1", "张三2", "张三3", "李四1", "李四2", "李四3", "王五1", "王五2", "王五3"}; static String[] password = {"123", "123", "123", "123", "123", "123", "123", "123", "123"}; static String[] type = {"小学", "小学", "小学", "初中", "初中", "初中", "高中", "高中", "高中"}; public static void main(String[] args) throws IOException { while (true) { System.out.println("请输入正确的用户名和密码:"); Scanner input = new Scanner(System.in); String countIn = input.next(); String passwordIn = input.next(); for (int ii = 0; ii < count.length; ii++) { if (count[ii].equals(countIn) && password[ii].equals(passwordIn)) { Teacher user = new Teacher(count[ii], type[ii]); back: while (true) { user.print1(); String in = input.next(); switch (in) { case "切换为小学": user.changeType("小学"); continue back; case "切换为初中": user.changeType("初中"); continue back; case "切换为高中": user.changeType("高中"); continue back; default: try { int num = Integer.parseInt(in); if (num == -1) { break back; } if (num < 10 || num > 30) { System.out.println("数量范围:[10,30],请重新输入"); continue back; } MakeQuestion paper = new MakeQuestion(user.getType(), num); FileIn fileIn1 = new FileIn(user); File file2 = fileIn1.makeFile(); paper.makePaper(num, file2, paper, fileIn1); } catch (NumberFormatException n) { System.out.println("输入错误,请重新输入"); } } } } } } } }
在main类里进行了用户地登录和切换,值得一提地是,作者使用了java中的标签,使得程序的逻辑显得十分简单,避免了复杂的跳转判断
Teacher类:
public void print1() { if (this.type.equals("小学")) { System.out.println("准备生成小学数学题目,请输入题目个数(范围:[10,30],输入-1推出当前账户)"); } if (this.type.equals("初中")) { System.out.println("准备生成初中数学题目,请输入题目个数(范围:[10,30],输入-1推出当前账户)"); } if (this.type.equals("高中")) { System.out.println("准备生成高中数学题目,请输入题目个数(范围:[10,30],输入-1推出当前账户)"); } }
进行了用户地创建,其中将一些集成性地语句浓缩到print1方法中,避免了在main函数中过多的解释,提高了代码的复用性
FileIn类:
public File makeFile() { SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); String date = df.format(new Date()); String name = user.getCountName(); String str = "./paper\\paper of " + name; File dirt = new File(str); if (!dirt.exists()) { dirt.mkdirs(); } File file = new File(str, date + ".txt"); try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } return file; } public void fileInput(File file, String line) throws IOException { boolean append = true; FileWriter fw = new FileWriter(file, append); fw.write(line); fw.append("\r\n"); fw.flush(); fw.close(); }
进行了用户文件夹的创建以及不同文件之间的查重,使用了相对路径,使得保存文件比较方便
CheckPaper类:
public boolean compare(String file1, String file2) throws IOException { Path path1 = Paths.get(file1); Path path2 = Paths.get(file2); try (InputStream inp1 = Files.newInputStream(path1); InputStream inp2 = Files.newInputStream(path2)) { int bt1; int bt2; do { bt1 = inp1.read(); bt2 = inp2.read(); if (bt1 != bt2) { return false; } } while (bt1 != -1); return true; } } public boolean checkPaper(String[] path, String filename) throws IOException { boolean res = false; for (int i = 0; i < path.length; i++) { if (compare(path[i], filename) && !filename.equals(path[i])) { res = true; } } return res; }
进行了文件的查重,其中又将查重的具体代码进行浓缩,使得代码逻辑清晰
MakeQuestion类:
public class MakeQuestion implements MakeAllQuestion { /** * 这个方法用来生成问题. * * @param type 类别参数 * @return {@link String} 返回相应生成的题目 */ public String makeQuestion(String type) { if (type.equals("小学")) { return makePrimaryQuestion(); } else if (type.equals("初中")) { return makeJuniorQuestion(); } else if (type.equals("高中")) { return makeHighQuestion(); } else { return "1"; } } String type; int num; String[] primaryChar = {"+", "-", "*", "/"}; String[] juniorChar = {"^2", "√", " "}; String[] highChar1 = {"sin", "cos", "tan", " "}; /** * 该类的构造函数. * * @param type 参数类别 * @param num 题目的数量 */ public MakeQuestion(String type, int num) { this.num = num; this.type = type; } /** * 获取该类的类别. * * @return {@link String} 返回类别 */ public String getType() { return this.type; } /** * 根据不同的标志位返回左括号还是右括号. * * @param flag 标志位 * @return {@link String} 返回括号字符 */ public String getBracket(boolean flag) { if (flag) { return "("; } else { return ")"; } } /** * 根据不同的标志位来添加左括号. * * @param g 标志位 * @param i 循环次数 * @param a 操作数个数 * @param question 题目 * @param flag 标志位 * @return {@link String}返回加完左括号的题目 */ public String leftBracket(int[] g, int i, int a, String question, boolean[] flag) { if (g[0] == 0 && i != (a - 1) && flag[0]) { question = question + getBracket(flag[0]); flag[0] = !flag[0]; g[0] = 1; } return question; } /** * 根据不同的标志位来添加右括号. * * @param g 标志位 * @param i 循环次数 * @param a 操作数个数 * @param question 题目 * @param flag 标志位 * @return {@link String}返回加完右括号的题目 */ public String rightBracket(int[] g, int i, int a, String question, boolean[] flag) { if (g[0] == 0 && i != (a - 1) && !flag[0]) { question = question + getBracket(flag[0]); flag[0] = !flag[0]; } return question; } /** * 生成随机的高中题目. * * @param a 操作数个数 * @param question 题目 * @param flag 标志位 * @param flag1 是否有高中符号的标志位 * @return {@link String}返回生成的题目 */ public String switchIntHigh(int a, String question, boolean[] flag, int[] flag1) { for (int i = 0; i < a; i++) { int c = (int) (Math.random() * 100 + 1); int d = (int) (Math.random() * 4); int e = (int) (Math.random() * 4); int g = (int) (Math.random() * 2); String str1 = Integer.toString(c); String str2 = primaryChar[d]; String str3 = highChar1[e]; switch (e) { case 0: case 1: case 2: question = question + str2; if (g == 0 && i != (a - 1) && flag[0]) { question = question + getBracket(flag[0]); flag[0] = !flag[0]; g = 1; } question = question + str3; question = question + str1; if (g == 0 && i != (a - 1) && !flag[0]) { question = question + getBracket(flag[0]); flag[0] = !flag[0]; } flag1[0] = 1; break; case 3: question = question + str2; if (g == 0 && i != (a - 1) && flag[0]) { question = question + getBracket(flag[0]); flag[0] = !flag[0]; g = 1; } question = question + str1; if (g == 0 && i != (a - 1) && !flag[0]) { question = question + getBracket(flag[0]); flag[0] = !flag[0]; } break; default: break; } } return question; } /** * 生成添加一个操作数和一个符号或者一个括号的部分题目. * * @param a 操作数个数 * @param question 题目 * @param flag 标志位 * @param flag1 判断有没有符号的标志位 * @return {@link String} 返回生成的部分题目 */ public String switchIntJunior(int a, String question, boolean[] flag, int[] flag1) { for (int i = 0; i < a; i++) { int[] g = new int[1]; g[0] = (int) (Math.random() * 2); int c = (int) (Math.random() * 100 + 1); int d = (int) (Math.random() * 4); int e = (int) (Math.random() * 3); String str1 = Integer.toString(c); String str2 = primaryChar[d]; String str3 = juniorChar[e]; switch (e) { case 0: question = question + str3; question = question + str2; question = leftBracket(g, i, a, question, flag); question = question + str1; question = rightBracket(g, i, a, question, flag); flag1[0] = 1; break; case 1: question = question + str2; question = question + str3; question = leftBracket(g, i, a, question, flag); question = question + str1; question = rightBracket(g, i, a, question, flag); flag1[0] = 1; break; case 2: question = question + str2; question = leftBracket(g, i, a, question, flag); question = question + str1; question = rightBracket(g, i, a, question, flag); break; default: break; } } return question; } /** * 生成一个完整的小学题目. * * @return {@link String} 返回生成好的小学题目 */ public String makePrimaryQuestion() { boolean flag = true; int c = (int) (Math.random() * 4 + 1); int d = (int) (Math.random() * 100 + 1); String question = Integer.toString(d); int f = (int) (Math.random() * 2); if (f == 0) { question = getBracket(flag) + question; flag = !flag; } for (int i = 0; i < c; i++) { int e = (int) (Math.random() * 2); int a = (int) (Math.random() * 100 + 1); int b = (int) (Math.random() * 4); String str1 = Integer.toString(a); String str2 = primaryChar[b]; question = question + str2; if (e == 0 && i != (c - 1) && flag) { question = question + getBracket(flag); flag = !flag; e = 1; } question = question + str1; if (e == 0 && i != (c - 1) && !flag) { question = question + getBracket(flag); flag = !flag; } } if (!flag) { question = question + ")"; } return question; } /** * 生成一个完整的初中题目. * * @return {@link String} 返回生成好的初中题目 */ public String makeJuniorQuestion() { boolean[] flag = new boolean[1]; flag[0] = true; int[] flag1 = new int[1]; int a = (int) (Math.random() * 4 + 1); int b = (int) (Math.random() * 100 + 1); String question = Integer.toString(b); int f = (int) (Math.random() * 2); if (f == 0) { question = getBracket(flag[0]) + question; flag[0] = !flag[0]; } question = switchIntJunior(a, question, flag, flag1); if (flag1[0] == 0) { question = juniorChar[1] + question; } if (!flag[0]) { question = question + ")"; } return question; } /** * 生成一个完整的高中题目. * * @return {@link String} 返回生成好的高中题目 */ public String makeHighQuestion() { boolean[] flag = new boolean[1]; flag[0] = true; int[] flag1 = new int[1]; int a = (int) (Math.random() * 4 + 1); int b = (int) (Math.random() * 100 + 1); String question = Integer.toString(b); int f = (int) (Math.random() * 2); if (f == 0) { question = getBracket(flag[0]) + question; flag[0] = !flag[0]; } question = switchIntHigh(a, question, flag, flag1); if (flag1[0] == 0) { int h = (int) (Math.random() * 3); question = highChar1[h] + question; } if (!flag[0]) { question = question + ")"; } return question; } /** * 将生成的题目加入文件中形成试卷. * * @param num 题目的个数 * @param file 相应的文件 * @param paper 制作题目的对象 * @param fileIn 加入文件的对象 * @throws IOException 抛出异常 */ public void makePaper(int num, File file, MakeQuestion paper, FileIn fileIn) throws IOException { boolean flag = true; while (flag) { fileIn.fileClear(file); switch (paper.getType()) { case "高中": for (int k = 0; k < num; k++) { String question1 = paper.makeQuestion("高中"); System.out.println(question1); String str = Integer.toString(k + 1) + ". " + question1; fileIn.fileInput(file, str); } break; case "初中": for (int k = 0; k < num; k++) { String question1 = paper.makeQuestion("初中"); System.out.println(question1); String str = Integer.toString(k + 1) + ". " + question1; fileIn.fileInput(file, str); } break; case "小学": for (int k = 0; k < num; k++) { String question1 = paper.makeQuestion("小学"); System.out.println(question1); String str = Integer.toString(k + 1) + ". " + question1; fileIn.fileInput(file, str); } break; default: break; } CheckPaper check = new CheckPaper(); String filename = file.getPath(); if (!check.checkPaper(fileIn.getAllFile(), filename)) { flag = false; } } System.out.println("题目生成完毕"); } }
根据步骤:
1.先判断进行创建的是什么类型的问题
2.根据类型进行出题:paper.makequestion(type),并将题目写入相应的文件,filein.fileinput(file,str);
3.进行查重判断,如果有重复,则终止试卷的生成 check.checkpaper();
五.优缺点分析
优点:
- 代码编写符合Google编程规范,在相应的地方加入了合适的注解以便于阅读与理解
- 代码复用性高,减少了重复冗余代码的数量
- 代码阅读性强,基本实现见名知义
- 类与类之间分工明确,为功能的修改与移植增添了更多的可能性
缺点:
- 查重功能可以进一步完善,并选择合适的查重方式
- 某些地方可以增添更多注释,某些变量可以取合适的名字来便于理解
六.总结
总的来说,该项目实现了基本应该实现的功能,完成度较高,在评价过程中,我也认识到了自己的不足,对于他人的项目也需要进行优点的吸纳,希望能在之后的学习过程中互相激励,争取完成更好的项目