2.0版本参考地址: https://blog.csdn.net/qq_34457443/article/details/113742369
摘要:
用试题文档(.txt)随机组卷生成试卷文档(.doc),本次代码实现的难点在于扫描试题文档和调整小题在试卷文档中的格式。前者要识别小题题目,识别小题选项。为此需要提前对试题文档做处理,用固定的格式进行输入,如此才能保证在小题不被改变的情况下进行扫描。生成的试卷为Word文档,格式正确,可打印。
关键字:随机选题、调换选项
一:课题要求
课程设计题目:随机组卷程序
基本要求:完成50分。
1. 卷子内容可以任意专业内容。四项单选题。
2. 数据源为50题,随机选择30题。
3. 要求每套题生成后,要方便打印
高级要求:完成每一项10分,
1. 使用外部数据。JDBC
2. 自动输出。
3. 答案顺序随机
4 要基本对齐(4项1行,2项1行,1项1行)
5 要求生成正确答案,单独成1行。
二:课题思路
第一步:构造TheTitle类
作用:1. 存储小题题目、选项、答案;
2.随机调换选项;
3.返回题目,选项,答案;
3.用小题选项ABCD转换为正确选项内容。
第二步:建立main
作用:1. 生成随机选题的标号;
2.扫描试题文件;
3.生成试卷。
三:环境要求
JAVA代码编写软件eclipse + Word软件 + .txt文件
四:实现过程
1:试题文件格式
小题的题首部加上字符“#”,题末尾加上字符“$”;
选项ABCD在一行,D选项的结尾必须是换行符“\n”.
2:试卷文件描述
首先生成小题,而选项基本对齐(4项1行,2项1行,1项1行);然后生成小题答案(5个一行)。
3:设计类titles
题目单独存储于字符串(title),4个选项存储于字符串数组(option),选项存储于字符(abcd)。
成员函数:
StringsearchAnswer(char abcd)用选项abcd返回选项内容; charchangeOption()交换选项内容并返回交换选项后正确的选项;
StringprinTitle() String prinOptionA() String prinOptionB()
StringprinOptionC() StringprinOptionD()返回小题题目和选项字符串。
4:扫描试题文件
第一步:打开试题文件
第二部:读取试题文件
第三部:初始化对象数组
第四部:分析试题文件并将试题保存于对象数组中
5:随机选题
建立一个int数组sorting,长度为试题文件小题总数(50),sorting[0]-[49]分别存储数字0-49。然后借用Random()随机生成0-49内两个数字a,b,交换sorting[a],sorting[b]内存储的数字,交换1000次,目的是为了彻底打乱0-49在sorting中的排序。如此以来,直接选取对象数组titles[sorting[i]](0<= I < 30),达到随机选30题的目的。
代码如下:
int []sorting;//int [] sorting = new int [50];
sorting = newint [number];
int flag = 1,suiji1, suiji2, temp;
for(int i =0; i < number; i++)
sorting[i] = flag++;
for(int i =0; i < 1000; i++){
suiji1 = new Random().nextInt(number);
suiji2 = new Random().nextInt(number);
temp = sorting[suiji1];
sorting[suiji1] = sorting[suiji2];
sorting[suiji2] = temp;
}
6:答案顺序随机
TheTitle类的char changeOption()成员函数,里面可以随机生成0-3两个数字a,b,交换option[a],option[b]存储的选项内容。
代码如下:
charchangeOption(){//交换选项 + 记录abcd
String temp = null, str = null;
str = searchAnswer(abcd);//交换选项前记录选项内容(str为 null+"")
char searchAbcd;
int suiji1, suiji2;
for(int i = 0; i < 50; i++){//交换选项
suiji1 = new Random().nextInt(4);//随机生成0-3的俩数
suiji2 = new Random().nextInt(4);
temp = option[suiji1];
option[suiji1] = option[suiji2];
option[suiji2] = temp;
}
//记录abcd
if(str == option[0]) searchAbcd = 'A';
else if(str == option[1]) searchAbcd = 'B';
else if(str == option[2]) searchAbcd = 'C';
else searchAbcd = 'D';
return searchAbcd;
}
实现结果如图:
试题文档:
试卷文档:
7:基本对齐
基本对齐最简单的的方法是在向试卷文件写入时,每写入一个选项就换行一次。
代码如下:
for(int j =0; j < 4; j++){
bw.write(titles[sorting[i]].option[j].replaceAll(removeSs,""));
//写入选项内容
bw.newLine();
}
实现结果如下图:
8:生成试卷
首先建立目标文件,用循环依次向目标文件中写入30个小题,在所有小题后面写入小题答案。而写入小题就要依靠TheTitle类中的成员函数返回字符串(小题题目,选项),将这些字符串写入试卷文档中。
代码如下:
FileWriterwriter = new FileWriter("D:\\试卷.doc");
//创建一个BufferedWriter缓冲对象
BufferedWriterbw = new BufferedWriter(writer);
bw.write(" HELLO ");
bw.newLine();
bw.write(" 出题人:ycf ");
bw.newLine();
StringremoveSs = "null";//用来去除写在所有字符串前的"null"
int i = 0;
while(true){
if(i >= titleNumber)
break;
str = null;//先置空(str暂时记录答案内容)
ans[i] =titles[sorting[i]].changeOption();//记录答案abcd
bw.write((i+1) +titles[sorting[i]].prinTitle().replace(removeSs, ""));//新序号 + 题目
bw.newLine();
for(int j = 0; j < 4; j++){
bw.write(titles[sorting[i]].option[j].replaceAll(removeSs,""));//写入选项内容
bw.newLine();
}
bw.newLine();
i++;
System.out.println("已经生成" + i + "个小题");
}
//-------------写入答案数组ans[0]~ans[29]-------------//
bw.write("-----------------------------答案如下-----------------------------");
bw.newLine();
str = null;
for(i = 0; i< 30; i++){//写入答案
bw.write(ans[i]);
if((i-4) % 5 == 0)
bw.write(' ');
}
9:生成试卷答案
试卷答案先暂时存储于数组ans[0]-ans[29]中,在所有小题写入试卷后写入试卷末尾。
代码如下:
str = null;
for(i = 0; i< 30; i++){//写入答案
bw.write(ans[i]);
if((i-4) % 5 == 0)
bw.write(' ');
}
五:代码实现
package suiji;
import java.util.Random;
import java.io.*;
class TheTitle{//存储题目的类
String title;//题目
String[] option = new String[4];
char abcd;//正确答案abcd
String prinTitle() { return title; }
String prinOptionA(){ return option[0]; }
String prinOptionB(){ return option[1]; }
String prinOptionC(){ return option[2]; }
String prinOptionD(){ return option[3]; }
String searchAnswer(char abcd){//返回正确答案内容(被changeOption()调用)
String str = null;
switch(abcd){
case 'A': str = option[0]; break;
case 'B': str = option[1]; break;
case 'C': str = option[2]; break;
case 'D': str = option[3]; break;
}
return str;//返回的是null+""
}
char changeOption(){//交换选项 + 记录abcd
String temp = null, str = null;
str = searchAnswer(abcd);//交换选项前记录选项内容(str为 null+"")
char searchAbcd;
int suiji1, suiji2;
for(int i = 0; i < 50; i++){//交换选项
suiji1 = new Random().nextInt(4);//随机生成0-3的俩数
suiji2 = new Random().nextInt(4);
temp = option[suiji1];
option[suiji1] = option[suiji2];
option[suiji2] = temp;
}
//记录abcd
if(str == option[0]) searchAbcd = 'A';
else if(str == option[1]) searchAbcd = 'B';
else if(str == option[2]) searchAbcd = 'C';
else searchAbcd = 'D';
return searchAbcd;
}
}
public class 随机组卷 {
/**
* @param args
* @author ycf
*/
public static void main(String[] args) throws Exception {
int number = 50;//题目总数
int titleNumber = 5;//生成题目数量
char [] ans = new char [number];//记录试卷答案
//----------------随机寻找1-50中30个数存储于sorting[0]-sorting[29]----------------//
int [] sorting;//int [] sorting = new int [50];
sorting = new int [number];
int flag = 1, suiji1, suiji2, temp;
for(int i = 0; i < number; i++)
sorting[i] = flag++;
for(int i = 0; i < 1000; i++){
suiji1 = new Random().nextInt(number);
suiji2 = new Random().nextInt(number);
temp = sorting[suiji1];
sorting[suiji1] = sorting[suiji2];
sorting[suiji2] = temp;
}
//-------------------------------------------50道题-------------------------------------------//
TheTitle [] titles = new TheTitle[number];
for(int i = 0; i < number; i++)
titles[i] = new TheTitle();
//-------------------------------------------扫描试题-------------------------------------------//
FileReader reader = new FileReader("D:\\试题.txt");
//创建一个BufferedReader缓冲对象
BufferedReader br = new BufferedReader(reader);
//str短暂存储文字 strTitle存储所有的题目
String str = null, strTitle = null;
// strTitle读取所有文字
while((str = br.readLine()) != null){
strTitle += str + '\n';
}
br.close();//关闭试题库文件
char[] chTitle = strTitle.toCharArray();//strTitle(字符串)转化为字符数组 chTitle
flag = 0;//记录对象数组的下标
for(int i = 0; i < chTitle.length; i++){//扫描字符
while(chTitle[i] == ' ')//消除空白格
i++;
if(chTitle[i] == '#'){//扫描题目
str = null;
i += 3;//去除每道题前的 '#'+原标题序号
for(; chTitle[i] != '$'; i++){
str += chTitle[i];
if(chTitle[i] == '(' && chTitle[i+2] == ')'){//搜寻答案
titles[flag].abcd = chTitle[i+1];
i++;
}
}
titles[flag].title = str;
i++;
}
if(chTitle[i] == 'A' && chTitle[i+1] == '.'){//扫描A选项
str = null;
i += 2;//跳过字符串"A."
for(; chTitle[i] != 'B'; i++){
str += chTitle[i];
}
titles[flag].option[0] = str;
}
if(chTitle[i] == 'B' && chTitle[i+1] == '.'){//扫描B选项
str = null;
i += 2;//跳过字符串"B."
for(; chTitle[i] != 'C'; i++){
str += chTitle[i];
}
titles[flag].option[1] = str;
}
if(chTitle[i] == 'C' && chTitle[i+1] == '.'){//扫描C选项
str = null;
i += 2;//跳过字符串"C."
for(; chTitle[i] != 'D'; i++){
str += chTitle[i];
}
titles[flag].option[2] = str;
}
if(chTitle[i] == 'D' && chTitle[i+1] == '.'){//扫描D选项
str = null;
i += 2;//跳过字符串"D."
for(; chTitle[i] != '\n'; i++){
str += chTitle[i];
}
titles[flag].option[3] = str;
flag++;
}
}
//---------------------------------------------生成试题---------------------------------------------//
FileWriter writer = new FileWriter("D:\\试卷.doc");
//创建一个BufferedWriter缓冲对象
BufferedWriter bw = new BufferedWriter(writer);
bw.write(" HELLO ");
bw.newLine();
bw.write(" 出题人:ycf ");
bw.newLine();
String removeSs = "null";//用来去除写在所有字符串前的"null"
int i = 0;
while(true){
if(i >= titleNumber)
break;
str = null;//先置空(str暂时记录答案内容)
ans[i] = titles[sorting[i]].changeOption();//记录答案abcd
bw.write((i+1) + titles[sorting[i]].prinTitle().replace(removeSs, ""));//新序号 + 题目
bw.newLine();
for(int j = 0; j < 4; j++){
bw.write((char)('A' + j) + titles[sorting[i]].option[j].replaceAll(removeSs, ""));//写入选项内容
bw.newLine();
}
bw.newLine();
i++;
System.out.println("已经生成" + i + "个小题");
}
//-------------写入答案数组ans[0]~ans[29]-------------//
bw.write("-------------------------------答案如下-------------------------------");
bw.newLine();
str = null;
for(i = 0; i < 30; i++){//写入答案
bw.write(ans[i]);
if((i-4) % 5 == 0)
bw.write(' ');
}
bw.flush();
bw.close();//关闭写入文件
}
}
三年后再次打开这篇博客,太垃圾了以至于不想阅读,强烈建议伙伴们去查看2.0版本。https://blog.csdn.net/qq_34457443/article/details/113742369