作者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
推 kyoe :老老實實地專心做BOT無誤 1.163.12.224 01/21 16:39
→ laechan :理論上選項只要改幾個字,就得重寫bot 210.61.157.53 01/21 17:20
推 QQmother :kyoe沒gg 123.192.148.71 01/21 18:59