1 #6

Merged
hnu202326010315 merged 1 commits from develop into main 5 months ago

@ -9,31 +9,35 @@
- 支持小学、初中和高中三个级别的用户账号
- 每个级别预设3个账号密码统一为123
- 登录成功后显示当前选择的出题级别
- 支持用户退出功能,可重新登录
### 2. 题目生成功能
- 根据账号类型自动选择对应的难度级别生成题目
- 支持自定义生成题目数量范围10-30题
- 操作数范围1-100
- 操作数个数2-5个
- 操作数个数1-5个
- 生成题目时实时显示题目内容
### 3. 多难度级别支持
- **小学**:仅包含加减乘除四则运算和括号
- **初中**:在小学基础上增加平方和开根号运算,每道题至少包含一个平方或开根号
- **高中**在初中基础上增加三角函数sin、cos、tan每道题至少包含一个三角函数
- **小学**:仅包含加减乘除四则运算和括号,支持随机括号嵌套
- **初中**:在小学基础上增加平方和开根号运算,题目包含1-5个操作数若只有1个操作数则必须是平方或根号表达式确保每道题至少包含一个平方或开根号
- **高中**在初中基础上增加三角函数sin、cos、tan题目包含1-5个操作数若只有1个操作数则强制为三角函数表达式确保每道题至少包含一个三角函数
### 4. 题目类型切换
- 支持在登录状态下切换不同难度级别的题目生成
- 输入格式:`切换为 小学/初中/高中`
- 切换成功后系统清屏并提示新的难度级别
### 5. 题目查重功能
- 自动检测新生成的题目是否与当前用户历史生成的题目重复
- 设置最大尝试次数,防止在题库不足时陷入死循环
- 确保每个用户生成的题目都是唯一的
### 6. 文件保存功能
- 题目以文本文件形式保存
- 文件名格式:`年-月-日-时-分-秒.txt`
- 每个用户有独立的文件夹存储题目
- 题目包含题号,每题之间空一行
- 文件名格式:`yyyy-MM-dd-HH-mm-ss.txt`(基于生成时间)
- 每个用户有独立的文件夹存储题目(文件夹名为用户名)
- 题目包含题号,每题之间空一行,便于阅读
## 使用说明
@ -45,11 +49,13 @@
### 生成题目
1. 登录成功后,系统提示输入题目数量
2. 输入10-30之间的数字生成对应数量的题目
3. 输入-1退出当前用户返回登录界面
3. 系统将显示生成的题目并保存到用户文件夹
4. 输入-1退出当前用户返回登录界面
### 切换难度
- 在任何提示输入题目数量的界面,输入`切换为 小学/初中/高中`即可切换题目难度
- 切换成功后,系统会提示新的难度级别
- 输入无效时,系统会提示错误信息并保持当前难度
## 账号列表
@ -67,7 +73,7 @@
## 项目结构
```
quesproject/
relentless1/
├── src/ # 源代码目录
│ ├── Main.java # 程序入口类
│ ├── User.java # 用户类
@ -81,26 +87,74 @@ quesproject/
│ └── FileUtils.java # 文件操作工具类
├── doc/ # 文档目录
│ └── README.md # 项目说明文档
── [用户名]/ # 用户题目文件夹(运行时自动创建)
── [用户名]/ # 用户题目文件夹(运行时自动创建)
```
## 技术实现
### 设计模式
- **工厂模式**通过QuestionStrategyFactory创建不同级别的题目生成策略
- **策略模式**通过QuestionStrategy接口及其实现类实现不同难度级别的题目生成
### 核心功能实现
1. **用户验证**:通过预设的账号列表进行验证
2. **题目生成**:根据不同难度级别使用不同的策略生成题目
3. **查重功能**:读取用户历史题目文件,确保新生成的题目不重复
4. **文件管理**:自动创建用户文件夹,按指定格式保存题目文件
- **策略模式**:通过`QuestionStrategy`接口定义题目生成策略,不同难度级别(小学、初中、高中)实现各自的题目生成算法
- **工厂模式**:通过`QuestionStrategyFactory`根据用户角色动态创建对应的题目生成策略对象
### 核心类功能
#### Main.java
- 程序入口,处理用户交互逻辑
- 实现登录流程、题目数量输入和难度切换功能
- 包含清屏方法,提升用户体验
#### User.java
- 表示用户实体,包含用户名、密码和角色属性
- 提供静态登录方法,验证用户凭据
- 用户信息硬编码在程序中每个角色有3个预设账号
#### QuestionGenerator.java
- 根据用户角色使用对应策略生成题目
- 实现题目查重逻辑,确保题目唯一性
- 协调策略选择、题目生成和文件保存
#### QuestionStrategy.java及其实现类
- `QuestionStrategy`:定义题目生成的接口
- `ElementaryQuestionStrategy`:实现小学题目的生成,包含加减乘除和括号
- `MiddleSchoolQuestionStrategy`:实现初中题目生成,增加平方和开根号运算
- `HighSchoolQuestionStrategy`:实现高中题目生成,增加三角函数运算
#### MathQuestion.java
- 表示单道数学题,包含题号和题目内容
#### FileUtils.java
- 提供文件操作工具方法
- 生成时间戳格式的文件名
- 保存题目到用户文件夹
- 加载用户历史题目进行查重
### 算法特点
1. **小学题目**:支持随机括号位置,确保数学表达式的多样性
2. **初中题目**
- 题目包含1-5个操作数
- 若只有1个操作数则必须是平方或根号表达式
- 有50%概率生成平方或根号操作数
- 确保每道题至少有一个平方或开根号运算
3. **高中题目**
- 题目包含1-5个操作数
- 若只有1个操作数则强制生成三角函数表达式
- 支持sin、cos、tan三种三角函数
- 确保每道题至少有一个三角函数
4. **查重机制**使用HashSet高效检测重复题目设置最大尝试次数避免死循环
## 运行环境
- Java 8及以上版本
- 支持Windows、Linux、macOS等操作系统
- 支持Windows和Linux操作系统清屏功能自适应
## 扩展建议
1. 添加自定义操作数范围和运算符的功能
2. 实现题目答案自动计算功能
3. 支持更多类型的数学表达式和运算符号
4. 添加图形用户界面,提升用户体验
5. 实现用户注册和密码修改功能
6. 支持题目导入导出功能
## 编译运行
## 编译运行
1. 编译:`javac -d out src/*.java`
2. 运行:`java -cp out Main`

@ -2,47 +2,89 @@ import java.util.Random;
/**
*
* <p>
*
*
* <p>
* 15 1 </p>
*/
public class HighSchoolQuestionStrategy implements QuestionStrategy {
/** 基本四则运算符。 */
private static final String[] BASIC_OPS = {"+", "-", "*", "/"};
/** 支持的三角函数。 */
private static final String[] TRIG_FUNCS = {"sin", "cos", "tan"};
/** 随机数生成器。 */
private final Random random = new Random();
/**
*
*
* @return
*/
@Override
public String generateQuestion() {
// 随机操作数个数2~5
int operandsCount = random.nextInt(4) + 2;
StringBuilder sb = new StringBuilder();
// 操作数个数1~5
int operandsCount = random.nextInt(5) + 1;
StringBuilder expression = new StringBuilder();
boolean hasTrig = false;
for (int i = 0; i < operandsCount; i++) {
int num = random.nextInt(100) + 1;
// 仅一个操作数时,强制生成一个三角函数表达式
if (operandsCount == 1) {
return buildTrigOperand();
}
// 每个操作数有概率带三角函数
if (random.nextBoolean()) {
String func = TRIG_FUNCS[random.nextInt(TRIG_FUNCS.length)];
sb.append(func).append("(").append(num).append(")");
// 生成多个操作数与运算符
for (int i = 0; i < operandsCount; i++) {
String operand = buildOperand();
expression.append(operand);
if (operand.matches(".*(sin|cos|tan).*")) {
hasTrig = true;
} else {
sb.append(num);
}
// 添加运算符(除最后一个操作数外)
if (i != operandsCount - 1) {
String op = BASIC_OPS[random.nextInt(BASIC_OPS.length)];
sb.append(" ").append(op).append(" ");
expression.append(' ')
.append(BASIC_OPS[random.nextInt(BASIC_OPS.length)])
.append(' ');
}
}
// 确保至少包含一个三角函数
if (!hasTrig) {
String func = TRIG_FUNCS[random.nextInt(TRIG_FUNCS.length)];
int num = random.nextInt(100) + 1;
return func + "(" + num + ") + " + sb;
expression.append(" + ").append(buildTrigOperand());
}
return expression.toString();
}
/**
*
*/
private String buildOperand() {
int num = random.nextInt(100) + 1;
if (random.nextBoolean()) {
return buildTrigOperandWithNumber(num);
}
return String.valueOf(num);
}
/**
*
*/
private String buildTrigOperand() {
int num = random.nextInt(100) + 1;
return buildTrigOperandWithNumber(num);
}
return sb.toString();
/**
*
*
* @param number 1~100
* @return sin(45)
*/
private String buildTrigOperandWithNumber(int number) {
String func = TRIG_FUNCS[random.nextInt(TRIG_FUNCS.length)];
return func + "(" + number + ")";
}
}

@ -1,50 +1,78 @@
import java.util.Random;
/**
*
*
* <p></p>
*/
public class MiddleSchoolQuestionStrategy implements QuestionStrategy {
private final Random random = new Random();
private final String[] basicOps = {"+", "-", "*", "/"};
/** 随机数生成器,生成操作数和运算符索引 */
private static final Random RANDOM = new Random();
/** 基本运算符集合 */
private static final String[] BASIC_OPS = {"+", "-", "*", "/"};
/**
*
* <p> 15 1 </p>
*
* @return
*/
@Override
public String generateQuestion() {
// 随机操作数个数 2-5。
int operandsCount = random.nextInt(4) + 2;
int operandsCount = RANDOM.nextInt(5) + 1; // 操作数个数 15
StringBuilder sb = new StringBuilder();
boolean hasSquareOrRoot = false;
// 生成运算符和操作数。
for (int i = 0; i < operandsCount; i++) {
int num = random.nextInt(100) + 1; // 生成 1-100 之间的数字。
// 每个操作数有概率平方或开根号。
if (random.nextBoolean()) {
if (random.nextBoolean()) {
sb.append("(").append(num).append(")^2");
hasSquareOrRoot = true;
} else {
// 确保根号下的数为正。
int rootNumber = random.nextInt(100) + 1;
sb.append("√(").append(rootNumber).append(")");
// 若只有一个操作数,则直接生成平方或根号表达式
if (operandsCount == 1) {
sb.append(generateSquareOrRoot());
} else {
// 多个操作数:依次生成操作数和运算符
for (int i = 0; i < operandsCount; i++) {
String operand = generateOperand();
sb.append(operand);
if (operand.contains("^2") || operand.contains("√")) {
hasSquareOrRoot = true;
}
} else {
sb.append(num);
}
// 添加运算符(除最后一个操作数外)。
if (i != operandsCount - 1) {
String op = basicOps[random.nextInt(basicOps.length)];
sb.append(" ").append(op).append(" ");
if (i != operandsCount - 1) {
sb.append(" ").append(BASIC_OPS[RANDOM.nextInt(4)]).append(" ");
}
}
}
// 如果没有平方或根号,强制添加一个。
// 如果多操作数情况下没有出现平方或根号,强制追加一个根号项
if (!hasSquareOrRoot) {
int rootNumber = random.nextInt(100) + 1;
sb.append(" + √(").append(rootNumber).append(")");
sb.append(" + ").append(generateSquareOrRoot());
}
return sb.toString();
}
/**
*
* <p> 50% 50% </p>
*
* @return
*/
private String generateOperand() {
int num = RANDOM.nextInt(100) + 1;
if (RANDOM.nextBoolean()) {
return RANDOM.nextBoolean()
? "(" + num + ")^2"
: "√(" + (RANDOM.nextInt(100) + 1) + ")";
}
return String.valueOf(num);
}
/**
*
*
* @return
*/
private String generateSquareOrRoot() {
return RANDOM.nextBoolean()
? "(" + (RANDOM.nextInt(100) + 1) + ")^2"
: "√(" + (RANDOM.nextInt(100) + 1) + ")";
}
}

Loading…
Cancel
Save