一、个人项目需求:
个人项目:中小学数学卷子自动生成程序
用户:
小学、初中和高中数学老师。
功能:
1、命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显示“当前选择为XX出题”,XX为小学、初中和高中三个选项中的一个。否则提示“请输入正确的用户名、密码”,重新输入用户名、密码;
2、登录后,系统提示“准备生成XX数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):”,XX为小学、初中和高中三个选项中的一个,用户输入所需出的卷子的题目数量,系统默认将根据账号类型进行出题。每道题目的操作数在1-5个之间,操作数取值范围为1-100;
3、题目数量的有效输入范围是“10-30”(含10,30,或-1退出登录),程序根据输入的题目数量生成符合小学、初中和高中难度的题目的卷子(具体要求见附表)。同一个老师的卷子中的题目不能与以前的已生成的卷子中的题目重复(以指定文件夹下存在的文件为准,见5);
4、在登录状态下,如果用户需要切换类型选项,命令行输入“切换为XX”,XX为小学、初中和高中三个选项中的一个,输入项不符合要求时,程序控制台提示“请输入小学、初中和高中三个选项中的一个”;输入正确后,显示“”系统提示“准备生成XX数学题目,请输入生成题目数量”,用户输入所需出的卷子的题目数量,系统新设置的类型进行出题;
5、生成的题目将以“年-月-日-时-分-秒.txt”的形式保存,每个账号一个文件夹。每道题目有题号,每题之间空一行;
个人项目9月17日晚上10点以前提交至创新课程管理系统。提交方式:工程文件打包,压缩包名为“几班+姓名.rar”。迟交2天及以内者扣分,每天扣20%。迟交2天及以上者0分。
附表-1:账户、密码
附表-2:小学、初中、高中题目难度要求
二、代码分析
UserLogin类:
public class UserLogin { public static void main(String[] args) { //Teacher [] teacher1 = new Teacher[3]; int N =3; PrimaryTeacher [] primaryTeachers = new PrimaryTeacher[N] ; MiddleTeacher [] middleTeachers = new MiddleTeacher[N] ; HighTeacher [] highTeachers = new HighTeacher[N] ; for(int i= 0;i<N; i++) { primaryTeachers[i] =new PrimaryTeacher(); primaryTeachers[i].setUserName("张三"+(i+1)); primaryTeachers[i].setLoginPassword("123"); primaryTeachers[i].setSchools("小学"); middleTeachers[i] = new MiddleTeacher(); middleTeachers[i].setUserName("李四"+(i+1)); middleTeachers[i].setLoginPassword("123"); middleTeachers[i].setSchools("初中"); highTeachers[i] = new HighTeacher(); highTeachers[i].setUserName("王五"+(i+1)); highTeachers[i].setLoginPassword("123"); highTeachers[i].setSchools("高中"); } //用户进行登录 System.out.println("——————————————————————————————————————"); System.out.println("| 中小学数学卷子自动生成程序 |"); System.out.println("——————————————————————————————————————"); Scanner st = new Scanner(System.in); Teacher Teachers = new Teacher(); while(true) { System.out.println("请输入用户名和密码"); Teachers.setUserName(st.next()); Teachers.setLoginPassword(st.next()); boolean res = Equal.equal(primaryTeachers,middleTeachers,highTeachers,Teachers,N); if(!res) { System.out.println("请输入正确的用户名、密码"); continue; }else if (res) { //已进入系统 System.out.println("登录成功"); System.out.println("若需要切换类型请输入 : 1 切换页面"); System.out.println("若不需要切换页面请输入: 0 "); int temp = st.nextInt(); if(temp==1) { while(true) { System.out.println("“切换为XX"); String Schools = st.next(); if((Schools.equals("小学"))||(Schools.equals("初中"))||(Schools.equals("高中"))) { System.out.println("已成功切换为"+Teachers.Schools+"模式");break; }else { System.out.println("请输入小学、初中和高中三个选项中的一个"); } } } while (true) { System.out.println("当前选择为"+Teachers.Schools+"出题"); System.out.print("准备生成"+Teachers.Schools+"数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):"); int number = st.nextInt();//生成题目数量(输入-1将退出当前用户,重新登录) if(number == -1) { System.out.println("退出当前用户,请重新登录"); break; } else if ((number>=10)&&(number)<=30) { //进行出题操作 System.out.println("正在生成题目"); if(Teachers.Schools=="小学") { File paper = MakeFile.makeFile(Teachers); PrimaryTeacher.PrimaryQuestion(number,4,paper); } else if (Teachers.getSchools()=="初中") { File paper = MakeFile.makeFile(Teachers); MiddleTeacher.MiddleQuestion(number,4,paper); } else if (Teachers.getSchools()=="高中") { File paper = MakeFile.makeFile(Teachers); HighTeacher.HighQuestion(number,4,paper); } }else if ((number<10)||(number>30)) { System.out.println("请输入有效整数,范围[10,30]");continue; } } } } }
该类中的main函数包含了用户登录以及切换模式等功能的实现,非常清晰,但是方法行数过长,可以将确认用户信息功能与切换功能单独作为一个方法,再去调用,也更方便后续修改。
check函数:
public static boolean check(File file, String title) { //定义变量 是否重复 boolean repetition = false; //获取txt文件上一级目录的路径 String parentPath = file.getParent(); File parent = new File(parentPath); //遍历上一级目录,获得其下的所有文件 File[] files = parent.listFiles(); //一个一个文件进行查重对比 for (int i = 0; i < files.length; i++) { try { FileReader fileReader = new FileReader(files[i]); BufferedReader bufferedReader = new BufferedReader(fileReader); while (true) { //读取一行数据 String usedTitle = bufferedReader.readLine(); //如果是空行就跳过 if (usedTitle == null) { break; } //以" "为分隔符," "后面的就是算式 String[] uT = usedTitle.split(" "); if (uT.length > 1) { if (uT[1].equals(title)) { System.out.println("重复"); //如果重复改变变量的值 repetition = true; } } } } catch (Exception e) { e.printStackTrace(); } } return repetition; }
该函数用于检查重复题目。
UserQuestion类:
public class UserQuestion { //生成随机整数 //生成随机符号 private static String getRandomOperator1(Random random) {//小学 String [] operators = {"+", "-", "*", "/","(",")"}; return operators[random.nextInt(operators.length)]; } private static String getRandomOperator2(Random random) {//初中 String [] operators = {"+", "-", "*", "/","^2","√","(",")"}; return operators[random.nextInt(operators.length)]; } private static String getRandomOperator3(Random random) {//高中 String [] operators = {"+", "-", "*", "/","^2","√","cos","sin","tan","(",")"}; return operators[random.nextInt(operators.length)]; } private static void addBrackets(StringBuffer problem, Random random) { int numOperations = (problem.length() + 1) / 2; int numBrackets = random.nextInt(numOperations); for (int i = 0; i < numBrackets; i++) { int index = random.nextInt(problem.length()); problem.insert(index, '('); problem.insert(index + 4, ')'); } } public static String QuestionExpression1(){ //小学 StringBuffer str = new StringBuffer() ; Random Random = new Random(); int number = Random.nextInt(5)+1; for (int i = 0; i < number; i++) { int operand = Random.nextInt(100)+1; // 随机生成操作数(1到100之间) String operator = i == 0 ? String.valueOf('+') : getRandomOperator1(Random); // 随机生成运算符 str.append(operator); str.append(operand); } // 在题目字符串中随机添加括号 // addBrackets(str, Random); return str.toString(); } public static String QuestionExpression2(){ //初中 StringBuffer str = new StringBuffer() ; Random Random = new Random(); int number = Random.nextInt(5)+1; for (int i = 0; i < number; i++) { int operand = Random.nextInt(100)+1; // 随机生成操作数(1到100之间) String operator = i == 0 ? String.valueOf('+') : getRandomOperator2(Random); // 随机生成运算符 str.append(operator); str.append(operand); } // 在题目字符串中随机添加括号 // addBrackets(str, Random); return str.toString(); } public static String QuestionExpression3(){ //高中 StringBuffer str = new StringBuffer() ; Random Random = new Random(); int number = Random.nextInt(5)+1; for (int i = 0; i < number; i++) { int operand = Random.nextInt(100)+1; // 随机生成操作数(1到100之间) String operator = i == 0 ? String.valueOf('+') : getRandomOperator3(Random); // 随机生成运算符 str.append(operator); str.append(operand); } // 在题目字符串中随机添加括号 // addBrackets(str, Random); return str.toString(); } }
该类用于生成小学初中高中对应的题目。每个模式的题都有不同的数组提供不同的数学运算符号,保证了不同的难度。但是太短不必单独成为方法,可以放到QuestionExpression的方法中。addBranket方法生成括号的方法有些问题,可能导致括号位置不对。
writeIn函数:
public static void writeIn(File file, Integer n, String title) { try { //传入文件 确定类型为续写 FileWriter fileWriter = new FileWriter(file,true); String path=file.getPath(); //序号 String num = n.toString() + "."; fileWriter.append(num).append(" ").append(title); //空一行 fileWriter.append("\r\n"); fileWriter.append("\r\n"); //刷新文件,关闭writer fileWriter.flush(); fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } }
该函数用于将生成的题目写进指定的文件中。
makeFile函数:
public static File makeFile(Teacher Teachers) { String mkPath = "F:\\IDEA_projects\\"+Teachers.getUserName(); File file =new File(mkPath) ; Date date = new Date() ; SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); String title = simpleDateFormat.format(date) + ".txt"; if (!file.exists()) { file.mkdirs(); } File paper = new File(mkPath, title); try { paper.createNewFile(); } catch (IOException e) { e.printStackTrace(); } return paper; }
该函数用于指定试卷位置以及名称,文件名称正确。
三、功能测试
账号密码正确时正常登录:
账号或密码错误时提示输入错误:
切换出题模式功能成功实现:
选择出题数量在正确范围时成功出题,不在范围内时提示输入有效题目数,输入-1时成功退出登录:
四、个人项目总评
优点:
代码复用不多,几乎没有重复代码。
输出美观且易于理解,便于用户使用。
结构整洁规范。
缺点:
main函数长度过长。
括号生成不符合逻辑。