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

合集下载
  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 所示, 注意由于程序设计题是从综合题库表中查询得 到的, 加上题库的增加删除操作, 所以题号是不连续的。
作者简介:石 静 (1978-), 女 , 硕 士 , 讲 师 , 研 究 方 向 : 网 络 及 数 据 库 技 术 ; 刘 欣 亮 (1970-), 男 , 硕 士 , 副 教 授 , 研 究方向: 数据库管理系统。 收稿日期:2015-05-17
2015.18 23
言, 一般由于题库量都特别大, 为了简单起见, 直接采用上 面的全局随机抽题就可以了, 不必担心泄题现象。 但是对于 一些不是太好组织的题目, 比如程序填空题、 程序改错题和 程序设计题等, 由于其判分方法的复杂性, 每一道题都需要 经过认真的斟酌和反复测试, 所以一般这类题的题库不会太 大, 就不能采用上述的全局随机抽题方法了, 可以使用分组 抽题策略, 以适应考试人数多 (主要是考试的场次多) 而题 库小的情况。 2.1 两种分组抽题策略
end i=i+1 end
2 分组抽题策略
上述的全局随机抽题策略虽然简单, 但是由于它每次抽 题都是在整个题库中进行遍历的, 所以如果题库相对于考试 的场次来说不是很大, 那么考过几场后, 很可能就出现泄题 现象了。 比如高校中的 “C 语言程序设计” 课程, 由于选课的 学生很多, 每次期末考试都要组织很多场, 这就需要保证每 一场次的考题不能重复出现。 对于选择题和普通的填空题而
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
假设当前抽取的是题量为 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 题
--下面的语句是取出第 i 章的出题量 set @tl =cast (substring (@lsstr1,1, patindex ('% @% ',
@lsstr1)-1) as int) --下 面 的 语 句 是 将 子 串 ' 第 i 章 的 出 题 量 @' 从 原 lsstr1 串
中去除 set @lsstr1 =substring (@lsstr1,patindex ('% @% ',@lsstr1) +
rand() 函数每次只能取一个随机数 , 将 它 放 入 循 环 执 行 n 次, 便可以取出 n 个随机数, 但是那样还要采取一些办法保 证取出的 n 个随机数不相同。
第一种方法比较简单, 下面以一个实际系统中选择题为 例, 看一下第一种方法的具体实现, 为了提高执行效率和方 便调用, 将此功能用 SQL Server 的存储过程实现。
(2) 用 随 机 函 数 : rand(), rand() 产 生 0-1 之 间 的 随 机 小 数。 配合取整函数和类型转换函数, 可以取得想要的随机 数。 如:
cast( floor(rand()*M) as int) 就 会 生 成 0 至 M 之 间 任 一 整数
cast(ceiling(rand() * M) as int) 就会生成 1 至 M 之间任一 整数
(1) 用 select top n order by newid() , newid() 函 数 的 返 回 值 是 一 个 全 球 唯 一 的 标 识 值 , 该 标 识 值 由 网 卡 号 和 CPU 时 钟 组 成 。 order by newid() 的 执 行 过 程 是 , newid() 在 扫 描 每 条 记 录的时候都生成一个唯一的函数值, 再按这个值对记录排序, 排序的结果当然每次都不一样了, 那么每次从这些新排序的 记录里取出前 n 条记录也就不同了。 可以看出, 当记录过多 时, 这样的代价有点大, 但是对于像题库表这样一个不超过 一千条记录的数据表来说, 效率还是很好的。
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
分组抽题是指在抽题以前, 先根据事先设置好的分组参 数, 将现有的试题分成若干小组, 然后每场考试的题目只限 制在某个或某几个小组中内进行抽取。 下面介绍两种分组抽 题策略。
(1) 分组随机抽题策略: 将现有的试题分成若干小组后, 在各个小组中进行随机抽题。
(2) 分组按考号抽题策略: 对试题先进行分组后, 再根 据考生的考号在小组内进行抽题。 具体做法是: 用考号和每 个小组的题量做求余运算, 余数为 0 取本小组的第一个题, 余数为 1 取本小组的第二个题, 依次类推。 这样, 使得考号 相邻考生的试卷一定不同, 适合于考生座位严格按考号安排 的考场。 2.2 分组抽题策略的实现方法
1 全局随机抽题策略
这是一种最简单易行的策略, 即按题型、 知识点 (章节) 分布等条件, 从整个题库中随机抽取符合条件的试题, 适合 于题库比较大的情况, 比如选择题和填空题。 这种抽题策略 被大多数考试系统所采用, 这里根据研究和实践提供两种方 便可行的实现方法。
随机抽题实际就是在整个试题数据库中随机抽取 n 条记 录, 在 SQL Server 中, 主要有两个方法可以实现。
在线考试系统随机抽题策略的讨论与实现
石静,刘欣亮
(河南科技大学信息工程学院软件学院,河南 洛阳 471023)
摘 要: 介绍了 3 种在线考试系统的题库随机抽题策略:全局随机抽题策略、分组随机抽题策略以及分组按考号随 机抽题策略,并给出了这 3 种抽题策略用 SQL Server 的存储过程具体实现的代码。这 3 种抽题策略简单方便,可以 满足不同考试情况的需要。 关键词: 在线考试系统;随机抽题策略;分组抽题
(1) 对于 “分组按考号抽题策略”, 最初的实现办法是借 助于视图和游标。 对 3 种综合题建立了各自的视图, 将他们 从一个题库表中筛选出来, 然后在相应的视图上进行分组。 由于题号并不是有规律的, 所以对其中记录的来回访问不能 依 靠 题 号 , 采 用 了 SQL 的 游 标 来 实 现 , 认 为 这 种 方 法 是 比 较 容易理解的。 后来, 在对题库中的题目进行分页浏览设计时, 从一种分页技术上受到了启发, 最终采用了 not in 的方式实现 了分组抽题, 要比原来的方法更为方便灵活。
DOI:10.16184/j.cnki.comprg.2015.18.010
对于一个实际可用的考试系统, 为了保证考试的安全, 通常希望它所产生的试卷题型题量相同, 而题目却不尽相同。 要实现这个目的, 不但需要设计合适的题库系统, 还需要一套 行 之 有 效 的 抽 题 策 略 , 其 中 随 机 抽 题 就 是 一 种 常 用 的 方 法 [1]。 以 一 个 ASP+SQL Server 实 现 的 “C 语 言 ” 考 试 系 统 为 例 , 介 绍 3 种方便有效的随机抽题策略及其实现方法。
相关文档
最新文档