|
![]() |
名片设计 CorelDRAW Illustrator AuotoCAD Painter 其他软件 Photoshop Fireworks Flash |
|
因为教学的需要,我决定编写一个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,在算法上并不繁琐。 <% 写一个生成随机记录的函数 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多少次,阵列中的数值最“随机”,而且我不知道当试题库的试题总数很多的情况下,这种算法是否会很占系统资源,欢迎大家来信和我讨论。 返回类别: 教程 上一教程: 对文件的操作--建立移动删除文件夹 下一教程: ASP 3.0高级编程(十九) 您可以阅读与"网上考试系统编制中的随机抽取试题的四种算法"相关的教程: · 用ASP开发试题库与在线考试系统(5) · 用ASP开发试题库与在线考试系统(4) · 用ASP开发试题库与在线考试系统(6) · 用ASP开发试题库与在线考试系统(1) · 用ASP开发试题库与在线考试系统(7) |
![]() ![]() |
快精灵印艺坊 版权所有 |
首页![]() ![]() ![]() ![]() ![]() ![]() ![]() |