作者laechan (小太保)
看板mud
标题[闲聊] 测验系统
时间Mon Jan 21 11:05:12 2013
比方现在有某一测验系统,执行时会出现底下画面
本次测验共 10 道题目,每题 10 分,总分 100 分。
--测验开始,请按 ENTER 键继续--
01.请问 bla bla bla bla
1.
2.
3.
4.
请选择: _
02.请问 bla bla bla bla
1.
2.
3.
4.
请选择:
========================================================
那麽,原则上我们需要一个题库脚本档或是题库资料库,一个
题库汇入系统,以及一个测验系统。
脚本档的型式可以类似底下..
请问 bla bla bla bla**
选项一**
选项二**
选项三**
选项四##
读进该档後假设为 cont,先做 explode(cont,"##"),再对每
一子项做 tmps=explode(sub_cont,"**"),则..
tmps[0] = 题目
tmps[1..sizeof(tmps)-1] = 各选项
则要新增题库时,只要透过编辑该档的方式,再用题库汇入系
统重新汇入即可。
题库资料库的意思,一般则是指该资料库具有资料即时 keyin
的能力,而且通常会与题库汇入系统写在一起,这时就规划资
料型态如下
mapping test_data=
([
"t01":(["q01":({"题目01的内容","选项1","选项2","选项3","选项4"}),
"q02":({"题目01的内容","选项1","选项2","选项3","选项4"}),
.
.
]);
这时候
tmps = test_data["t01"]["q01"];
tmps[0] = 题目
tmps[1..sizeof(tmps)-1] = 各选项
然後撰写一个 random_sort 函数来对 tmps 做乱数排序,但
是不动第 1 个(题目),这样就能产生乱数顺序的选项。
tmps=sort_array(tmps,"random_sort",this_object());
int random_sort(string a,string b)
{
if(a[0..0]==设定题目有特殊标头) return -1; // 永远传回该值
return -1+random(2); // 其它情况就传回乱数
}
测验系统一般可以做底下的架构...
// 程式进入点
void main(string str)
{
// 依玩家所给的 key 值(如 t01)读取测验资料
mapping test_data=读取测验资料[str];
// 这时 test_data 内容类似 ([ "q01":({...}), "q02":({...}), ...])
string* tmps=([]);
int j;
tmps=keys(test_data);
// 这时 tmps 的内容类似 ({"q01","q02",...})
// 对题目做乱数排序
tmps=sort_array(tmps,"random_sort",this_object());
j=sizeof(tmps);
write(sprintf("本次测验共 %d 道题目,每题 %d 分,总分 100 分.\n\n"+
"--测验开始,请按 ENTER 键继续--",j,100/j));
input_to("test_start",0,test_data,tmps,j,0,str);
return 1;
}
int test_start(string str,mapping test_data,mixed tmps,int j,int s)
{
string* tmps2=([]);
string choose;
int i,k;
if(s>0)
{
// 代表玩家已开始答题, 做答题的相关侦测
// 例如 atoi(str) = 玩家选择了该题的第几个选项
}
if(s>=j || str=="q")
{
write("测验结束。\n");
return 1;
}
// 随机选
choose=tmps[random(j)];
tmps2=test_data[choose];
tmps2=sort_array(tmps2,"random_sort",this_object());
str=sprintf("%2d.%s\n",s+1,tmps2[0]);
k=sizeof(tmps2);
for(i=1;i<k;i++)
str+=sprintf(" %d.%s\n",i,tmps2[i]);
write(str+"请选择: ");
// 将需回答的题目减少
tmps-=({choose});
// 循环 input,s+1 代表玩家已回答几题
input_to("test_start",0,test_data,tmps,j,
s+1,str);
return 1;
}
上面纯粹不进行答案校正及回答储存,只让玩家答完 10 题
在 s>0 的判断部份,主要看各家 mud 的做法,以圣殿来说
一般我会将它存在玩家的 temp_data 区,做为玩家本次上线
时答题的状况,例如玩家每答一题:
// 玩家在 choose 这一题上回答的是第 atoi(str) 个选项
this_player()->set_temp("testing/"+choose,atoi(str));
最後讲一下测验系统的核心重点,其实是在於题库的扩充及
维护上,需注意几个地方..
一、题库需易於扩充。
二、需设计题库的简易搜寻功能。
三、尽可能以汇入的方式而非人工手动 key-in 的方式维护
题库
四、最好采取分散式储存架构,避免 题库.o 档日後单一档
案过於肥大的问题(因为题目都是中英文字混杂长度长)
圣殿有打算在玩家进阶职业时做该职业的相关测验,题库可
能几十题,每次随机抽10题,玩家需得到一定分数才能得到
进阶的资格这类的。
那因为玩家日後多半会自行建立所有题库及答案的索引,所
以从这点来出发,我们 wiz 也就尽量不要太用心去设计题目
及测验系统,简单、方便就好,因此重点就在於「易於扩充
及维护」,比方某年某月某日你突然又增加 10 个题目到题
库中,玩家就得再更新它的题库答案索引,我想玩家迟早会
发现「与其每次都得辛苦地这样做,不如老老实实地专心回
答问题」。
Laechan
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 210.61.157.53
1F:推 kyoe :老老实实地专心做BOT无误 1.163.12.224 01/21 16:39
2F:→ laechan :理论上选项只要改几个字,就得重写bot 210.61.157.53 01/21 17:20
3F:推 QQmother :kyoe没gg 123.192.148.71 01/21 18:59