From c117e88078a8a2f8c63e015f5646827b1eb8e8f8 Mon Sep 17 00:00:00 2001 From: Arno <15528622+arno-1@user.noreply.gitee.com> Date: Sat, 27 Sep 2025 00:07:20 +0800 Subject: [PATCH] Initial commit --- doc/README.md | 35 +++++++++++++ src/Base/Question.java | 22 ++++++++ src/Base/User.java | 21 ++++++++ src/Deal/Deal_file.java | 75 +++++++++++++++++++++++++++ src/Deal/Deal_paper.java | 56 ++++++++++++++++++++ src/Deal/Deal_user.java | 35 +++++++++++++ src/Generator/G_ques.java | 7 +++ src/Generator/Jun_g_ques.java | 63 +++++++++++++++++++++++ src/Generator/Pri_g_ques.java | 39 ++++++++++++++ src/Generator/Sen_g_ques.java | 47 +++++++++++++++++ src/Main.java | 6 +++ src/Math_System.java | 97 +++++++++++++++++++++++++++++++++++ 12 files changed, 503 insertions(+) create mode 100644 doc/README.md create mode 100644 src/Base/Question.java create mode 100644 src/Base/User.java create mode 100644 src/Deal/Deal_file.java create mode 100644 src/Deal/Deal_paper.java create mode 100644 src/Deal/Deal_user.java create mode 100644 src/Generator/G_ques.java create mode 100644 src/Generator/Jun_g_ques.java create mode 100644 src/Generator/Pri_g_ques.java create mode 100644 src/Generator/Sen_g_ques.java create mode 100644 src/Main.java create mode 100644 src/Math_System.java diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 0000000..fe253d4 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,35 @@ +# 中小学数学卷子自动生成器 + +## 文件结构及类设计 +软件2302_乔毅凡_个人项目 +|——src  源代码文件夹 +  |——Base  基本类包 +    |——Question  题目类 +    |——User  用户类 +  |——Deal  操作类包 +    |——Deal_file  处理文件保存和查重 +    |——Deal_paper  生成完整试卷 +    |——Deal_user  处理用户加载 +  |——Generator  题目生成器包 +    |——G_ques  题目生成器接口 +    |——Pri_g_ques  小学题目生成 +    |——Jun_g_ques  初中题目生成 +    |——Sen_g_ques  高中题目生成 +  |——Math_System  出卷系统类 +  |——Main  main函数 +|——doc  说明文件目录 +  |——README.md  说明文件 + +## 使用说明 +1. 进入系统后,输入账号密码登录(空格分割),登录界面输入exit可以退出系统。 +2. 登陆后,输入数字(10-30)生成试卷,并提示文件的保存地址。 +3. 登陆后可以通过“切换为/小学/初中/高中”切换出题模式。 +4. 输入“-1”退出当前登录 + +## 题目生成说明 +1. 小学题目2-5个操作数,运算包含+、-、*、\,随机加括号 +2. 初中题目1-5个操作数,运算包含+、-、*、\,随机加平方或开根(至少一个),没有括号 +3. 高中题目1-5个操作数,运算包含+、-、*、\,每一项均为三角函数,随机加平方。 + +--- +软件2302 202326010228 乔毅凡 \ No newline at end of file diff --git a/src/Base/Question.java b/src/Base/Question.java new file mode 100644 index 0000000..b367eb5 --- /dev/null +++ b/src/Base/Question.java @@ -0,0 +1,22 @@ +package Base; + +public class Question { + private int number; + private String content; + private String type; + + public Question(int number, String content, String type) { + this.number = number; + this.content = content; + this.type = type; + } + + public int getNumber() { return number; } + public String getContent() { return content; } + public String getType() { return type; } + + @Override + public String toString(){ + return this.number+". "+this.content+" = ?"; + } +} diff --git a/src/Base/User.java b/src/Base/User.java new file mode 100644 index 0000000..289b7ff --- /dev/null +++ b/src/Base/User.java @@ -0,0 +1,21 @@ +package Base; + +public class User { + private String id; + private String password; + private String type; + + public User(String id, String ps, String type) { + this.id = id; + this.password = ps; + this.type = type; + } + + public String getUsername() { return id; } + public String getPassword() { return password; } + public String getUserType() { return type; } + + public void change_type(String new_type){ + this.type=new_type; + } +} diff --git a/src/Deal/Deal_file.java b/src/Deal/Deal_file.java new file mode 100644 index 0000000..9a3ce7f --- /dev/null +++ b/src/Deal/Deal_file.java @@ -0,0 +1,75 @@ +package Deal; + +import Base.Question; + +import java.io.*; +import java.text.SimpleDateFormat; +import java.util.*; + +public class Deal_file { + private static final String BASE_DIR="试卷/"; + + public Deal_file() { + File baseDir = new File(BASE_DIR); + if (!baseDir.exists()) { + if (!baseDir.mkdirs()) + System.out.println("目录创建失败!"); + } + } + + public void savePaper(ArrayList paper, String username) { + String userDirPath = BASE_DIR + username + "/"; + File userDir = new File(userDirPath); + if (!userDir.exists()) { + if (!userDir.mkdirs()) { + System.out.println("目录创建失败!"); + return; + } + } + String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); + String filePath = userDirPath + timestamp + ".txt"; + + try (PrintWriter writer = new PrintWriter(new FileWriter(filePath))) { + for (int i = 0; i < paper.size(); i++) { + writer.println(paper.get(i).toString()); + if (i < paper.size() - 1) { + writer.println(); + } + } + System.out.println("试卷已保存至: " + new File(filePath).getAbsolutePath()); + } catch (IOException e) { + System.out.println("保存文件出错: " + e.getMessage()); + } + } + + public Set Check_Existing(String username) { + Set questions = new HashSet<>(); + String userDirPath = BASE_DIR + username + "/"; + File userDir = new File(userDirPath); + + if (!userDir.exists() || !userDir.isDirectory()) { + return questions; + } + + File[] files = userDir.listFiles(); + if (files == null) { + return questions; + } + + for (File file : files) { + if (file.isFile() && file.getName().endsWith(".txt")) { + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line; + while ((line = reader.readLine()) != null) { + if (!line.trim().isEmpty()) { + questions.add(line.trim()); + } + } + } catch (IOException e) { + return questions; + } + } + } + return questions; + } +} diff --git a/src/Deal/Deal_paper.java b/src/Deal/Deal_paper.java new file mode 100644 index 0000000..ab2fff3 --- /dev/null +++ b/src/Deal/Deal_paper.java @@ -0,0 +1,56 @@ +package Deal; + +import Base.Question; +import Base.User; +import Generator.G_ques; +import Generator.Jun_g_ques; +import Generator.Pri_g_ques; +import Generator.Sen_g_ques; + +import java.util.ArrayList; +import java.util.Set; + +public class Deal_paper { + private G_ques g_ques; + private Deal_file write_file; + public Deal_paper(User user){ + write_file=new Deal_file(); + switch (user.getUserType()){ + case "小学":{ + g_ques=new Pri_g_ques(); + break; + } + case "初中":{ + g_ques=new Jun_g_ques(); + break; + } + case "高中":{ + g_ques=new Sen_g_ques(); + break; + } + default:{ + g_ques=new Pri_g_ques(); + } + } + } + + public void g_paper(int count,String username){ + ArrayList result=new ArrayList<>(); + Set existing_ques=write_file.Check_Existing(username); + for (int i=0;i all_user; + public Deal_user(){ + load_user(); + } + + public void load_user(){ + all_user=new HashMap<>(); + + all_user.put("张三1", new User("张三1", "123", "小学")); + all_user.put("张三2", new User("张三2", "123", "小学")); + all_user.put("张三3", new User("张三3", "123", "小学")); + + // 初中老师 + all_user.put("李四1", new User("李四1", "123", "初中")); + all_user.put("李四2", new User("李四2", "123", "初中")); + all_user.put("李四3", new User("李四3", "123", "初中")); + + // 高中老师 + all_user.put("王五1", new User("王五1", "123", "高中")); + all_user.put("王五2", new User("王五2", "123", "高中")); + all_user.put("王五3", new User("王五3", "123", "高中")); + } + + public User login(String id,String psw){ + User temp=all_user.get(id); + return (temp!=null&&temp.getPassword().equals(psw))?temp:null; + } +} diff --git a/src/Generator/G_ques.java b/src/Generator/G_ques.java new file mode 100644 index 0000000..c3017cb --- /dev/null +++ b/src/Generator/G_ques.java @@ -0,0 +1,7 @@ +package Generator; + +public interface G_ques { + String g_question(); + String g_type(); + char g_operator(); +} diff --git a/src/Generator/Jun_g_ques.java b/src/Generator/Jun_g_ques.java new file mode 100644 index 0000000..8a8585a --- /dev/null +++ b/src/Generator/Jun_g_ques.java @@ -0,0 +1,63 @@ +package Generator; + +import java.util.Random; + +public class Jun_g_ques implements G_ques{ + private Random ra= new Random(); + + @Override + public String g_question() { + int count=ra.nextInt(5)+1; + StringBuilder question = new StringBuilder(); + boolean flag=false; + for (int i=0;i0){ + question.append(" ").append(g_operator()).append(" "); + } + if (ra.nextDouble()<0.25) { + if (ra.nextBoolean()) { + question.append(ra.nextInt(30) + 1).append("²"); + } + else { + question.append("√").append(ra.nextInt(100) + 1); + } + flag=true; + } + else { + question.append(ra.nextInt(100) + 1); + } + } + if (!flag){ + if(count==1){ + if (ra.nextBoolean()){ + question.append("²"); + } + else { + question.insert(0,"√"); + } + } + else { + String[] parts = question.toString().split(" "); + int pos = ra.nextInt(count); + if (ra.nextBoolean()) { + parts[pos * 2] = parts[pos * 2] + "²"; + } else { + parts[pos * 2] = "√" + parts[pos * 2]; + } + question = new StringBuilder(String.join(" ", parts)); + } + } + return question.toString(); + } + + @Override + public String g_type(){ + return "初中"; + } + + @Override + public char g_operator(){ + char[] op={'+','-','*','/'}; + return op[ra.nextInt(op.length)]; + } +} diff --git a/src/Generator/Pri_g_ques.java b/src/Generator/Pri_g_ques.java new file mode 100644 index 0000000..18f4687 --- /dev/null +++ b/src/Generator/Pri_g_ques.java @@ -0,0 +1,39 @@ +package Generator; + +import java.util.Random; + +public class Pri_g_ques implements G_ques{ + private Random ra= new Random(); + + @Override + public String g_question() { + int count=ra.nextInt(4)+2; + StringBuilder question = new StringBuilder(); + int count_bracket=0; + for (int i=0;i 0) { + question.append(" ").append(g_operator()).append(" "); + } + if (i!=count-1&&ra.nextDouble()<0.4){ + question.append("("); + count_bracket++; + } + question.append(ra.nextInt(100) + 1); + } + if (count_bracket!=0){ + question.append(")".repeat(Math.max(0, count_bracket))); + } + return question.toString(); + } + + @Override + public String g_type(){ + return "小学"; + } + + @Override + public char g_operator(){ + char[] op={'+','-','*','/'}; + return op[ra.nextInt(op.length)]; + } +} diff --git a/src/Generator/Sen_g_ques.java b/src/Generator/Sen_g_ques.java new file mode 100644 index 0000000..52bfcd9 --- /dev/null +++ b/src/Generator/Sen_g_ques.java @@ -0,0 +1,47 @@ +package Generator; + +import java.util.Random; + +public class Sen_g_ques implements G_ques{ + private Random ra= new Random(); + + @Override + public String g_question() { + int count=ra.nextInt(5)+1; + StringBuilder question = new StringBuilder(); + boolean flag=false; + for (int i=0;i 0) { + question.append(" ").append(g_operator()).append(" "); + } + if (ra.nextDouble()<0.3){ + question.append(g_trig()).append("²").append("(").append(g_angle()).append("°)"); + } + else { + question.append(g_trig()).append("(").append(g_angle()).append("°)"); + } + } + return question.toString(); + } + + @Override + public String g_type(){ + return "高中"; + } + + @Override + public char g_operator(){ + char[] op={'+','-','*','/'}; + return op[ra.nextInt(op.length)]; + } + + public String g_trig(){ + String[] trig={"sin","cos","tan"}; + return trig[ra.nextInt(trig.length)]; + } + + public String g_angle(){ + String[] angle={"15","22.5","75","105","120","135","150","210","300"}; + return angle[ra.nextInt(angle.length)]; + } +} diff --git a/src/Main.java b/src/Main.java new file mode 100644 index 0000000..bb31fb1 --- /dev/null +++ b/src/Main.java @@ -0,0 +1,6 @@ +public class Main { + public static void main(String[] args){ + Math_System m_system=new Math_System(); + m_system.main_menu(); + } +} diff --git a/src/Math_System.java b/src/Math_System.java new file mode 100644 index 0000000..fdbd9d7 --- /dev/null +++ b/src/Math_System.java @@ -0,0 +1,97 @@ +import Base.User; +import Deal.Deal_paper; +import Deal.Deal_user; + +import java.util.Scanner; + +public class Math_System { + private User now_user; + private Deal_paper d_paper; + private Deal_user d_user; + private Scanner scanner; + + public Math_System(){ + now_user=null; + d_paper=null; + d_user=new Deal_user(); + } + + public void main_menu(){ + scanner=new Scanner(System.in); + while(true){ + if (now_user==null){ + login_in(); + } + else { + generator(); + } + } + } + + public void login_in(){ + System.out.println("请输入用户名和密码(空格分隔):"); + String input = scanner.nextLine().trim(); + + if (input.equalsIgnoreCase("exit")) { + System.exit(0); + } + + String[] parts = input.split("\\s+"); //空格 + + if (parts.length != 2){ + System.out.println("请输入正确的用户名、密码"); + return; + } + + String username=parts[0]; + String psw=parts[1]; + + if (d_user.login(username,psw)==null) { + now_user=null; + System.out.println("请输入正确的用户名、密码"); + } + else { + now_user=d_user.login(username,psw); + d_paper=new Deal_paper(now_user); + System.out.println("当前选择为 " + now_user.getUserType() + " 出题"); + } + } + + public void generator(){ + System.out.println("准备生成"+now_user.getUserType()+"数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):"); + String input = scanner.nextLine().trim(); + + if (input.equals("-1")){ + now_user=null; + d_paper=null; + return; + } + if (input.startsWith("切换为")) { + change_mode(input); + return; + } + try { + int count = Integer.parseInt(input); + if (count<10||count>30){ + System.out.println("题目数量应在10-30之间。"); + return; + } + d_paper.g_paper(count,now_user.getUsername()); + }catch (NumberFormatException e){ + System.out.println("请正确输入题目数量。"); + } + } + + public void change_mode(String new_mode){ + String[] parts=new_mode.split("切换为"); + String type=parts[1].trim(); + if ((!type.equals("小学") && !type.equals("初中") && !type.equals("高中")) || parts.length!=2){ + System.out.println("请输入小学、初中和高中三个选项中的一个"); + } + else{ + now_user.change_type(type); + d_paper=new Deal_paper(now_user); + System.out.println("成功切换为"+type); + } + } +}