中小学数学试卷自动分发程序 #1

Merged
hnu202326010327 merged 4 commits from develop into main 4 months ago

@ -1,2 +0,0 @@
# personal_program

@ -0,0 +1,22 @@
**中小学数学卷子自动生成程序**
运行系统
- 基于 x64 的 Windows 11, version 24H2 (KB5064401)
运行窗口
- 基于 Windows 的 PowerShell
编码语言版本
- Python 3.8.0
中文编码格式
- UTF-8
账户信息
- 张三、李四、王二各有三个账号。示例张三1张三2张三3。
- 所有账户的初始密码均为 123。
操作说明
- 登陆后switch 可选择出题年级
- -1 退出账号
- quit 退出系统

@ -0,0 +1,8 @@
{
"python.linting.flake8Enabled": true,
"python.formatting.provider": "yapf",
"python.linting.flake8Args": ["--max-line-length=248"],
"python.linting.pylintEnabled": false,
"python-envs.defaultEnvManager": "ms-python.python:system",
"python-envs.pythonProjects": []
}

Binary file not shown.

@ -0,0 +1,275 @@
import os
import random
import re
from datetime import datetime
from typing import List, Set, Dict, Optional
class MathPaperGenerator:
def __init__(self):
# 预设用户账号
self.users = {
'primary': [
{'username': '张三1', 'password': '123', 'type': '小学'},
{'username': '张三2', 'password': '123', 'type': '小学'},
{'username': '张三3', 'password': '123', 'type': '小学'}
],
'middle': [
{'username': '李四1', 'password': '123', 'type': '初中'},
{'username': '李四2', 'password': '123', 'type': '初中'},
{'username': '李四3', 'password': '123', 'type': '初中'}
],
'high': [
{'username': '王五1', 'password': '123', 'type': '高中'},
{'username': '王五2', 'password': '123', 'type': '高中'},
{'username': '王五3', 'password': '123', 'type': '高中'}
]
}
self.current_user: Optional[Dict] = None
self.current_type: Optional[str] = None
self.base_dir = "数学试卷"
# 创建基础目录
if not os.path.exists(self.base_dir):
os.makedirs(self.base_dir)
def authenticate(self, username: str, password: str) -> Optional[Dict]:
"""用户认证"""
for user_type, user_list in self.users.items():
for user in user_list:
if user['username'] == username and user['password'] == password:
return user
return None
def get_user_folder(self, username: str) -> str:
"""获取用户专属文件夹路径"""
user_folder = os.path.join(self.base_dir, username)
if not os.path.exists(user_folder):
os.makedirs(user_folder)
return user_folder
def get_all_existing_questions(self, username: str) -> Set[str]:
"""获取该用户所有已生成的题目"""
user_folder = self.get_user_folder(username)
all_questions = set()
if not os.path.exists(user_folder):
return all_questions
for filename in os.listdir(user_folder):
if filename.endswith('.txt'):
filepath = os.path.join(user_folder, filename)
try:
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
# 提取所有题目(去除题号)
questions = re.findall(r'\d+\.\s*(.+?)(?=\n\d+\.|\n\n|$)', content, re.DOTALL)
all_questions.update(question.strip() for question in questions)
except Exception as e:
print(f"读取文件 {filename} 时出错: {e}")
return all_questions
def generate_primary_question(self) -> str:
"""生成小学题目:加减乘除"""
operators = ['+', '-', '×', '÷']
num_operands = random.randint(2, 5) # 2-5个操作数
operands = [random.randint(1, 100) for _ in range(num_operands)]
ops = [random.choice(operators) for _ in range(num_operands - 1)]
# 构建表达式
expression = str(operands[0])
for i in range(num_operands - 1):
expression += f" {ops[i]} {operands[i+1]}"
return expression
def generate_middle_question(self) -> str:
"""生成初中题目:包含平方、开方、括号"""
if random.random() < 0.5:
# 基础四则运算带括号
a, b, c = random.randint(1, 100), random.randint(1, 100), random.randint(1, 100)
ops = ['+', '-', '×']
op = random.choice(ops)
return f"({a} {op} {b}) × {c}"
else:
# 平方或开方运算
num = random.randint(1, 20)
if random.random() < 0.5:
return f"{num}² + {random.randint(1, 100)}"
else:
return f"{num**2} × {random.randint(1, 50)}"
def generate_high_question(self) -> str:
"""生成高中题目:包含三角函数、乘方等"""
trig_functions = ['sin', 'cos', 'tan']
num = random.randint(1, 90)
choice = random.randint(0, 2)
if choice == 0:
# 三角函数
func = random.choice(trig_functions)
return f"{func}({num}°) × {random.randint(1, 50)}"
elif choice == 1:
# 乘方运算
base = random.randint(2, 10)
exp = random.randint(2, 4)
return f"{base}^{exp} + {random.randint(1, 100)}"
else:
# 复杂表达式
a, b = random.randint(1, 50), random.randint(1, 50)
return f"({a} + {b}) ×{random.randint(1, 100)}"
def generate_question(self, difficulty: str) -> str:
"""根据难度生成题目"""
if difficulty == '小学':
return self.generate_primary_question()
elif difficulty == '初中':
return self.generate_middle_question()
else: # 高中
return self.generate_high_question()
def generate_paper(self, username: str, difficulty: str, num_questions: int) -> bool:
"""生成试卷"""
user_folder = self.get_user_folder(username)
existing_questions = self.get_all_existing_questions(username)
generated_questions = []
attempts = 0
max_attempts = num_questions * 10 # 防止无限循环
while len(generated_questions) < num_questions and attempts < max_attempts:
question = self.generate_question(difficulty)
# 检查题目是否重复
if question not in existing_questions and question not in generated_questions:
generated_questions.append(question)
existing_questions.add(question)
attempts += 1
# 如果无法生成足够的不重复题目
if len(generated_questions) < num_questions:
print(f"警告:只能生成 {len(generated_questions)} 道不重复的题目")
# 生成文件名
timestamp = datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
filename = f"{timestamp}.txt"
filepath = os.path.join(user_folder, filename)
# 写入文件
try:
with open(filepath, 'w', encoding='utf-8') as f:
for i, question in enumerate(generated_questions, 1):
f.write(f"{i}. {question}")
if i < len(generated_questions): # 题目之间空一行
f.write("\n\n")
print(f"试卷已生成:{filepath}")
print(f"成功生成 {len(generated_questions)} 道题目")
return True
except Exception as e:
print(f"文件保存失败: {e}")
return False
def switch_type(self, new_type: str) -> bool:
"""切换题目类型"""
valid_types = ['小学', '初中', '高中']
if new_type in valid_types:
self.current_type = new_type
print(f"当前选择为{new_type}出题")
return True
else:
print("请输入小学、初中和高中三个选项中的一个")
return False
def run(self):
"""主运行循环"""
print("=== 中小学数学卷子自动生成程序 ===")
while True:
# 登录阶段
while self.current_user is None:
try:
input_str = input("请输入用户名和密码用空格隔开输入quit退出").strip()
if input_str.lower() == 'quit':
print("再见!")
return
parts = input_str.split()
if len(parts) != 2:
print("请输入正确的用户名、密码")
continue
username, password = parts
user = self.authenticate(username, password)
if user:
self.current_user = user
self.current_type = user['type']
print(f"当前选择为{self.current_type}出题")
else:
print("请输入正确的用户名、密码")
except KeyboardInterrupt:
print("\n再见!")
return
except Exception as e:
print(f"输入错误:{e}")
# 登录后的操作阶段
while self.current_user is not None:
try:
# 确保 current_type 不为 None
if self.current_type is None:
self.current_type = self.current_user['type']
prompt = f"准备生成{self.current_type}数学题目请输入生成题目数量10-30输入-1退出当前用户输入'switch'切换类型):"
user_input = input(prompt).strip()
if user_input == '-1':
print("退出当前用户")
self.current_user = None
self.current_type = None
break
elif user_input.startswith('切换为'):
# 处理切换类型
new_type = user_input[3:].strip()
self.switch_type(new_type)
elif user_input.lower() == 'switch':
new_type = input("请输入要切换的类型(小学/初中/高中):").strip()
self.switch_type(new_type)
else:
# 处理生成题目
try:
num = int(user_input)
if 10 <= num <= 30:
# 确保 difficulty 参数是字符串类型
difficulty = self.current_type or self.current_user['type']
self.generate_paper(
self.current_user['username'],
difficulty,
num
)
else:
print("题目数量应在10-30之间")
except ValueError:
print("请输入有效的数字")
except KeyboardInterrupt:
print("\n再见!")
return
except Exception as e:
print(f"发生错误:{e}")
def main():
"""主函数"""
try:
generator = MathPaperGenerator()
generator.run()
except Exception as e:
print(f"程序发生错误: {e}")
if __name__ == "__main__":
main()

@ -0,0 +1,49 @@
1. 2 + 36 × 19 - 49
2. 61 + 8 + 50 ÷ 89
3. 3 ÷ 71 - 83 ÷ 83
4. 83 ÷ 48 - 73 × 49 × 93
5. 64 - 19
6. 53 - 40 - 97
7. 50 × 95 + 82 - 79 + 44
8. 86 × 50 × 9 ÷ 60 × 29
9. 15 ÷ 48 - 48 + 35
10. 39 ÷ 37 × 15 - 81
11. 9 × 20 ÷ 37 ÷ 50 - 100
12. 67 ÷ 45
13. 74 ÷ 70 + 22
14. 2 × 26 + 31 - 30 + 9
15. 6 × 57 - 76 - 55 - 31
16. 96 ÷ 34 ÷ 88
17. 26 × 11 ÷ 24
18. 54 × 71 × 54 ÷ 81
19. 100 ÷ 50 ÷ 57 - 94 + 75
20. 18 × 54 × 41
21. 32 + 52 + 22 - 35 + 26
22. 44 - 100
23. 1 - 48 ÷ 8 ÷ 17
24. 95 + 24 - 20
25. 78 ÷ 100 ÷ 23 - 49 + 42
Loading…
Cancel
Save