Compare commits

..

1 Commits

Author SHA1 Message Date
Forever-XK 0dea48e3bb v3.0
5 months ago

@ -1,12 +1,15 @@
中小学数学卷子自动生成程序
-
---
项目简介
-
---
本项目实现了一个为中小学教师自动生成试卷的程序。
程序通过命令行进行交互,根据登录的账号自动匹配对应难度的试题进行生成,同时支持用户切换,难度切换,试题查重,自动保存等功能。
项目结构
-
---
```plaintext
中小学数学卷子自动生成程序/
├── src/ # 源代码目录
@ -27,6 +30,7 @@
```
功能特性
-
---
1. 用户登录
支持预设的 9 个账户(小学 3 个、初中 3 个、高中 3 个)
账户信息:
@ -53,6 +57,7 @@
使用示例
-
---
### 平台支持

Binary file not shown.

@ -1,29 +0,0 @@
1. (66 * 13) / 98
2. (54 + 11) / 27 + 14 - 40
3. (68 / 7) * 80 * 74 + 40
4. (51 / 88) + 69 * 24
5. (38 * 80) / 94 / 1 - 41
6. (61 - 80) * 65
7. (87 / 54) + 36
8. (52 / 81) + 11 - 36
9. 75 - 71
10. (77 - 5) - 87 * 81
11. 59 / (62 + 29 * 85) - 14
12. (72 * 67) * 36
13. (91 / 16) * 78
14. 71 - 30
15. (38 * 26) + 54 / 90

@ -1,39 +0,0 @@
1. 26 + 45 - pow(43,2) / 10
2. 68 * sqrt(20) + 7
3. 5 - 81 + 61 * pow(64,2) - 36
4. 6 + pow(41,2)
5. 55 / sqrt(78) * 93 / 17
6. pow(93,2) * 1 * 78
7. 6 - pow(8,2) - 7
8. sqrt(34) + 6
9. 68 * pow(39,2)
10. 19 - sqrt(66)
11. 62 + 57 - pow(60,2) / 19 + 88
12. 61 + 54 * sqrt(98) * 51 * 78
13. pow(23,2) - 82 * 13
14. pow(22,2) - 43
15. 59 - sqrt(82)
16. 22 / pow(19,2)
17. sqrt(6) - 13
18. 51 + 7 * sqrt(13) + 13 / 86
19. 80 * 59 + 38 / sqrt(28) + 59
20. 42 + 79 + 60 / pow(93,2) + 68

@ -1,49 +0,0 @@
1. cos(50) - 5 - 15 * 48
2. 85 + 27 + cos(81) + 54 * 22
3. cos(65) + 99
4. 90 - sin(23)
5. 12 - 49 * cos(52)
6. 53 * 56 / 29 + sin(59)
7. tan(5) + 45
8. 8 + 41 / 50 + cos(27) - 69
9. 77 * 80 - sin(68) / 59
10. sin(73) * 90 * 52
11. cos(15) / 3 / 45 / 71 - 55
12. 6 + 89 * sin(58)
13. 2 + cos(86) / 13 * 28
14. 92 + 68 + 10 - cos(88) + 37
15. 31 + 68 * 4 - cos(32)
16. 20 - 52 * 52 / sin(22)
17. 47 + 61 / 2 * 23 - cos(21)
18. sin(10) / 34
19. 91 - cos(3) + 59 - 15 * 30
20. 5 / 91 - cos(0) / 4 * 66
21. 54 - 40 / sin(79)
22. 6 + tan(58) - 16
23. 6 / cos(32) / 22
24. 9 / tan(33) * 24 + 69
25. 37 - 23 + cos(1) + 60 - 96

@ -1,19 +0,0 @@
1. 93 / 27 * 80 * pow(44,2) / 20
2. 29 / pow(78,2) / 98 - 60 / 45
3. 32 + 33 + 20 - 1 / pow(21,2)
4. 20 / pow(20,2) * 10 - 33 * 2
5. 59 / 22 * 91 - sqrt(14) + 39
6. 56 * 64 / sqrt(76) / 64
7. 75 - pow(33,2) - 54 - 7 - 36
8. 62 + sqrt(6)
9. pow(91,2) / 10 / 11 / 49 * 97
10. 31 + 82 / 53 / sqrt(80)

@ -1,59 +0,0 @@
1. 52 - sin(28)
2. 41 + 33 - tan(80) + 24
3. sin(72) - 89 - 70 - 7
4. 81 - 94 - 73 + cos(77)
5. tan(30) + 51 - 2
6. 39 + sin(1) + 10 - 60
7. 100 + cos(8) - 38 * 19 * 89
8. sin(79) / 98
9. cos(75) * 49 * 79
10. 78 / 40 * 75 / tan(0)
11. sin(43) - 13 * 69 * 83
12. 48 - cos(51)
13. 29 * 27 + tan(42) + 53
14. 85 + tan(48) - 18
15. 89 * tan(39)
16. 42 - sin(22) + 39
17. 74 * sin(4) - 10 * 47
18. 65 - 96 - 29 / cos(89) * 41
19. 46 * sin(2)
20. 32 * 84 - 97 / 20 + tan(50)
21. 28 * cos(59) / 63
22. sin(16) * 58
23. 53 * 55 - 63 + cos(66)
24. sin(91) * 82 / 60 * 88 + 65
25. 36 + 7 - 57 * 74 * sin(52)
26. 5 / 58 - tan(49)
27. 90 * tan(74)
28. tan(3) * 36
29. 49 / tan(82)
30. 15 / 12 / 37 - 76 / tan(35)

@ -1,42 +1,44 @@
package Program;
public class HighMaker extends QuestionMaker {
private static final char[] OPERATORS = {'+', '-', '*', '/'};
private static final String[] FUNCTIONS = {"sin", "cos", "tan"};
private static final char[] operators = {'+', '-', '*', '/'};
private static final String[] functions = {"sin", "cos", "tan"};
/**
*
* @return
*/
@Override
protected String makeOneQuestion() {
StringBuilder question = new StringBuilder();
boolean check = false;
boolean check=false;
int count = rand.nextInt(4) + 2;
int trigFunction = rand.nextInt(count);
int count=rand.nextInt(4)+2;
int trigFunction=rand.nextInt(count);
for (int i = 0; i < count; i++) {
if (i > 0) {
char operator = OPERATORS[rand.nextInt(OPERATORS.length)];
for(int i=0;i<count;i++){
if(i>0){
char operator=operators[rand.nextInt(operators.length)];
question.append(" ").append(operator).append(" ");
}
if (i == trigFunction && !check) {
String function = FUNCTIONS[rand.nextInt(FUNCTIONS.length)];
int angle = rand.nextInt(100);
if(i==trigFunction&&!check){
String function=functions[rand.nextInt(functions.length)];
int angle=rand.nextInt(100);
question.append(function).append("(").append(angle).append(")");
check = true;
} else {
int random = randomMaker();
check=true;
}else{
int random=randomMaker();
question.append(random);
}
}
if (!check) {
String function = FUNCTIONS[rand.nextInt(FUNCTIONS.length)];
char operator = OPERATORS[rand.nextInt(OPERATORS.length)];
int angle = rand.nextInt(100);
if(!check){
String function=functions[rand.nextInt(functions.length)];
char operator=operators[rand.nextInt(operators.length)];
int angle=rand.nextInt(100);
question.append(" ").append(operator).append(" ").append(function)
.append("(").append(angle).append(")");
}
@ -44,8 +46,10 @@ public class HighMaker extends QuestionMaker {
}
@Override
protected boolean checkQuestion(String question) {
// 检查是否包含三角函数
return question.contains("sin(") || question.contains("cos(")
|| question.contains("tan(");
}
}
}

@ -1,3 +0,0 @@
Manifest-Version: 1.0
Main-Class: Program.Main

@ -2,6 +2,10 @@ package Program;
import java.util.Scanner;
/**
*
*/
public class Main {
private final Scanner scanner;
private final Users users;
@ -9,12 +13,6 @@ public class Main {
private String currentUser;
private Type currentType;
public Main() {
this.scanner = new Scanner(System.in);
this.users = new Users();
this.questionManager = new QuestionManager();
}
private String getGrade(Type type) {
switch (type) {
case primary:
@ -28,16 +26,25 @@ public class Main {
}
}
/**清屏函数*/
public Main() {
this.scanner = new Scanner(System.in);
this.users = new Users();
this.questionManager = new QuestionManager();
}
/**
*
*/
private void clearScreen() {
try {
try{
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
} else {
if(os.contains("win")){
new ProcessBuilder("cmd","/c","cls").inheritIO().start().waitFor();
}else{
new ProcessBuilder("clear").inheritIO().start().waitFor();
}
} catch (Exception e) {
}catch(Exception e){
System.out.print("\033[H\033[2J");
System.out.flush();
}
@ -46,7 +53,7 @@ public class Main {
@SuppressWarnings("InfiniteLoopStatement")
public void run() {
while (true) {
if (Login()) {
if(Login()) {
Exchange();
}
}
@ -56,44 +63,45 @@ public class Main {
*
* @return
*/
private boolean Login() {
while (true) {
System.out.print("请输入用户名和密码[空格隔开]或输入‘-1退出程序: ");
String input = scanner.nextLine().trim();
if ("-1".equals(input)) {
if("-1".equals(input)) {
System.out.println("程序已退出");
System.exit(0);
}
String[] parts = input.split("\\s+");
if (parts.length != 2) {
if(parts.length != 2) {
System.out.println("请输入正确的用户名或密码");
continue;
}
String username = parts[0];
String password = parts[1];
Type type = users.verification(username, password);
if (type != null) {
Type type = users.verification(username,password);
if(type != null) {
currentUser = username;
currentType = type;
System.out.println("欢迎您," + currentUser + "");
System.out.println("欢迎您," +currentUser+"");
System.out.println("当前选择为" + getGrade(type) + "出题");
return true;
} else {
}else {
System.out.println("请输入正确的用户名或密码");
}
}
}
private void Exchange() {
while (true) {
System.out.print("准备生成" + getGrade(currentType)
+ "数学题目,请输入生成题目数量[10-30]或输入‘切换为’切换难度或输入‘-1退出当前用户");
while(true){
System.out.print("准备生成"+getGrade(currentType)
+"数学题目,请输入生成题目数量[10-30]或输入‘切换为’切换难度或输入‘-1退出当前用户");
String input = scanner.nextLine().trim();
if (input.startsWith("切换为")) {
if(input.startsWith("切换为")) {
Change(input);
continue;
}
@ -101,7 +109,7 @@ public class Main {
try {
int number = Integer.parseInt(input);
if (number == -1) {
if(number==-1){
currentType = null;
currentUser = null;
clearScreen();
@ -109,12 +117,12 @@ public class Main {
return;
}
if (number < 10 || number > 30) {
if(number<10||number>30){
System.out.println("题目数量必须在10-30之间");
continue;
}
makeAndSaveQuestions(number);
} catch (NumberFormatException e) {
makeAndSaveQuestions(number);
}catch(NumberFormatException e){
System.out.println("请输入有效数字");
}
}
@ -124,10 +132,11 @@ public class Main {
*
* @param input
*/
private void Change(String input) {
String result = input.substring(3).trim();
String result=input.substring(3).trim();
Type newType = null;
Type newType=null;
switch (result) {
case "小学":
newType = Type.primary;
@ -138,15 +147,16 @@ public class Main {
case "高中":
newType = Type.high;
break;
default:
}
if (newType == null) {
if(newType==null) {
System.out.println("请输入小学、初中和高中三个选项中的一个");
return;
}
currentType = newType;
System.out.println("成功切换为‘" + getGrade(newType)
currentType=newType;
System.out.println("成功切换为‘"+getGrade(newType)
+ "!");
}
@ -154,20 +164,21 @@ public class Main {
* -makeQuestions
* @param number
*/
private void makeAndSaveQuestions(int number) {
QuestionMaker maker = createMaker(currentType);
java.util.Set<String> exQuestions =
java.util.Set<String> exQuestions=
questionManager.loadQuestions(currentUser);
java.util.List<String> questions =
maker.makeQuestions(number, exQuestions);
java.util.List<String> questions=
maker.makeQuestions(number,exQuestions);
if (questions.size() < number) {
System.out.println("警告:由于查重限制,实际生成题目数量为:" + questions.size() + "道");
if(questions.size()<number){
System.out.println("警告:由于查重限制,实际生成题目数量为:" + questions.size()+"道");
}
questionManager.saveQuestions(currentUser, questions);
System.out.println(questions.size() + "道题目生成完成");
questionManager.saveQuestions(currentUser,questions);
System.out.println(questions.size()+"道题目生成完成");
}
/**
@ -175,6 +186,7 @@ public class Main {
* @param type
* @return
*/
private QuestionMaker createMaker(Type type) {
switch (type) {
case primary:
@ -184,7 +196,7 @@ public class Main {
case high:
return new HighMaker();
default:
throw new IllegalArgumentException("未知的输入" + type);
throw new IllegalArgumentException("未知的输入"+type);
}
}
@ -192,4 +204,4 @@ public class Main {
Main main = new Main();
main.run();
}
}
}

@ -1,15 +1,18 @@
package Program;
package Program;
import java.util.Set;
import java.util.List;
/**
*
*/
public interface Manager {
/**
*
* @param username
* @param questions
*/
void saveQuestions(String username, List<String> questions);
/**
@ -17,5 +20,6 @@ public interface Manager {
* @param username
* @return
*/
Set<String> loadQuestions(String username);
}

@ -1,46 +1,48 @@
package Program;
public class MiddleMaker extends QuestionMaker {
private static final char[] OPERATORS = {'+', '-', '*', '/'};
private static final char[] operators = {'+', '-', '*', '/'};
/**
*
* @return
*/
@Override
protected String makeOneQuestion() {
StringBuilder question = new StringBuilder();
boolean check = false;
int count = rand.nextInt(4) + 2;
int squareOrRoot = rand.nextInt(count);
int count=rand.nextInt(4) + 2;
int squareOrRoot=rand.nextInt(count);
for (int i = 0; i < count; i++) {
if (i > 0) {
char operator = OPERATORS[rand.nextInt(OPERATORS.length)];
for(int i = 0; i < count; i++){
if(i > 0) {
char operator = operators[rand.nextInt(operators.length)];
question.append(" ").append(operator).append(" ");
}
int random = randomMaker();
int random=randomMaker();
if (i == squareOrRoot && !check) {
if (rand.nextBoolean()) {
if(i==squareOrRoot&&!check) {
if(rand.nextBoolean()) {
question.append("pow(").append(random).append(",2)");
} else {
}else{
question.append("sqrt(").append(random).append(")");
}
check = true;
} else {
}else{
question.append(random);
}
}
if (!check) {
int random = randomMaker();
char operator = OPERATORS[rand.nextInt(OPERATORS.length)];
if (rand.nextBoolean()) {
if(!check){
int random=randomMaker();
char operator = operators[rand.nextInt(operators.length)];
if(rand.nextBoolean()) {
question.append(" ").append(operator).append(" pow(").append(random).append(",2)");
} else {
}else{
question.append(" ").append(operator).append(" sqrt(").append(random).append(")");
}
}
@ -48,7 +50,8 @@ public class MiddleMaker extends QuestionMaker {
}
@Override
protected boolean checkQuestion(String question) {
return question.contains("pow(") || question.contains("sqrt(");
}
}
}

@ -1,52 +1,56 @@
package Program;
public class PrimaryMaker extends QuestionMaker {
private static final char[] OPERATORS = {'+', '-', '*', '/'};
private static final char[] operators = {'+', '-', '*', '/'};
/**
*
* @param expression
* @return
*/
protected String bracketsMaker(String expression) {
protected String BracketsMaker(String expression){
String[] sum = expression.split(" ");
if (sum.length >= 5) {
// 只有当式子长度>=5时才添加括号
if(sum.length >= 5){
int maxStart = (sum.length - 5) / 2;
if (maxStart > 0) {
if(maxStart > 0){
int start = (rand.nextInt(maxStart) + 1) * 2;
int minEnd = start + 2;
int maxEnd = Math.min(sum.length - 3, start + 4);
if (maxEnd > minEnd) {
if(maxEnd > minEnd){
int end = minEnd + (rand.nextInt((maxEnd - minEnd) / 2 + 1)) * 2;
StringBuilder result = getBuilder(sum, start, end);
return result.toString();
}
}
// 如果上述逻辑没有添加括号,强制在前三个元素周围添加括号
StringBuilder result = new StringBuilder();
result.append("(").append(sum[0]).append(" ").append(sum[1]).append(" ").append(sum[2]).append(")");
for (int i = 3; i < sum.length; i++) {
for(int i = 3; i < sum.length; i++){
result.append(" ").append(sum[i]);
}
return result.toString();
}
// 对于长度<5的短式直接返回原式不添加括号
return expression;
}
private static StringBuilder getBuilder(String[] sum, int start, int end) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < sum.length; i++) {
if (i == start) {
for(int i = 0; i < sum.length; i++){
if(i == start){
result.append("(");
}
result.append(sum[i]);
if (i == end) {
if(i == end){
result.append(")");
}
if (i < sum.length - 1) {
if(i < sum.length - 1){
result.append(" ");
}
}
@ -60,12 +64,12 @@ public class PrimaryMaker extends QuestionMaker {
question.append(randomMaker());
for (int i = 1; i < count; i++) {
char operator = OPERATORS[rand.nextInt(OPERATORS.length)];
for(int i = 1; i < count; i++){
char operator = operators[rand.nextInt(operators.length)];
int randNum = randomMaker();
question.append(" ").append(operator).append(" ").append(randNum);
}
return bracketsMaker(question.toString());
return BracketsMaker(question.toString());
}
@Override

@ -1,42 +0,0 @@
package Program;
import java.util.HashMap;
import java.util.Map;
public class Users {
private static final Map<String, String> USERS = new HashMap<>();
static {
USERS.put("张三1", "123");
USERS.put("张三2", "123");
USERS.put("张三3", "123");
USERS.put("李四1", "123");
USERS.put("李四2", "123");
USERS.put("李四3", "123");
USERS.put("王五1", "123");
USERS.put("王五2", "123");
USERS.put("王五3", "123");
}
/**
*
* @param username
* @param password
* @return null
*/
public Type verification(String username, String password) {
if (!USERS.containsKey(username) || !USERS.get(username).equals(password)) {
return null;
}
if (username.startsWith("张三")) {
return Type.primary;
} else if (username.startsWith("李四")) {
return Type.middle;
} else if (username.startsWith("王五")) {
return Type.high;
}
return null;
}
}

@ -13,8 +13,9 @@ public abstract class QuestionMaker {
*
* @return 1-100
*/
protected int randomMaker() {
return rand.nextInt(100) + 1;
protected int randomMaker(){
return rand.nextInt(100)+1;
}
/**
@ -23,13 +24,14 @@ public abstract class QuestionMaker {
* @param exQuestions
* @return
*/
public List<String> makeQuestions(int number, Set<String> exQuestions) {
List<String> questions = new ArrayList<>();
int sum = 0;
while (questions.size() < number && sum < MAX_QUESTIONS) {
String question = makeOneQuestion();
if (checkQuestion(question) && !exQuestions.contains(question)) {
public List<String> makeQuestions(int number,Set<String> exQuestions) {
List<String> questions=new ArrayList<>();
int sum=0;
while(questions.size()<number&&sum<MAX_QUESTIONS) {
String question=makeOneQuestion();
if(checkQuestion(question)&&!exQuestions.contains(question)){
questions.add(question);
exQuestions.add(question);
}
@ -42,6 +44,7 @@ public abstract class QuestionMaker {
*
* @return
*/
protected abstract String makeOneQuestion();
/**
@ -49,5 +52,7 @@ public abstract class QuestionMaker {
* @param question
* @return
*/
protected abstract boolean checkQuestion(String question);
}
}

@ -17,20 +17,20 @@ public class QuestionManager implements Manager {
@Override
public void saveQuestions(String username, List<String> questions) {
File userFile = new File(QUESTIONS_FILE + File.separator + username);
File userFile = new File(QUESTIONS_FILE+File.separator+username);
if (!userFile.exists()) {
if (!userFile.mkdirs()) {
if(!userFile.mkdirs()){
System.err.println("创建目录失败: " + userFile.getPath());
return;
return; // 或者抛出异常
}
}
LocalDateTime now = LocalDateTime.now();
String fileName = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss"))
+ ".txt";
File questionsFile = new File(userFile, fileName);
+".txt";
File questionsFile = new File(userFile,fileName);
try (PrintWriter writer = new PrintWriter(new FileWriter(questionsFile))) {
try(PrintWriter writer=new PrintWriter(new FileWriter(questionsFile))) {
for (int i = 0; i < questions.size(); i++) {
writer.println((i + 1) + ". " + questions.get(i));
if (i < questions.size() - 1) {
@ -38,38 +38,38 @@ public class QuestionManager implements Manager {
}
}
System.out.println("文件已保存至:" + questionsFile.getPath());
} catch (IOException e) {
} catch (IOException e){
System.err.println("保存文件失败: " + e.getMessage());
}
}
@Override
public Set<String> loadQuestions(String username) {
public Set<String> loadQuestions(String username){
Set<String> questions = new HashSet<>();
File userFile = new File(QUESTIONS_FILE + File.separator + username);
File userFile = new File(QUESTIONS_FILE+File.separator+username);
if (!userFile.exists() || !userFile.isDirectory()) {
if(!userFile.exists()||!userFile.isDirectory()) {
return questions;
}
File[] files = userFile.listFiles((dir, name) -> name.endsWith(".txt"));
if (files == null) {
if(files==null) {
return questions;
}
for (File file : files) {
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
try(BufferedReader reader=new BufferedReader(new FileReader(file))){
String line;
while ((line = reader.readLine()) != null) {
while((line= reader.readLine())!=null){
line = line.trim();
if (line.matches("\\d+\\.\\s+.*")) {
if(line.matches("\\d+\\.\\s+.*")){
String question = line.substring(line.indexOf('.') + 1).trim();
questions.add(question);
}
}
} catch (IOException e) {
}catch(IOException e){
System.err.println("读取文件失败: " + file.getName() + " - " + e.getMessage());
}
}
return questions;
}
}
}

@ -1,7 +1,10 @@
package Program;
/**
*
*/
public enum Type {
primary,
middle,
high
}
}

@ -0,0 +1,43 @@
package Program;
import java.util.HashMap;
import java.util.Map;
public class Users {
private static final Map<String,String> users = new HashMap<>();
static {
users.put("张三1","123");
users.put("张三2","123");
users.put("张三3","123");
users.put("李四1","123");
users.put("李四2","123");
users.put("李四3","123");
users.put("王五1","123");
users.put("王五2","123");
users.put("王五3","123");
}
/**
*
* @param username
* @param password
* @return null
*/
public Type verification(String username,String password) {
if(!users.containsKey(username)||!users.get(username).equals(password)) {
return null;
}
if(username.startsWith("张三")){
return Type.primary;
}else if(username.startsWith("李四")){
return Type.middle;
}else if(username.startsWith("王五")){
return Type.high;
}
return null;
}
}
Loading…
Cancel
Save