From 4f1b4341738e84319345fb8b98b49df27848098b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=B0=B8=E4=BD=B3?= Date: Sat, 27 Sep 2025 16:24:21 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=AC=AC=E4=B8=80=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 28 -- doc/Git使用说明.md | 172 --------- doc/README.md | 86 +++-- README.md => doc/README_root.md | 0 git_setup.bat | 63 ---- src/Makefile | 40 ++- src/app.cpp | 92 +++++ src/auth.cpp | 29 ++ src/exam.cpp | 152 ++++++++ src/include/app.hpp | 30 ++ src/include/auth.hpp | 27 ++ src/include/exam.hpp | 33 ++ src/include/login.hpp | 20 ++ src/include/utils.hpp | 25 ++ src/login.cpp | 38 ++ src/main.cpp | 415 +--------------------- src/math_exam_generator.exe | Bin 0 -> 173968 bytes src/paper/张三1/.history.txt | 30 ++ src/paper/张三1/2025-09-27-16-21-44.txt | 60 ++++ src/run.bat | 11 - src/run_utf8.bat | 12 - src/utils.cpp | 74 ++++ 22 files changed, 688 insertions(+), 749 deletions(-) delete mode 100644 .gitignore delete mode 100644 doc/Git使用说明.md rename README.md => doc/README_root.md (100%) delete mode 100644 git_setup.bat create mode 100644 src/app.cpp create mode 100644 src/auth.cpp create mode 100644 src/exam.cpp create mode 100644 src/include/app.hpp create mode 100644 src/include/auth.hpp create mode 100644 src/include/exam.hpp create mode 100644 src/include/login.hpp create mode 100644 src/include/utils.hpp create mode 100644 src/login.cpp create mode 100644 src/math_exam_generator.exe create mode 100644 src/paper/张三1/.history.txt create mode 100644 src/paper/张三1/2025-09-27-16-21-44.txt delete mode 100644 src/run.bat delete mode 100644 src/run_utf8.bat create mode 100644 src/utils.cpp diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 5fe5705..0000000 --- a/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -# 编译生成的可执行文件 -*.exe -*.out -*.o -*.obj - -# 临时文件 -*.tmp -*.temp -*~ - -# 系统文件 -.DS_Store -Thumbs.db - -# IDE文件 -.vscode/ -.idea/ -*.swp -*.swo - -# 生成的题目文件夹(用户数据) -xiaoxue*/ -chuzhong*/ -gaozhong*/ - -# 日志文件 -*.log \ No newline at end of file diff --git a/doc/Git使用说明.md b/doc/Git使用说明.md deleted file mode 100644 index 0852a92..0000000 --- a/doc/Git使用说明.md +++ /dev/null @@ -1,172 +0,0 @@ -# Git版本控制使用说明 - -## 项目Git结构 - -根据头歌平台要求,本项目采用以下分支结构: -- **master分支**:稳定版本,用于发布 -- **develop分支**:开发版本,用于日常开发 - -## 快速设置(推荐) - -### 方法一:使用自动化脚本 -1. 双击项目根目录下的 `git_setup.bat` 文件 -2. 按照提示输入Git用户名和邮箱 -3. 脚本会自动完成仓库初始化和分支创建 - -### 方法二:手动设置 -如果您熟悉Git命令,可以按照以下步骤手动设置: - -## 详细设置步骤 - -### 1. 检查Git安装 -```bash -git --version -``` -如果提示"git不是内部或外部命令",请先安装Git: -- 访问:https://git-scm.com/download/win -- 下载并安装Git for Windows - -### 2. 初始化仓库 -```bash -# 进入项目目录 -cd "e:\学习通\download\软件项目管理\软件2301班_沈永佳_个人项目" - -# 初始化Git仓库 -git init - -# 配置用户信息 -git config user.name "您的姓名" -git config user.email "您的邮箱" -``` - -### 3. 创建分支结构 -```bash -# 创建并切换到develop分支 -git checkout -b develop - -# 添加所有文件 -git add . - -# 提交初始版本 -git commit -m "初始提交:中小学数学卷子自动生成程序" - -# 创建master分支 -git checkout -b master - -# 合并develop分支到master -git merge develop --no-ff -m "合并develop分支到master(稳定版本)" - -# 切换回develop分支进行日常开发 -git checkout develop -``` - -## 连接头歌平台 - -### 1. 在头歌平台创建项目 -1. 登录头歌平台 -2. 创建新项目:`软件2301班_沈永佳_个人项目` -3. 复制项目的Git仓库地址 - -### 2. 添加远程仓库 -```bash -# 添加远程仓库(替换为实际的仓库地址) -git remote add origin https://git.educoder.net/your-username/软件2301班_沈永佳_个人项目.git - -# 推送master分支 -git push -u origin master - -# 推送develop分支 -git push -u origin develop -``` - -## 日常开发流程 - -### 开发新功能 -```bash -# 确保在develop分支 -git checkout develop - -# 拉取最新代码 -git pull origin develop - -# 修改代码后提交 -git add . -git commit -m "描述您的修改内容" - -# 推送到远程develop分支 -git push origin develop -``` - -### 发布稳定版本 -```bash -# 切换到master分支 -git checkout master - -# 合并develop分支的稳定功能 -git merge develop --no-ff -m "发布版本v1.x" - -# 推送到远程master分支 -git push origin master - -# 切换回develop分支继续开发 -git checkout develop -``` - -## 常用Git命令 - -| 命令 | 说明 | -|------|------| -| `git status` | 查看文件状态 | -| `git log --oneline` | 查看提交历史 | -| `git branch` | 查看分支列表 | -| `git checkout [分支名]` | 切换分支 | -| `git add .` | 添加所有修改的文件 | -| `git commit -m "消息"` | 提交修改 | -| `git push origin [分支名]` | 推送到远程分支 | -| `git pull origin [分支名]` | 拉取远程分支 | - -## 文件结构说明 - -``` -项目根目录/ -├── .git/ # Git版本控制目录 -├── .gitignore # Git忽略文件配置 -├── src/ # 源代码目录 -│ ├── main.cpp # 主程序文件 -│ ├── Makefile # 编译配置 -│ ├── run.bat # 运行脚本 -│ └── run_utf8.bat # UTF-8编码运行脚本 -├── doc/ # 文档目录 -│ ├── README.md # 项目说明 -│ └── Git使用说明.md # 本文档 -└── git_setup.bat # Git自动设置脚本 -``` - -## 注意事项 - -1. **编码问题**:确保使用UTF-8编码,避免中文乱码 -2. **分支管理**: - - develop分支用于日常开发 - - master分支只用于稳定版本发布 -3. **提交信息**:使用清晰的中文描述提交内容 -4. **文件忽略**:`.gitignore`已配置忽略编译文件和用户数据 - -## 故障排除 - -### 问题1:Git命令不识别 -**解决方案**:安装Git for Windows并重启命令行 - -### 问题2:中文文件名乱码 -**解决方案**: -```bash -git config --global core.quotepath false -``` - -### 问题3:推送失败 -**解决方案**:检查网络连接和仓库地址是否正确 - -## 联系方式 - -如有问题,请联系: -- 姓名:沈永佳 -- 班级:软件2301班 \ No newline at end of file diff --git a/doc/README.md b/doc/README.md index 553b8eb..3e00ed9 100644 --- a/doc/README.md +++ b/doc/README.md @@ -12,9 +12,9 @@ - 根据账户类型自动识别出题难度 ### 2. 智能题目生成 -- **小学题目**:2-3个操作数,数值范围1-50,支持加减法 -- **初中题目**:3-4个操作数,数值范围1-100,支持加减乘法 -- **高中题目**:4-5个操作数,数值范围1-100,支持加减乘除法 +- **小学题目**:2-3个操作数,数值范围1-50,支持加减乘除和括号运算 +- **初中题目**:3-4个操作数,数值范围1-100,支持加减乘除和括号运算,并能计算平方和开根号 +- **高中题目**:4-5个操作数,数值范围1-100,支持加减乘除和括号运算,并能计算平方和开根号,而且题目中至少有一个sin,cos或tan运算符 ### 3. 题目管理 - 自动避免同一教师生成重复题目 @@ -29,15 +29,15 @@ | 学段 | 用户名 | 密码 | |------|--------|------| -| 小学 | xiaoxue1 | 123456 | -| 小学 | xiaoxue2 | 123456 | -| 小学 | xiaoxue3 | 123456 | -| 初中 | chuzhong1 | 123456 | -| 初中 | chuzhong2 | 123456 | -| 初中 | chuzhong3 | 123456 | -| 高中 | gaozhong1 | 123456 | -| 高中 | gaozhong2 | 123456 | -| 高中 | gaozhong3 | 123456 | +| 小学 | 张三1 | 123 | +| 小学 | 张三2 | 123 | +| 小学 | 张三3 | 123 | +| 初中 | 李四1 | 123 | +| 初中 | 李四2 | 123 | +| 初中 | 李四3 | 123 | +| 高中 | 王五1 | 123 | +| 高中 | 王五2 | 123 | +| 高中 | 王五3 | 123 | ## 编译和运行 @@ -60,24 +60,9 @@ g++ -std=c++17 -Wall -Wextra -O2 -o math_exam_generator main.cpp ``` ### 运行程序 - -#### 方法一:使用UTF-8编码脚本(推荐,解决乱码问题) -```bash -cd src -run_utf8.bat -``` - -#### 方法二:手动设置编码后运行 ```bash cd src -chcp 65001 -math_exam_generator.exe -``` - -#### 方法三:直接运行(可能出现中文乱码) -```bash -cd src -math_exam_generator.exe +./math_exam_generator ``` ## 使用说明 @@ -85,7 +70,7 @@ math_exam_generator.exe ### 1. 登录 启动程序后,输入用户名和密码,用空格隔开: ``` -请输入用户名和密码(用空格隔开): xiaoxue1 123456 +请输入用户名和密码(用空格隔开): 张三1 123 ``` ### 2. 生成试卷 @@ -110,13 +95,28 @@ math_exam_generator.exe ``` 项目根目录/ -├── src/ # 源代码目录 -│ ├── main.cpp # 主程序文件 -│ └── Makefile # 编译配置文件 -├── doc/ # 文档目录 -│ └── README.md # 项目说明文档 -└── [用户名]/ # 自动生成的用户文件夹 - └── 年-月-日-时-分-秒.txt # 生成的试卷文件 +├── doc/ # 文档目录 +│ ├── README.md # 本项目的详细说明 +│ └── README_root.md # 根目录的README +└── src/ # 源代码目录 + ├── Makefile # 编译配置文件 + ├── app.cpp # 应用逻辑 + ├── auth.cpp # 用户认证模块 + ├── exam.cpp # 试卷生成模块 + ├── include/ # 头文件目录 + ├── login.cpp # 登录逻辑 + ├── main.cpp # 主程序入口 + ├── math_exam_generator.exe # 编译后的可执行文件 + └── utils.cpp # 工具函数 + +``` +*注:程序运行时,会在`src`目录下自动生成`paper`文件夹,用于存放用户生成的试卷。* + +``` +src/ +└── paper/ + └── [用户名]/ # 自动生成的用户文件夹 + └── 年-月-日-时-分-秒.txt # 生成的试卷文件 ``` ## 试卷格式示例 @@ -127,6 +127,18 @@ math_exam_generator.exe 2. 42 - 15 + 23 = ? 3. 8 + 17 - 9 + 14 = ? + +4. 36 * 4 - 20 = ? + +5. 16^2 - 4 = ? + +6. 2^3 - 1 = ? + +7. sin(30°) = ? + +8. cos(60°) = ? + +9. tan(45°) +2= ? ``` ## 技术特点 @@ -146,7 +158,7 @@ math_exam_generator.exe ## 版本控制 本项目使用Git进行版本控制: -- `master` 分支:稳定版本 +- `main` 分支:稳定版本 - `develop` 分支:开发版本 ## 作者 diff --git a/README.md b/doc/README_root.md similarity index 100% rename from README.md rename to doc/README_root.md diff --git a/git_setup.bat b/git_setup.bat deleted file mode 100644 index 787f3c2..0000000 --- a/git_setup.bat +++ /dev/null @@ -1,63 +0,0 @@ -@echo off -chcp 65001 >nul -echo ======================================== -echo 中小学数学卷子生成程序 Git 设置 -echo ======================================== -echo. - -echo 正在检查Git是否已安装... -git --version >nul 2>&1 -if %errorlevel% neq 0 ( - echo [错误] 未检测到Git,请先安装Git: - echo 1. 访问 https://git-scm.com/download/win - echo 2. 下载并安装Git for Windows - echo 3. 重新运行此脚本 - pause - exit /b 1 -) - -echo [成功] Git已安装 -echo. - -echo 正在初始化Git仓库... -git init -if %errorlevel% neq 0 ( - echo [错误] Git初始化失败 - pause - exit /b 1 -) - -echo 正在配置Git用户信息... -set /p username="请输入您的Git用户名: " -set /p email="请输入您的Git邮箱: " - -git config user.name "%username%" -git config user.email "%email%" - -echo. -echo 正在创建分支结构... -git checkout -b develop -git add . -git commit -m "初始提交:中小学数学卷子自动生成程序" - -echo 正在创建master分支... -git checkout -b master -git merge develop --no-ff -m "合并develop分支到master(稳定版本)" - -echo. -echo ======================================== -echo Git仓库设置完成! -echo. -echo 分支结构: -echo - master: 稳定版本 -echo - develop: 开发版本(当前分支) -echo. -echo 下一步: -echo 1. 在头歌平台创建项目仓库 -echo 2. 复制仓库地址 -echo 3. 运行以下命令添加远程仓库: -echo git remote add origin [仓库地址] -echo git push -u origin master -echo git push -u origin develop -echo ======================================== -pause \ No newline at end of file diff --git a/src/Makefile b/src/Makefile index 68ba534..e961a40 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,22 +1,28 @@ -# Makefile for Math Exam Generator -CXX = g++ -CXXFLAGS = -std=c++17 -Wall -Wextra -O2 -TARGET = math_exam_generator -SOURCE = main.cpp +# Simple Makefile for Math Exam Generator -# Default target -all: $(TARGET) +CXX ?= g++ +CXXFLAGS ?= -std=c++17 -Wall -Wextra -O2 -# Build target -$(TARGET): $(SOURCE) - $(CXX) $(CXXFLAGS) -o $(TARGET) $(SOURCE) +# Cross-platform remove command +ifeq ($(OS),Windows_NT) + RM := cmd /C del /Q +else + RM := rm -f +endif -# Clean target -clean: - rm -f $(TARGET) $(TARGET).exe +TARGET := math_exam_generator +SRCS := main.cpp app.cpp auth.cpp exam.cpp login.cpp utils.cpp +OBJS := $(SRCS:.cpp=.o) + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) $(CXXFLAGS) -o $@ $^ + -$(RM) $(OBJS) -# Run target -run: $(TARGET) - ./$(TARGET) +%.o: %.cpp + $(CXX) $(CXXFLAGS) -c $< -o $@ -.PHONY: all clean run \ No newline at end of file +.PHONY: clean +clean: + -$(RM) $(OBJS) $(TARGET) $(TARGET).exe \ No newline at end of file diff --git a/src/app.cpp b/src/app.cpp new file mode 100644 index 0000000..258b77d --- /dev/null +++ b/src/app.cpp @@ -0,0 +1,92 @@ +#include "include/app.hpp" +#include "include/utils.hpp" + +#include +#include +#include + +namespace fs = std::filesystem; + +namespace meg { + +App::App() {} + +void App::handle_logged_in() { + if (!current_user_) return; + current_level_ = current_user_->level; + + while (true) { + std::wcout << L"准备生成" << level_to_chinese(current_level_) << L"数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):"; + std::wcout.flush(); + std::wstring line; + if (!std::getline(std::wcin, line)) return; // EOF + line = trim(line); + if (line.empty()) continue; + + if (line == L"-1") { + std::wcout << L"已退出登录。" << std::endl; + current_user_.reset(); + return; + } + + // 支持命令:切换为小学/初中/高中 + if (starts_with(line, L"切换为")) { + std::wstring t = line.substr(3); + t = trim(t); + if (t == L"小学") current_level_ = Level::Primary; + else if (t == L"初中") current_level_ = Level::Middle; + else if (t == L"高中") current_level_ = Level::High; + else { + std::wcout << L"不支持的类型:" << t << std::endl; + continue; + } + std::wcout << L"已切换为" << level_to_chinese(current_level_) << L"。" << std::endl; + continue; + } + + // 尝试解析数量 + try { + int n = std::stoi(std::string(line.begin(), line.end())); + if (n < 10 || n > 30) { + std::wcout << L"请输入 10-30 之间的数字。" << std::endl; + continue; + } + + fs::path base = fs::path("paper") / current_user_->username; + fs::create_directories(base); + auto history_path = base / ".history.txt"; + auto history = exam_.load_history(history_path); + auto questions = exam_.generate_unique(current_level_, n, history); + // 保存试卷 + std::string ts = now_timestamp_str(); + fs::path outfile = base / (ts + ".txt"); + std::ofstream fout(outfile); + for (size_t i = 0; i < questions.size(); ++i) { + fout << (i + 1) << ". " << questions[i] << "\n\n"; + } + fout.close(); + exam_.append_history(history_path, questions); + + std::wcout << L"已生成试卷:" << outfile.wstring() << std::endl; + } catch (...) { + std::wcout << L"请输入正确的数字,或使用指令如:切换为初中。" << std::endl; + } + } +} + +void App::run() { + init_console_locale(); + std::wcout << L"中小学数学卷子自动生成程序" << std::endl; + while (true) { + if (!current_user_) { + auto u = login_.prompt_login(); + if (!u) return; // EOF 退出 + current_user_ = u; + current_level_ = current_user_->level; + } else { + handle_logged_in(); + } + } +} + +} // namespace meg \ No newline at end of file diff --git a/src/auth.cpp b/src/auth.cpp new file mode 100644 index 0000000..02774e9 --- /dev/null +++ b/src/auth.cpp @@ -0,0 +1,29 @@ +#include "include/auth.hpp" + +namespace meg { + +Auth::Auth() { + // 小学 张三1..3 + users_[L"张三1"] = {L"123", Level::Primary}; + users_[L"张三2"] = {L"123", Level::Primary}; + users_[L"张三3"] = {L"123", Level::Primary}; + + // 初中 李四1..3 + users_[L"李四1"] = {L"123", Level::Middle}; + users_[L"李四2"] = {L"123", Level::Middle}; + users_[L"李四3"] = {L"123", Level::Middle}; + + // 高中 王五1..3 + users_[L"王五1"] = {L"123", Level::High}; + users_[L"王五2"] = {L"123", Level::High}; + users_[L"王五3"] = {L"123", Level::High}; +} + +std::optional Auth::authenticate(const std::wstring& username, const std::wstring& password) const { + auto it = users_.find(username); + if (it == users_.end()) return std::nullopt; + if (it->second.first != password) return std::nullopt; + return User{username, password, it->second.second}; +} + +} // namespace meg \ No newline at end of file diff --git a/src/exam.cpp b/src/exam.cpp new file mode 100644 index 0000000..d22a57f --- /dev/null +++ b/src/exam.cpp @@ -0,0 +1,152 @@ +#include "include/exam.hpp" + +#include +#include +#include + +namespace meg { + +static int rand_int(std::mt19937& rng, int lo, int hi) { + std::uniform_int_distribution dist(lo, hi); + return dist(rng); +} + +ExamGenerator::ExamGenerator() { + std::random_device rd; + rng_ = std::mt19937(rd()); +} + +std::unordered_set ExamGenerator::load_history(const std::filesystem::path& history_path) { + std::unordered_set s; + std::ifstream fin(history_path); + std::string line; + while (std::getline(fin, line)) { + if (!line.empty()) s.insert(line); + } + return s; +} + +void ExamGenerator::append_history(const std::filesystem::path& history_path, const std::vector& qs) { + std::ofstream fout(history_path, std::ios::app); + for (auto& q : qs) { + fout << q << '\n'; + } +} + +std::vector ExamGenerator::generate_unique(Level level, int count, std::unordered_set& history) { + std::vector out; + int attempts = 0; + while ((int)out.size() < count && attempts < count * 50) { + std::string q; + if (level == Level::Primary) q = gen_primary(); + else if (level == Level::Middle) q = gen_middle(); + else q = gen_high(); + + if (history.insert(q).second) { + out.push_back(q); + } + ++attempts; + } + return out; +} + +static std::string join_ops(const std::vector& nums, const std::vector& ops) { + std::string s; + for (size_t i = 0; i < nums.size(); ++i) { + s += std::to_string(nums[i]); + if (i < ops.size()) { + s += ' '; + s += ops[i]; + s += ' '; + } + } + return s; +} + +std::string ExamGenerator::gen_primary() { + int n_ops = rand_int(rng_, 1, 2); // 2-3个操作数 => 1-2个操作符 + std::vector nums; + for (int i = 0; i < n_ops + 1; ++i) nums.push_back(rand_int(rng_, 1, 50)); + static const char all_ops[] = {'+', '-', '*', '/'}; + std::vector ops; + for (int i = 0; i < n_ops; ++i) ops.push_back(all_ops[rand_int(rng_, 0, 3)]); + std::string expr = join_ops(nums, ops); + // 适度加括号 + if (nums.size() >= 3 && rand_int(rng_, 0, 1)) { + size_t pos = expr.find(' '); + if (pos != std::string::npos) { + expr = "(" + expr.substr(0, pos) + ")" + expr.substr(pos); + } + } + return expr + " = ?"; +} + +std::string ExamGenerator::gen_middle() { + int n_ops = rand_int(rng_, 2, 3); // 3-4 操作数 + std::vector nums; + for (int i = 0; i < n_ops + 1; ++i) nums.push_back(rand_int(rng_, 1, 100)); + static const char all_ops[] = {'+', '-', '*', '/'}; + std::vector ops; + for (int i = 0; i < n_ops; ++i) ops.push_back(all_ops[rand_int(rng_, 0, 3)]); + + // 随机把一个数变成平方或开方 + int idx = rand_int(rng_, 0, (int)nums.size() - 1); + bool use_sqrt = rand_int(rng_, 0, 1) == 1; + std::string expr = join_ops(nums, ops); + + // 找到替换位置(简单方式:直接重新拼接) + std::string s; + for (size_t i = 0; i < nums.size(); ++i) { + std::string term = std::to_string(nums[i]); + if ((int)i == idx) { + if (use_sqrt) term = "sqrt(" + term + ")"; // 开根号 + else term = term + "^2"; // 平方 + } + s += term; + if (i < ops.size()) { + s += ' '; s += ops[i]; s += ' '; + } + } + return s + " = ?"; +} + +std::string ExamGenerator::gen_high() { + int n_ops = rand_int(rng_, 3, 4); // 4-5 操作数 + std::vector nums; + for (int i = 0; i < n_ops + 1; ++i) nums.push_back(rand_int(rng_, 1, 100)); + static const char all_ops[] = {'+', '-', '*', '/'}; + std::vector ops; + for (int i = 0; i < n_ops; ++i) ops.push_back(all_ops[rand_int(rng_, 0, 3)]); + + // 先基础表达式 + std::string base; + for (size_t i = 0; i < nums.size(); ++i) { + base += std::to_string(nums[i]); + if (i < ops.size()) { base += ' '; base += ops[i]; base += ' '; } + } + + // 至少一个三角函数,角度用 30/45/60/90 之一,使用 "deg" 标识角度 + static const char* funcs[] = {"sin", "cos", "tan"}; + static const int angles[] = {30, 45, 60, 90}; + std::string tri = std::string(funcs[rand_int(rng_, 0, 2)]) + "(" + std::to_string(angles[rand_int(rng_, 0, 3)]) + "deg)"; + + // 随机把一个数替换为三角项 + size_t replace_pos = rand_int(rng_, 0, (int)nums.size() - 1); + // 重建字符串并替换 + std::string s; + for (size_t i = 0; i < nums.size(); ++i) { + std::string term = (i == replace_pos) ? tri : std::to_string(nums[i]); + s += term; + if (i < ops.size()) { s += ' '; s += ops[i]; s += ' '; } + } + + // 同时可能再加平方或开方 + if (rand_int(rng_, 0, 1)) { + s = "(" + s + ")^2"; + } else if (rand_int(rng_, 0, 1)) { + s = "sqrt(" + s + ")"; + } + return s + " = ?"; +} + +} // namespace meg \ No newline at end of file diff --git a/src/include/app.hpp b/src/include/app.hpp new file mode 100644 index 0000000..4aca3dd --- /dev/null +++ b/src/include/app.hpp @@ -0,0 +1,30 @@ +#ifndef MEG_APP_HPP +#define MEG_APP_HPP + +#include +#include +#include "auth.hpp" +#include "login.hpp" +#include "exam.hpp" + +namespace meg { + +class App { +public: + App(); + void run(); + +private: + Auth auth_; + LoginManager login_{auth_}; + ExamGenerator exam_; + + std::optional current_user_; + Level current_level_ = Level::Primary; + + void handle_logged_in(); +}; + +} // namespace meg + +#endif // MEG_APP_HPP \ No newline at end of file diff --git a/src/include/auth.hpp b/src/include/auth.hpp new file mode 100644 index 0000000..3a2f4a9 --- /dev/null +++ b/src/include/auth.hpp @@ -0,0 +1,27 @@ +#ifndef MEG_AUTH_HPP +#define MEG_AUTH_HPP + +#include +#include +#include +#include "utils.hpp" + +namespace meg { + +struct User { + std::wstring username; + std::wstring password; + Level level; +}; + +class Auth { +public: + Auth(); + std::optional authenticate(const std::wstring& username, const std::wstring& password) const; +private: + std::map> users_; +}; + +} // namespace meg + +#endif // MEG_AUTH_HPP \ No newline at end of file diff --git a/src/include/exam.hpp b/src/include/exam.hpp new file mode 100644 index 0000000..1e1cb60 --- /dev/null +++ b/src/include/exam.hpp @@ -0,0 +1,33 @@ +#ifndef MEG_EXAM_HPP +#define MEG_EXAM_HPP + +#include +#include +#include +#include +#include +#include "utils.hpp" + +namespace meg { + +class ExamGenerator { +public: + ExamGenerator(); + // 加载/保存历史,防止同教师重复题目 + std::unordered_set load_history(const std::filesystem::path& history_path); + void append_history(const std::filesystem::path& history_path, const std::vector& qs); + + // 生成不重复题目 + std::vector generate_unique(Level level, int count, std::unordered_set& history); + +private: + std::mt19937 rng_; + + std::string gen_primary(); + std::string gen_middle(); + std::string gen_high(); +}; + +} // namespace meg + +#endif // MEG_EXAM_HPP \ No newline at end of file diff --git a/src/include/login.hpp b/src/include/login.hpp new file mode 100644 index 0000000..e6551e6 --- /dev/null +++ b/src/include/login.hpp @@ -0,0 +1,20 @@ +#ifndef MEG_LOGIN_HPP +#define MEG_LOGIN_HPP + +#include +#include +#include "auth.hpp" + +namespace meg { + +class LoginManager { +public: + explicit LoginManager(const Auth& auth) : auth_(auth) {} + std::optional prompt_login(); +private: + const Auth& auth_; +}; + +} // namespace meg + +#endif // MEG_LOGIN_HPP \ No newline at end of file diff --git a/src/include/utils.hpp b/src/include/utils.hpp new file mode 100644 index 0000000..48269e0 --- /dev/null +++ b/src/include/utils.hpp @@ -0,0 +1,25 @@ +#ifndef MEG_UTILS_HPP +#define MEG_UTILS_HPP + +#include +#include + +namespace meg { + +enum class Level { Primary, Middle, High }; + +std::wstring level_to_chinese(Level level); + +// 初始化控制台本地化,解决中文输入/输出问题 +void init_console_locale(); + +// 生成时间戳:YYYY-MM-DD-HH-MM-SS +std::string now_timestamp_str(); + +// 字符串工具 +bool starts_with(const std::wstring& s, const std::wstring& prefix); +std::wstring trim(const std::wstring& s); + +} // namespace meg + +#endif // MEG_UTILS_HPP \ No newline at end of file diff --git a/src/login.cpp b/src/login.cpp new file mode 100644 index 0000000..729632e --- /dev/null +++ b/src/login.cpp @@ -0,0 +1,38 @@ +#include "include/login.hpp" +#include "include/utils.hpp" + +#include +#include + +namespace meg { + +std::optional LoginManager::prompt_login() { + while (true) { + std::wcout << L"请输入用户名和密码(用空格隔开): "; + std::wcout.flush(); + std::wstring line; + if (!std::getline(std::wcin, line)) { + return std::nullopt; + } + line = trim(line); + if (line.empty()) continue; + + // 拆分为两段:用户名 密码 + std::wistringstream iss(line); + std::wstring u, p; + iss >> u >> p; + if (u.empty() || p.empty()) { + std::wcout << L"输入格式不正确,请重新输入。" << std::endl; + continue; + } + auto user = auth_.authenticate(u, p); + if (user) { + std::wcout << L"登录成功,欢迎您," << u << L"!" << std::endl; + return user; + } else { + std::wcout << L"用户名或密码错误,请重试。" << std::endl; + } + } +} + +} // namespace meg \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 9443107..2bd9c39 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,410 +1,7 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#include -#include -#include -#endif - -using namespace std; -namespace fs = std::filesystem; - -// 用户账号结构 -struct User { - string username; - string password; - string type; // "小学", "初中", "高中" -}; - -// 数学题目结构 -struct MathQuestion { - string question; - int answer; - - bool operator<(const MathQuestion& other) const { - return question < other.question; - } -}; - -class MathExamGenerator { -private: - vector users; - User currentUser; - bool isLoggedIn; - string currentType; - random_device rd; - mt19937 gen; - - // 存储已生成的题目,避免重复 - map> generatedQuestions; - -public: - MathExamGenerator() : gen(rd()), isLoggedIn(false) { - initializeUsers(); - loadExistingQuestions(); - } - - // 初始化预设账号 - void initializeUsers() { - // 小学账号 - users.push_back({"xiaoxue1", "123456", "小学"}); - users.push_back({"xiaoxue2", "123456", "小学"}); - users.push_back({"xiaoxue3", "123456", "小学"}); - - // 初中账号 - users.push_back({"chuzhong1", "123456", "初中"}); - users.push_back({"chuzhong2", "123456", "初中"}); - users.push_back({"chuzhong3", "123456", "初中"}); - - // 高中账号 - users.push_back({"gaozhong1", "123456", "高中"}); - users.push_back({"gaozhong2", "123456", "高中"}); - users.push_back({"gaozhong3", "123456", "高中"}); - } - - // 加载已存在的题目 - void loadExistingQuestions() { - for (const auto& user : users) { - string folderPath = user.username; - if (fs::exists(folderPath)) { - for (const auto& entry : fs::directory_iterator(folderPath)) { - if (entry.is_regular_file() && entry.path().extension() == ".txt") { - loadQuestionsFromFile(entry.path().string(), user.username); - } - } - } - } - } - - // 从文件加载题目 - void loadQuestionsFromFile(const string& filename, const string& username) { - ifstream file(filename); - string line; - while (getline(file, line)) { - if (!line.empty() && line.find('.') != string::npos) { - // 提取题目部分(去掉题号) - size_t dotPos = line.find('.'); - if (dotPos != string::npos && dotPos + 1 < line.length()) { - string question = line.substr(dotPos + 1); - // 去掉前后空格 - question.erase(0, question.find_first_not_of(" \t")); - question.erase(question.find_last_not_of(" \t") + 1); - - MathQuestion mq; - mq.question = question; - mq.answer = 0; // 这里简化处理 - generatedQuestions[username].insert(mq); - } - } - } - file.close(); - } - - // 用户登录 - bool login(const string& username, const string& password) { - for (const auto& user : users) { - if (user.username == username && user.password == password) { - currentUser = user; - currentType = user.type; - isLoggedIn = true; - cout << "当前选择为" << currentType << "出题" << endl; - return true; - } - } - return false; - } - - // 生成小学数学题 - MathQuestion generatePrimaryQuestion() { - uniform_int_distribution<> opCount(2, 3); // 操作数2-3个 - uniform_int_distribution<> numDist(1, 50); // 数值范围1-50 - uniform_int_distribution<> opDist(0, 1); // 0:加法, 1:减法 - - int operandCount = opCount(gen); - vector numbers; - vector operators; - - for (int i = 0; i < operandCount; i++) { - numbers.push_back(numDist(gen)); - } - - for (int i = 0; i < operandCount - 1; i++) { - operators.push_back(opDist(gen) == 0 ? '+' : '-'); - } - - // 构建题目字符串 - stringstream ss; - ss << numbers[0]; - int result = numbers[0]; - - for (int i = 0; i < operators.size(); i++) { - ss << " " << operators[i] << " " << numbers[i + 1]; - if (operators[i] == '+') { - result += numbers[i + 1]; - } else { - result -= numbers[i + 1]; - } - } - - // 确保结果为正数 - if (result < 0) { - return generatePrimaryQuestion(); - } - - ss << " = ?"; - - MathQuestion question; - question.question = ss.str(); - question.answer = result; - - return question; - } - - // 生成初中数学题 - MathQuestion generateMiddleQuestion() { - uniform_int_distribution<> opCount(3, 4); // 操作数3-4个 - uniform_int_distribution<> numDist(1, 100); // 数值范围1-100 - uniform_int_distribution<> opDist(0, 2); // 0:加法, 1:减法, 2:乘法 - - int operandCount = opCount(gen); - vector numbers; - vector operators; - - for (int i = 0; i < operandCount; i++) { - numbers.push_back(numDist(gen)); - } - - for (int i = 0; i < operandCount - 1; i++) { - int op = opDist(gen); - if (op == 0) operators.push_back('+'); - else if (op == 1) operators.push_back('-'); - else operators.push_back('*'); - } - - // 构建题目字符串 - stringstream ss; - ss << numbers[0]; - int result = numbers[0]; - - for (int i = 0; i < operators.size(); i++) { - ss << " " << operators[i] << " " << numbers[i + 1]; - if (operators[i] == '+') { - result += numbers[i + 1]; - } else if (operators[i] == '-') { - result -= numbers[i + 1]; - } else { - result *= numbers[i + 1]; - } - } - - ss << " = ?"; - - MathQuestion question; - question.question = ss.str(); - question.answer = result; - - return question; - } - - // 生成高中数学题 - MathQuestion generateHighQuestion() { - uniform_int_distribution<> opCount(4, 5); // 操作数4-5个 - uniform_int_distribution<> numDist(1, 100); // 数值范围1-100 - uniform_int_distribution<> opDist(0, 3); // 0:加法, 1:减法, 2:乘法, 3:除法 - - int operandCount = opCount(gen); - vector numbers; - vector operators; - - for (int i = 0; i < operandCount; i++) { - numbers.push_back(numDist(gen)); - } - - for (int i = 0; i < operandCount - 1; i++) { - int op = opDist(gen); - if (op == 0) operators.push_back('+'); - else if (op == 1) operators.push_back('-'); - else if (op == 2) operators.push_back('*'); - else { - operators.push_back('/'); - // 确保除法结果为整数 - numbers[i + 1] = numbers[i] % numbers[i + 1] == 0 ? numbers[i + 1] : - (numbers[i] / numbers[i + 1] + 1); - } - } - - // 构建题目字符串 - stringstream ss; - ss << numbers[0]; - double result = numbers[0]; - - for (int i = 0; i < operators.size(); i++) { - ss << " " << operators[i] << " " << numbers[i + 1]; - if (operators[i] == '+') { - result += numbers[i + 1]; - } else if (operators[i] == '-') { - result -= numbers[i + 1]; - } else if (operators[i] == '*') { - result *= numbers[i + 1]; - } else { - if (numbers[i + 1] != 0) { - result /= numbers[i + 1]; - } - } - } - - ss << " = ?"; - - MathQuestion question; - question.question = ss.str(); - question.answer = (int)result; - - return question; - } - - // 根据类型生成题目 - MathQuestion generateQuestion(const string& type) { - if (type == "小学") { - return generatePrimaryQuestion(); - } else if (type == "初中") { - return generateMiddleQuestion(); - } else { - return generateHighQuestion(); - } - } - - // 检查题目是否重复 - bool isQuestionDuplicate(const MathQuestion& question) { - return generatedQuestions[currentUser.username].count(question) > 0; - } - - // 生成试卷 - void generateExam(int questionCount) { - vector questions; - - // 生成不重复的题目 - while (questions.size() < questionCount) { - MathQuestion question = generateQuestion(currentType); - if (!isQuestionDuplicate(question)) { - questions.push_back(question); - generatedQuestions[currentUser.username].insert(question); - } - } - - // 创建用户文件夹 - string folderPath = currentUser.username; - if (!fs::exists(folderPath)) { - fs::create_directory(folderPath); - } - - // 生成文件名(年-月-日-时-分-秒.txt) - auto now = chrono::system_clock::now(); - auto time_t = chrono::system_clock::to_time_t(now); - auto tm = *localtime(&time_t); - - stringstream filename; - filename << folderPath << "/" - << put_time(&tm, "%Y-%m-%d-%H-%M-%S") << ".txt"; - - // 写入文件 - ofstream file(filename.str()); - for (int i = 0; i < questions.size(); i++) { - file << (i + 1) << ". " << questions[i].question << endl; - if (i < questions.size() - 1) { - file << endl; // 题目之间空一行 - } - } - file.close(); - - cout << "试卷已生成并保存到: " << filename.str() << endl; - } - - // 切换类型 - bool switchType(const string& newType) { - if (newType == "小学" || newType == "初中" || newType == "高中") { - currentType = newType; - return true; - } - return false; - } - - // 主运行循环 - void run() { - cout << "=== 中小学数学卷子自动生成程序 ===" << endl; - - while (true) { - if (!isLoggedIn) { - cout << "请输入用户名和密码(用空格隔开): "; - string username, password; - cin >> username >> password; - - if (login(username, password)) { - continue; - } else { - cout << "请输入正确的用户名、密码" << endl; - continue; - } - } - - cout << "准备生成" << currentType << "数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):"; - string input; - cin >> input; - - // 检查是否是切换命令 - if (input.find("切换为") == 0) { - string newType = input.substr(3); // 去掉"切换为" - if (switchType(newType)) { - cout << "准备生成" << currentType << "数学题目,请输入生成题目数量:"; - continue; - } else { - cout << "请输入小学、初中和高中三个选项中的一个" << endl; - continue; - } - } - - try { - int count = stoi(input); - - if (count == -1) { - isLoggedIn = false; - cout << "已退出登录" << endl; - continue; - } - - if (count >= 10 && count <= 30) { - generateExam(count); - } else { - cout << "题目数量必须在10-30之间" << endl; - } - } catch (const exception& e) { - cout << "请输入有效的数字" << endl; - } - } - } -}; - -int main() { -#ifdef _WIN32 - // 设置控制台编码为UTF-8,解决中文乱码问题 - SetConsoleOutputCP(CP_UTF8); - SetConsoleCP(CP_UTF8); - - // 设置locale为中文 - setlocale(LC_ALL, "zh_CN.UTF-8"); -#endif - - MathExamGenerator generator; - generator.run(); - return 0; +#include "include/app.hpp" + +int main() { + meg::App app; + app.run(); + return 0; } \ No newline at end of file diff --git a/src/math_exam_generator.exe b/src/math_exam_generator.exe new file mode 100644 index 0000000000000000000000000000000000000000..e86f2d6246993690304595aa69edb0d8c343206a GIT binary patch literal 173968 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 literal 0 HcmV?d00001 diff --git a/src/paper/张三1/.history.txt b/src/paper/张三1/.history.txt new file mode 100644 index 0000000..f83fd24 --- /dev/null +++ b/src/paper/张三1/.history.txt @@ -0,0 +1,30 @@ +40 + 31 * 38 = ? +46 * 6 = ? +(8) - 32 / 31 = ? +36 + 20 + 17 = ? +(7) + 14 / 39 = ? +(19) - 24 * 20 = ? +(13) - 27 * 43 = ? +43 / 17 - 39 = ? +17 - 43 = ? +9 / 30 = ? +48 / 31 = ? +17 - 24 = ? +(3) - 23 * 30 = ? +26 / 38 = ? +(48) / 46 * 33 = ? +11 * 7 = ? +(47) / 17 * 31 = ? +36 * 10 / 14 = ? +47 * 23 / 32 = ? +(29) - 14 * 33 = ? +33 * 46 + 38 = ? +(4) * 11 * 9 = ? +(39) / 36 - 36 = ? +25 - 4 = ? +12 - 8 = ? +39 - 32 = ? +13 / 25 = ? +40 - 43 = ? +(48) + 44 + 28 = ? +(12) / 9 + 44 = ? diff --git a/src/paper/张三1/2025-09-27-16-21-44.txt b/src/paper/张三1/2025-09-27-16-21-44.txt new file mode 100644 index 0000000..48699e3 --- /dev/null +++ b/src/paper/张三1/2025-09-27-16-21-44.txt @@ -0,0 +1,60 @@ +1. 40 + 31 * 38 = ? + +2. 46 * 6 = ? + +3. (8) - 32 / 31 = ? + +4. 36 + 20 + 17 = ? + +5. (7) + 14 / 39 = ? + +6. (19) - 24 * 20 = ? + +7. (13) - 27 * 43 = ? + +8. 43 / 17 - 39 = ? + +9. 17 - 43 = ? + +10. 9 / 30 = ? + +11. 48 / 31 = ? + +12. 17 - 24 = ? + +13. (3) - 23 * 30 = ? + +14. 26 / 38 = ? + +15. (48) / 46 * 33 = ? + +16. 11 * 7 = ? + +17. (47) / 17 * 31 = ? + +18. 36 * 10 / 14 = ? + +19. 47 * 23 / 32 = ? + +20. (29) - 14 * 33 = ? + +21. 33 * 46 + 38 = ? + +22. (4) * 11 * 9 = ? + +23. (39) / 36 - 36 = ? + +24. 25 - 4 = ? + +25. 12 - 8 = ? + +26. 39 - 32 = ? + +27. 13 / 25 = ? + +28. 40 - 43 = ? + +29. (48) + 44 + 28 = ? + +30. (12) / 9 + 44 = ? + diff --git a/src/run.bat b/src/run.bat deleted file mode 100644 index df72c47..0000000 --- a/src/run.bat +++ /dev/null @@ -1,11 +0,0 @@ -@echo off -echo 正在编译程序... -g++ -std=c++17 -Wall -Wextra -O2 -o math_exam_generator.exe main.cpp -if %errorlevel% equ 0 ( - echo 编译成功!正在启动程序... - echo. - math_exam_generator.exe -) else ( - echo 编译失败! - pause -) \ No newline at end of file diff --git a/src/run_utf8.bat b/src/run_utf8.bat deleted file mode 100644 index 5699628..0000000 --- a/src/run_utf8.bat +++ /dev/null @@ -1,12 +0,0 @@ -@echo off -chcp 65001 >nul -echo 正在编译程序... -g++ -std=c++17 -Wall -Wextra -O2 -o math_exam_generator.exe main.cpp -if %errorlevel% equ 0 ( - echo 编译成功!正在启动程序... - echo. - math_exam_generator.exe -) else ( - echo 编译失败! - pause -) \ No newline at end of file diff --git a/src/utils.cpp b/src/utils.cpp new file mode 100644 index 0000000..fd10f3b --- /dev/null +++ b/src/utils.cpp @@ -0,0 +1,74 @@ +#include "include/utils.hpp" + +#include +#include +#include +#include +#include + +#ifdef _WIN32 +# include +# include +#endif + +namespace meg { + +std::wstring level_to_chinese(Level level) { + switch (level) { + case Level::Primary: return L"小学"; + case Level::Middle: return L"初中"; + case Level::High: return L"高中"; + } + return L"小学"; +} + +void init_console_locale() { +#ifdef _WIN32 + _setmode(_fileno(stdout), _O_U16TEXT); + _setmode(_fileno(stdin), _O_U16TEXT); + _setmode(_fileno(stderr), _O_U16TEXT); +#else + try { + std::locale loc(""); + std::locale::global(loc); + std::wcout.imbue(loc); + std::wcin.imbue(loc); + std::wcerr.imbue(loc); + } catch (...) { + // 忽略本地化设置失败 + } +#endif +} + +std::string now_timestamp_str() { + using namespace std::chrono; + auto now = system_clock::now(); + std::time_t t = system_clock::to_time_t(now); + std::tm tm{}; +#ifdef _WIN32 + localtime_s(&tm, &t); +#else + localtime_r(&t, &tm); +#endif + std::ostringstream oss; + oss << std::put_time(&tm, "%Y-%m-%d-%H-%M-%S"); + return oss.str(); +} + +bool starts_with(const std::wstring& s, const std::wstring& prefix) { + if (prefix.size() > s.size()) return false; + return std::equal(prefix.begin(), prefix.end(), s.begin()); +} + +static inline bool is_space(wchar_t c) { + return c == L' ' || c == L'\t' || c == L'\n' || c == L'\r' || c == L'\f' || c == L'\v'; +} + +std::wstring trim(const std::wstring& s) { + size_t b = 0, e = s.size(); + while (b < e && is_space(s[b])) ++b; + while (e > b && is_space(s[e-1])) --e; + return s.substr(b, e - b); +} + +} // namespace meg \ No newline at end of file -- 2.34.1