在线考试系统随机抽题策略的讨论与实现_石静

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
下面以 “分组按考号抽题策略” 抽取程序设计题为例分 析一下这种方法。
假设题库中有 10 个程序设计题, 要分为 3 组。 那 么 进 行 划 分 的 式 子 可 以 这 样 写 : @count= ceiling (1.0* @total / @groups) 其中, ceiling 函数的功能是返回大于或等于指定数值表达 式的最小整数; @count “每组包含的试题数目”, 当然最后一组可能低于 这个数。 @total “程 序 设 计 题 的 总 个 数 ”, 可 以 通 过 查 询 综 合 题 题 库得到该值; @groups “分 组 的 总 数 目 ”, 可 以 通 过 查 询 考 试 设 置 表 得 到该值。 由 上 算 出 , 10 个 题 分 为 3 组 , 每 组 的 题 量 为 : 4, 4, 2。 如图 1 所示, 注意由于程序设计题是从综合题库表中查询得 到的, 加上题库的增加删除操作, 所以题号是不连续的。
(2) 用 随 机 函 数 : rand(), rand() 产 生 0-1 之 间 的 随 机 小 数。 配合取整函数和类型转换函数, 可以取得想要的随机 数。 如:
cast( floor(rand()*M) as int) 就 会 生 成 0 至 M 之 间 任 一 整数
cast(ceiling(rand() * M) as int) 就会生成 1 至 M 之间任一 整数
1 全局随机抽题策略
这是一种最简单易行的策略, 即按题型、 知识点 (章节) 分布等条件, 从整个题库中随机抽取符合条件的试题, 适合 于题库比较大的情况, 比如选择题和填空题。 这种抽题策略 被大多数考试系统所采用, 这里根据研究和实践提供两种方 便可行的实现方法。
随机抽题实际就是在整个试题数据库中随机抽取 n 条记 录, 在 SQL Server 中, 主要有两个方法可以实现。
(1) 对于 “分组按考号抽题策略”, 最初的实现办法是借 助于视图和游标。 对 3 种综合题建立了各自的视图, 将他们 从一个题库表中筛选出来, 然后在相应的视图上进行分组。 由于题号并不是有规律的, 所以对其中记录的来回访问不能 依 靠 题 号 , 采 用 了 SQL 的 游 标 来 实 现 , 认 为 这 种 方 法 是 比 较 容易理解的。 后来, 在对题库中的题目进行分页浏览设计时, 从一种分页技术上受到了启发, 最终采用了 not in 的方式实现 了分组抽题, 要比原来的方法更为方便灵活。
DOI:10.16184/prg.2015.18.010
对于一个实际可用的考试系统, 为了保证考试的安全, 通常希望它所产生的试卷题型题量相同, 而题目却不尽相同。 要实现这个目的, 不但需要设计合适的题库系统, 还需要一套 行 之 有 效 的 抽 题 策 略 , 其 中 随 机 抽 题 就 是 一 种 常 用 的 方 法 [1]。 以 一 个 ASP+SQL Server 实 现 的 “C 语 言 ” 考 试 系 统 为 例 , 介 绍 3 种方便有效的随机抽题策略及其实现方法。
(1) 用 select top n order by newid() , newid() 函 数 的 返 回 值 是 一 个 全 球 唯 一 的 标 识 值 , 该 标 识 值 由 网 卡 号 和 CPU 时 钟 组 成 。 order by newid() 的 执 行 过 程 是 , newid() 在 扫 描 每 条 记 录的时候都生成一个唯一的函数值, 再按这个值对记录排序, 排序的结果当然每次都不一样了, 那么每次从这些新排序的 记录里取出前 n 条记录也就不同了。 可以看出, 当记录过多 时, 这样的代价有点大, 但是对于像题库表这样一个不超过 一千条记录的数据表来说, 效率还是很好的。
24 2015.18
型=程序设计题 order by 题号) order by 题号。 当 然 这 种 情 况 可 以 用 desc 倒 着 直 接 取 出 最 后 一 个 题 , 这
里这样写是为了和上面的情况统一起来。
图2 (2) “分组随机抽题策略” 比较简单, 分好组后, 在小组 内用 newid() 或者 rand() 即可。 为了和上面的 “分组按考号抽 题策略” 代码统一, 这里用 rand() 函数实现。 2.3 主要代码 if @ctclflag=0 --ctclflag=0 表明是采用的全局随机抽题策略 insert into sjzht (stuid,th) select top 1 @stuid as stuid,th from zhtk where tx =@txflag order by newid () -- 当 前 @txflag=5, 表 示 是 程 序 设 计 题 else --ctclflag≠0 表明是采用分组抽题策略 begin select @max=count (*) from zhtk where tx=@txflag -@max 是设计题的总题量 if (@groups>= @max) --分组总数超出或等于总题量的情况 begin if (@groupid>@max) --当前小组号大于总题量,那么就抽 取最后一个设计题
1,50) if @tl>0 --如果 @tl>0,在“选择题库”xztk 的第 i 章中随机抽
取 @tl 个题存到“试卷选择题表” sjxzt 中 begin --其中 stuid 为考号字段,也是试卷 号 ;th 为 题 号 字 段 ; tjda 为答案字段;zj 表示章节号 set @sqlstr='insert into sjxzt (stuid,th,tjda) select top '+cast (@tl as varchar(2)) + ' '+cast (@stuid as varchar (20))+' as stuid , th ,'''' as tjda from xztk where zj= '+cast (@i as varchar (2))+' order by newid() ' exec sp_executesql @sqlstr
set @i=1 --@i 表示章节序号 set @lsstr1=@xztl --@xztl 是 从 考 试 设 置 表 kssz 中 查 询 出 的选择题各章节的出题量 while len (@lsstr1)>0 --@xztl=' 第 0 章题量 @ 第 1 章题量 @ 第 2 章题量……@ 第 12 题量 begin
--下面的语句是取出第 i 章的出题量 set @tl =cast (substring (@lsstr1,1, patindex ('% @% ',
@lsstr1)-1) as int) --下 面 的 语 句 是 将 子 串 ' 第 i 章 的 出 题 量 @' 从 原 lsstr1 串
中去除 set @lsstr1 =substring (@lsstr1,patindex ('% @% ',@lsstr1) +
图1
假设当前抽取的是题量为 4 的小组, 比如第 2 组, 考号 为 '20100002', 先将考号转换为整型, 然后做求余运算:
20100002 % 4=2 那么当前考生应抽 取 当 前 小 组 的 第 3 题 , 即 题 号 为 25 的 题。 我们只需要将该题前面的题全 “去掉”, 然后抽取当前的 第 一 个 即 可 , 当 然 所 谓" 去 掉" 不 是 真 的 删 除 , 而 是 用 “not int” 来忽略掉。 那么该题前面有多少道题呢? 当然是本小组前面的所有题个数即 (2-1) ×4=4, 再 加 上 在本小组内该题前面所有题的数目 2。 所以第 2 组的第 3 题前 面一共有 4+2=6 个题。 那么要想取得这个题, 需要的 SQL 语句为: select top 1 题号 from 综 合 题 题 库 where 题 型=程 序 设 计 题 and 题 号 not in (select top 6 题 号 from 综 合 题 题 库 where 题型=程序设计题 order by 题号) order by 题号 即: select top 1 th from zhtk where tx=5 and th not in (select top 6 th from zhtk where tx=5 order by th) order by th 上面分析的是一般的情况, 下面看一下假设当前抽取的 是 最 后 一 个 小 组 即 第 3 组 , 小 组 题 量 小 于 4, 考 号 为 '20100003' 的情况。 20100003 % 4=3 那么当前考生应抽取当前小组的第 4 题, 但是最后一组 只有两道题, 这时候再按照上面的做法就出问题了。 采用下 面的办法处理最后一组的这种情况: 仍然按照前面的算法求出要取的题前面有多少道题, 即 (3-1) *4+3=11, 如果这个数值大于或等于总题量 10, 那么让 该考号实际取最后一个题。 对于这个例子, 由于 11>10, 那么考号为 '20100003' 的考 生所取题目的题号为 50, 如图 2 所示。 它 前 面 题 的 个 数 为 10 -1 =9 , 所 以 取 得 该 题 的 SQL 语 句为: select top 1 题号 from 综合题题库 where 题型=程序设计题 and 题 号 not in (select top 9 题 号 from 综 合 题 题 库 where 题
在线考试系统随机抽题策略的讨论与实现
石静,刘欣亮
(河南科技大学信息工程学院软件学院,河南 洛阳 471023)
摘 要: 介绍了 3 种在线考试系统的题库随机抽题策略:全局随机抽题策略、分组随机抽题策略以及分组按考号随 机抽题策略,并给出了这 3 种抽题策略用 SQL Server 的存储过程具体实现的代码。这 3 种抽题策略简单方便,可以 满足不同考试情况的需要。 关键词: 在线考试系统;随机抽题策略;分组抽题
rand() 函数每次只能取一个随机数 , 将 它 放 入 循 环 执 行 n 次, 便可以取出 n 个随机数, 但是那样还要采取一些办法保 证取出的 n 个随机数不相同。
第一种方法比较简单, 下面以一个实际系统中选择题为 例, 看一下第一种方法的具体实现, 为了提高执行效率和方 便调用, 将此功能用 SQL Server 的存储过程实现。
end i=i+1 end
2 分组抽题策略
上述的全局随机抽题策略虽然简单, 但是由于它每次抽 题都是在整个题库中进行遍历的, 所以如果题库相对于考试 的场次来说不是很大, 那么考过几场后, 很可能就出现泄题 现象了。 比如高校中的 “C 语言程序设计” 课程, 由于选课的 学生很多, 每次期末考试都要组织很多场, 这就需要保证每 一场次的考题不能重复出现。 对于选择题和普通的填空题而
作者简介:石 静 (1978-), 女 , 硕 士 , 讲 师 , 研 究 方 向 : 网 络 及 数 据 库 技 术 ; 刘 欣 亮 (1970-), 男 , 硕 士 , 副 教 授 , 研 究方向: 数据库管理系统。 收稿日期:2015-05-17
2015.18 23
ቤተ መጻሕፍቲ ባይዱ
言, 一般由于题库量都特别大, 为了简单起见, 直接采用上 面的全局随机抽题就可以了, 不必担心泄题现象。 但是对于 一些不是太好组织的题目, 比如程序填空题、 程序改错题和 程序设计题等, 由于其判分方法的复杂性, 每一道题都需要 经过认真的斟酌和反复测试, 所以一般这类题的题库不会太 大, 就不能采用上述的全局随机抽题方法了, 可以使用分组 抽题策略, 以适应考试人数多 (主要是考试的场次多) 而题 库小的情况。 2.1 两种分组抽题策略
分组抽题是指在抽题以前, 先根据事先设置好的分组参 数, 将现有的试题分成若干小组, 然后每场考试的题目只限 制在某个或某几个小组中内进行抽取。 下面介绍两种分组抽 题策略。
(1) 分组随机抽题策略: 将现有的试题分成若干小组后, 在各个小组中进行随机抽题。
(2) 分组按考号抽题策略: 对试题先进行分组后, 再根 据考生的考号在小组内进行抽题。 具体做法是: 用考号和每 个小组的题量做求余运算, 余数为 0 取本小组的第一个题, 余数为 1 取本小组的第二个题, 依次类推。 这样, 使得考号 相邻考生的试卷一定不同, 适合于考生座位严格按考号安排 的考场。 2.2 分组抽题策略的实现方法
相关文档
最新文档