网上考试系统编制中的随机抽取试题的四种算法

算法|随机

  因为教学的需要,我决定编写一个asp+ms sql2000的网上考试系统,其功能主要为:实现判断题、单项多项选择题和填空题的在线自动答题、改卷;并将学生的错误答案记入数据库,供教师分析。在编写从题库中随机抽取试题这一模块的算法上,却颇费了一番周折,现将解决过程记录如下,以供大家参考。
为了便于说明问题,文中提供的代码中的变量pd为从题库中要抽取出来考试的试题数量,数据库表名与字段名我都使用了中文,并仅以判断题为例。

算法一

由于不知道如何实现从题库中随机抽取试题的sql语句,我在网上下载了几个免费的考试系统进行研究,找到了第一种算法,其思路为先将数据库中所有数据读出,获得试题的总数后,生成一个1~(试题的总数-考试的试题数量)之间的随机数,然后从这里开始读出数据:

<% set rs=server.CreateObject("ADODB.RecordSet")

    sql="select * from 判断题 order by id asc"

    rs.open sql,conn,1,1

    mycound=rs.Recordcount '取得试题总数

randomize '初始化随机数种子值

n=fix((mycound-pd+1)*Rnd+1)

rs.move n ‘指针移到n这个随机数这个位置

for i=1 to pd

session("pdda")=session("pdda")&rs("正确答案")&"|" ‘用session来记录标准答案

‘输出试题及答案%>

  <tr> 

  <td width="10%" ><%=i%>、<%=rs("题目内容")%></td>

  <td align="center" width="10%" ><select name="cate<%=i%>"> 

  <option selected value=True>对</option> 

  <option value=False>错</option></select> </td> 

   </tr> 

<% rs.movenext

next

rs.close%>

这种算法基本上可以实现随机抽取试题,并让每个学生的试题和每一次刷新以后的试题都不相同,但是它的最大不足在于试题的先后顺序总是相同,特别是题库中试题不多的时候,学生几乎可以用背答案方法来应付考试了。虽然可以通过改变数据的排序方式来改变试题的先后顺序,但变化总是不大。

算法二

第二种算法的思路很简单,就是不断生成1~题库中的试题总数之间的随机数,然后到数据库中读取这条记录,直到满足考试的试题量为止。

<%

set rs=server.CreateObject("ADODB.RecordSet")

    sql="select * from 判断题 order by id asc"

    rs.open sql,conn,1,1

    mycound=rs.Recordcount '取得题库中的试题总数

rs.close

for i=1 to pd 

randomize 

sid=int((mycound +1)*rnd+1) ‘生成1~题库中的试题总数之间的随机数

set rs=conn.execute("select * from判断题where id="&sid) 

while rs.eof 

randomize 

sid=int((mycound +1)*rnd+1) 

set rs=conn.execute("select * from判断题where id="&sid) ‘如果数据库中找不到这条试题,就继续生成随机数读取试题。

wend

session("pdda")=session("pdda")&rs("正确答案")&"|" ‘用session来记录标准答案

‘输出试题及答案%>

  <tr> 

  <td width="10%" ><%=i%>、<%=rs("题目内容")%></td>

  <td align="center" width="10%" ><select name="cate<%=i%>"> 

  <option selected value=True>对</option> 

  <option value=False>错</option></select> </td> 

   </tr> 

<%

next

%>

这种算法应该是真正意义上的随机抽取试题,但是遗憾的是如果在题库中题量不多的情况下,很容易会在数据库中读取重复的试题,如果再使用一个变量来储存已经读取过的试题id来解决试题重复的问题,算法就过于繁琐,是很不可取的。

  算法二补充:

第二种算法的思路很简单,就是不断生成1~题库中的试题总数之间的随机数,然后到数据库中读取这条记录,直到满足考试的试题量为止。当时我认为这种算法应该是真正意义上的随机抽取试题,但是遗憾的是如果在题库中题量不多的情况下,很容易会在数据库中读取重复的试题,虽然也可以再使用一个变量或数组来储存已经读取过的试题id来解决试题重复的问题,算法就过于繁琐。为此,我片面地认为不可取的。其实用一个变量或数组来储存已经读取过的试题id,在算法上并不繁琐。

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

<%

写一个生成随机记录的函数

Function rndtest(m_count,r_count) ''参数m_count为试题总数,r_count为要读出的试题数

dim x,st,i

i=0

do while i>=r_count

randomize

x=fix(rnd*m_count)+1 ''产生1~m_count的随机数

if not instr(st,x)>0 then

st=st&x&","  ''用,分割

i=i+1

end if

if i>=m_count then exit do ''如果m_count小于r_count将出现死循环,于是判断并跳出循环

loop

rndtest=st

end function

set rs=server.CreateObject("ADODB.RecordSet")

       sql="select * from 判断题 order by id asc"

       rs.open sql,conn,1,1

mycound =rndtest(rs.Recordcount, pd) '取得题库中的试题总数

testcound=split(mycound, "'")

for i=0 to UBound(testcound)

rs.absoluteposition=matrix(i) ‘把记录指针移指向第testcound (i)条记录

session("pdda")=session("pdda")&rs("正确答案")&"|"  ‘用session来记录标准答案

‘输出试题及答案%>

   <tr> 

   <td  width="10%" ><%=i%>、<%=rs("题目内容")%></td>

    <td align="center" width="10%" ><select name="cate<%=i%>"> 

    <option selected value=True>对</option> 

    <option value=False>错</option></select> </td> 

     </tr> 

<%

next

%>

算法三

由于第二种算法容易造成试题重复,为了避免系统产生重复的随机数,我试着将题库中试题总数均分为kp个范围,让每个范围个产生一个随机数,这样就有效地避免了随机数重复。

<% set rs=server.CreateObject("ADODB.RecordSet")

    sql="select * from 判断题 order by id asc"

    rs.open sql,conn,1,1

    mycound=rs.Recordcount '取得试题总数

for i=1 to pd 

randomize 

temp=fix((fix(rs.Recordcount/pd)+1)*rnd+1) ‘生成1~题库试题总数除以试卷试题数之间的随机数

rs.move temp ‘指针移到随机数位置

session("pdda")=session("pdda")&rs("正确答案")&"|" ‘用session来记录标准答案

‘输出试题及答案%>

  <tr> 

  <td width="10%" ><%=i%>、<%=rs("题目内容")%></td>

  <td align="center" width="10%" ><select name="cate<%=i%>"> 

  <option selected value=True>对</option> 

  <option value=False>错</option></select> </td> 

   </tr> 

<%next

rs.close%>

这种算法能够有效地解决了算法一和算法二的不足,既做到了随机抽取试题,又做到了试题不重复。但是仔细一想还是存在不足:就是题库中的每一道试题出现的概率不相同,这样就显得不科学了。因为kp次都产生大数字的概率是不大了,这样排在后面的试题出现的机会就很小了。

算法四

算法四是我最后的研究结果,其算法分为三步:

Setp1、获取试题库试题总数,然后生成一个1~试题总数的阵列。

Setp2、生成随机数,将这个矩阵打乱。

Setp3、按顺序取出阵列中的题目。

这种算法和洗牌的原理相类似,图示如下:

(设试题库总数为10,要抽取出5道题)

Setp1:

阵列的初始内容如下:

A1

A2

A3

A4

A5

A6

A7

A8

A9

A10

1

2

3

4

5

6

7

8

9

10

Setp2:

生成两个随机数,如3和6。然后将A3和A6的内容交换,阵列的内容变为:

A1

A2

A3

A4

A5

A6

A7

A8

A9

A10

1

2

6

4

5

3

7

8

9

10

Setp3、按顺序取出阵列中的题目A1~A5的内容,应该是1、2、6、4、5,读出数据库中相应的试题。

如果不断循环Setp2,该阵列中的内容就随机打乱,这样既实现了随机抽取试题的目的,又避免了试题抽取重复。

<%    

dim matrix() '定义变量数组

set rs=server.CreateObject("ADODB.RecordSet")

sql="select * from 判断题order by id asc"

rs.open sql,conn,1,1

mycound=rs.Recordcount '取得试题总数

'设定阵列的初始值

for i=0 to mycound

matrix(i)=i+1

next

randomize '生成随机数种子

for i=0 to 2*mycound ‘循环2*试题总数次

j=fix(rnd*mycound)   

k=fix(rnd*mycound)

'交换matrix(k)和matrix(j)的内容

temp=matrix(k)

matrix(k)=matrix(j)

matrix(j)=temp

next

'取出阵列中的题目,数量为试卷中该类题的数量

for i=1 to pd 

rs.absoluteposition=matrix(i) ‘把记录指针移指向第matrix(i)条记录

session("pdda")=session("pdda")&rs("正确答案")&"|" ‘用session来记录标准答案

‘输出试题及答案%>

  <tr> 

  <td width="10%" ><%=i%>、<%=rs("题目内容")%></td>

  <td align="center" width="10%" ><select name="cate<%=i%>"> 

  <option selected value=True>对</option> 

  <option value=False>错</option></select> </td> 

   </tr> 

<%next

rs.close%>

算法四补充:

当时无法解决定义一个足够大的数组,于是用dim matrix(X),预设一个足够大的数字X。虽然说暂时不会出现问题,但是如果数据库中的试题数很大呢?总像一块石头搁在心中。呵呵。现在发现了ReDim语句,vbs参考中是这样介绍ReDim 语句的:在过程级中声明动态数组变量并分配或重新分配存储空间。这样用ReDim matrix (rst.Recordcount)就可以完美地解决了这个问题。

<%       

Dim matrix()

set rs=server.CreateObject("ADODB.RecordSet")

sql="select * from 判断题order by id asc"

rs.open sql,conn,1,1

mycound=rs.Recordcount  '取得试题总数

ReDim matrix(rst.Recordcount) ‘定义一个等于rst.Recordcount的数组

'设定阵列的初始值

for i=0 to mycound

matrix(i)=i+1

next

randomize  '生成随机数种子

for i=0 to 2*mycound  ‘循环2*试题总数次

j=fix(rnd*mycound)     

k=fix(rnd*mycound)

'交换matrix(k)和matrix(j)的内容

temp=matrix(k)

matrix(k)=matrix(j)

matrix(j)=temp

next

'取出阵列中的题目,数量为试卷中该类题的数量

for i=1 to pd 

rs.absoluteposition=matrix(i) ‘把记录指针移指向第matrix(i)条记录

session("pdda")=session("pdda")&rs("正确答案")&"|"  ‘用session来记录标准答案

‘输出试题及答案%>

   <tr> 

   <td  width="10%" ><%=i%>、<%=rs("题目内容")%></td>

    <td align="center" width="10%" ><select name="cate<%=i%>"> 

    <option selected value=True>对</option> 

    <option value=False>错</option></select> </td> 

     </tr> 

<%next

rs.close%>

总结:

相对来说,算法四应该是最合理的。但是我不知道应该循环Setp2多少次,阵列中的数值最“随机”,而且我不知道当试题库的试题总数很多的情况下,这种算法是否会很占系统资源,欢迎大家来信和我讨论。

时间: 2024-10-09 14:25:53

网上考试系统编制中的随机抽取试题的四种算法的相关文章

随机抽取试题 并把他们显示到一个控件上怎么做啊

问题描述 急急急哪位高手帮忙解决我用C#做项目项目名叫在线考试系统现遇到难题随机抽取试题并把他们显示到一个控件上怎么做啊 解决方案 解决方案二:用随机数来取对应试题的ID这个应该要用到数据库吧``解决方案三:同上用随机数范围就定在你有多少道题解决方案四:产生一组不相同的随机数(试题id)在一个数组里面然后select试题from表whereidin数组集合解决方案五:用2个数组一个记录总的题数一个记录相应题目是否已被抽取给你一个类似的案例(我写的)privatevoidgetgut(){stri

利用ASP.NET构建网上考试系统

asp.net 随着计算机网络的普及,基于数据库的B/S网上考试系统得到广泛地应用,现以ASP.net(C#)+SQL server(或ACCESS)为例说明开发网上考试系统的实现方法. 一.数据库的设计: 建立数据库netexam,在库中添加考生信息表StuInfo,分别建立以下字段:考号ExamId(c)(主键).考生姓名Name(c).是否登录考试LogYn(c).得分Score(c).随机生成的试题答案mca(c) (注:此处以多选题为例,单选题.判断题同理).添加多选题题库表mc,建立

用ASP实现网上考试系统

随着互连网技术的发展网上教学将成为人们接受再教育和终身教育的主要形式.在网上学校中,人们可以不受时间和空间的限制,随时随地选学任何地方的任何课程.网上学校的发展对网上考试的发展提出了迫切的要求.这里是我用Asp和Access数据库实现的一个网上考试系统.当用户凭用户名和口令登录时,系统首先检查该用户是否已参加过考试,若是则进行成绩查询,若否则从题库中提取考题供用户解答.等用户提交答卷后,系统进行评分并将成绩登记入库. 一. 数据库设计 首先建立一数据库exercise.mdb,其中包括两个表:u

asp网上考试系统代码分析

网上考试 随着互连网技术的发展网上教学将成为人们接受再教育和终身教育的主要形式.在网上学校中,人们可以不受时间和空间的限制,随时随地选学任何地方的任何课程.网上学校的发展对网上考试的发展提出了迫切的要求.这里是我用Asp和Access数据库实现的一个网上考试系统.当用户凭用户名和口令登录时,系统首先检查该用户是否已参加过考试,若是则进行成绩查询,若否则从题库中提取考题供用户解答.等用户提交答卷后,系统进行评分并将成绩登记入库. 一. 数据库设计 首先建立一数据库exercise.mdb,其中包括

谁有用ASP做的网上考试系统

问题描述 谁有用ASP做的网上考试系统要那种有倒计时并且自动评分和给评语的有的联系我我的QQ是28446687或者直接给我发到邮箱xb28446687@126.com谢谢!谢谢!

IOS中Json解析实例方法详解(四种方法)_IOS

作为一种轻量级的数据交换格式,json正在逐步取代xml,成为网络数据的通用格式. 有的json代码格式比较混乱,可以使用此"http://www.bejson.com/"网站来进行JSON格式化校验(点击打开链接).此网站不仅可以检测Json代码中的错误,而且可以以视图形式显示json中的数据内容,很是方便. 从IOS5开始,APPLE提供了对json的原生支持(NSJSONSerialization),但是为了兼容以前的iOS版本,可以使用第三方库来解析Json. 本文将介绍Tou

php中通过数组进行高效随机抽取指定条记录的算法_php技巧

php使用数组array_rand()函数进行高效随机抽取指定条数的记录,可以随机抽取数据库中的记录,适合进行随机展示和抽奖程序. 该算法主要是利用php的array_rand()函数,下面看一下array_rand()函数的主要功能: array_rand-从数组中随机取出一个或多个单元 mixed array_rand(array $input[,int $num_req] ) array_rand()在你想从数组中取出一个或多个随机的单元时相当有用.它接受input作为输入数组和一个可选的

java+sql2005 随机抽取试题的代码_JSP编程

复制代码 代码如下: import java.awt.BorderLayout; import java.util.*; import java.awt.event.*; import java.awt.Container; import java.awt.EventQueue; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Stateme

入门:在网页中使用CSS样式表的四种方法

css|网页|样式表 如何在网页中插入CSS 前面我们了解了CSS的语法,但要想在浏览器中显示出效果,就要让浏览器识别并调用.当浏览器读取样式表时,要依照文本格式来读,这里介绍四种在页面中插入样式表的方法:链入外部样式表.内部样式表.导入外表样式表和内嵌样式. 1. 链入外部样式表 链入外部样式表是把样式表保存为一个样式表文件,然后在页面中用< link >标记链接到这个样式表文件,这个标记必须放到页面的< head >区内,如下: <head> -- <link