1、引言
隨著國內高等教育信息化的推進,辦公自動化等現代信息技術的廣泛應用,考試管理的信息化方面也有了長足的發展。大部分的院系在考試過程中為了做到嚴格紀律,都紛紛采用了隨機排座機制來保障考試的順利進行。但是,傳統的隨機座號機制是通過考前人工排序或在考場內隨機抽號的方式進行的,這就耗費了大量的人力和時間,造成效率低下,為此,我們開發了一個簡單的考場隨機排座系統。
2、設計內容
根據考場隨機排座的要求,整個系統由以下的模塊組成:數據導入、排序處理、打印輸出。除此之外,還要求系統具有良好的人機界面。
數據導入工作的對象是欲排序的名單,由於大部分的學生信息采用Excel格式或者Word文檔格式進行存儲,所以,首要的工作是要將這些格式文檔讀入排座系統。
對於排座系統中各個記錄的隨機排序,應避免VC++中偽隨機數機制可能帶來的影響,為每條記錄分配一個真正的符合數學規律的隨機值。
數據的輸出部分包括模擬顯示和打印兩部分,將對隨機排序後的結果進行輸出,生成考場座次表,和試卷一起密封,方便監考人員在考試之前進行宣讀。
軟件系統主要采用VC++ 6.0編寫,整個系統是基於對話框的應用程序,程序的主界面采用了列表視圖控件,打印和顯示部分則利用了MFC的打印機制。
3、關鍵技術
3.1數據導入
由於每一個考生在入學時就已經在學院的管理系統中具有了相應的信息,只需要將該信息導入排座系統即可,也可以通過人工的方式進行錄入,本系統支持EXCEL和TXT兩種格式的數據導入。EXCEL格式的考生信息導入排座系統的方法主要有兩種:一種是通過ODBC數據接口對Excel格式的文件進行讀取[1],該方法需要熟悉SQL語法和數據庫操作的相關知識,文獻[1]介紹了該方法的詳細操作步驟;另一種方法則是利用工具軟件XLS Converter先將EXCEL格式的文件轉換為TXT文件[2],然後再利用VC本身的文件操作函數進行讀取,本系統采用了這種方法,即利用VC調用文件轉換引擎將Excel轉換為TXT格式。實現的部分核心代碼如下:
cmdline=exePath+"XLSConverter.exe "+"C: empXLS emp.xls"+" txt C: empXLS";
char buf[1024],cmdll[1024];
sprintf(cmdll,"%s",cmdline);
cmdll[sizeof(cmdll)-1]=0;
sprintf(buf,"%s","XLSConverter.exe");
buf[sizeof(buf)-1] = 0;
//通過在新的進程中以命令形式調用轉換引擎XLSConverter.exe
STARTUPINFO startInfo;
startInfo.cb = sizeof(STARTUPINFO);
startInfo.lpReserved = NULL;
startInfo.lpTitle = buf;
startInfo.lpDesktop = NULL;
startInfo.dwX = 0;
startInfo.dwY = 0;
startInfo.dwXSize = 0;
startInfo.dwYSize = 0;
startInfo.dwXCountChars = 0;
startInfo.dwYCountChars = 0;
startInfo.dwFlags = STARTF_USESTDHANDLES;
startInfo.wShowWindow = 0; //SW_SHOWDEFAULT;
startInfo.lpReserved2 = NULL;
startInfo.cbReserved2 = 0;
startInfo.hStdInput = 0;
startInfo.hStdOutput = 0;
startInfo.hStdError = 0;
//產生新的進程,運行命令行,調用轉換引擎進行轉換
int nRet=CreateProcess(
NULL,
cmdll,
NULL,
NULL,
TRUE,
0, //CREATE_NEW_CONSOLE
NULL,
NULL,
&startInfo,
&pidInfo);
if(!nRet)
{
AfxMessageBox("調用引擎失敗,程序將退出!",MB_OK|MB_ICONSTOP);
return -1;
}
DWord dwWait=WaitForSingleObject(pidInfo.hProcess, INFINITE); //等待進程結束
return;
3.2隨機數的產生
隨機數的產生需要一個隨機的種子,而計算機產生的隨機數是通過遞推的方法得到的,必須有一個初始值,也就是通常所說的隨機種子,如果不對隨機種子進行初始化,那麼計算機有一個缺省的隨機種子,這樣每次產生的隨機數序列結果就會完全相同,在VC系統中,隨機種子的初始化是通過srand(int)函數進行的,但是如果給定的參數是一個常量,則每次得到的隨機數序列也會完全相同,即使是使用系統時間作為隨機種子進行初始化srand(GetTickCount()),又不能在每次調用rand()的時候都進行這項操作,因為現在計算機上運行速度比較快,當連續調用rand()函數時,系統的時間還沒有更新,這也不足以保證產生隨機數序列的真正隨機性。
本系統采用了對產生的隨機數序列進行篩選的方法,使得產生的隨機數序列符合一維正態分布的概率密度函數規律,其原理為:若一個數列服從一維正態分布,那麼它的概率密度函數為(其中,為常數,分別代表數學期望和方差[3]),根據一維正態分布的概率密度理論為隨機數序列的均值,代表著隨機數在該處的概率最大,為方差,代表產生的隨機數偏離均值的程度,其概率密度函數曲線如圖1所示,利用rand()函數線性變換後產生的平均隨機數,帶入該函數模型進行驗證,若隨機數的函數值在曲線范圍內,即認為該隨機數符合條件,進行保留,反之,捨棄;基於該方法產生的10000個隨機數序列的統計如圖2所示,從圖2可以看出隨機數序列符合一維正態分布的規律,達到系統所需的隨機數要求。
產生隨機數的核心代碼如下:
//產生有四位小數的min和max之間的一個隨機數
double CRandomGen::AverageRandom(double min, double max)
{
int minInteger = (int)(min*10000);
int maxInteger = (int)(max*10000);
int randInteger = rand()*rand();
int diffInteger = maxInteger - minInteger;
int resultInteger = randInteger % diffInteger + minInteger;
return resultInteger/10000.0;
}
//計算給定隨機數的一位正態分布函數值
double CRandomGen::Normal(double x, double miu, double sigma)
{
return 1.0/(sqrt(2*PI)*sigma)* exp(-1*(x-miu)*(x-miu)/(2*sigma*sigma));
}
//對產生的隨機數進行篩選
double CRandomGen::NormalRandom(double miu, double sigma, double min, double max)
{
double x;
double dScope;
double y;
do
{
x = AverageRandom(min,max);
y = Normal(x, miu, sigma);
dScope = AverageRandom(0, Normal(miu,miu,sigma));
}while( dScope > y);
return x;
}
3.3打印處理
由於整個系統采用了基於對話框的應用程序結構,而基於對話框的應用程序本身不具有文檔/視圖結構,對打印功能的支持有限,所以整個打印處理部分也需要自定義解決,本系統采用了生成臨時CFrameWnd和CView類對象的方法[4]調用系統默認的OnFilePrintPrevIEw()函數來實現打印功能,文獻[4]對此有詳細描述。
4 結束語
本系統運行後的界面如圖3所示,通過該系統可以很方便地實現對考生隨機座號的生成,同時,系統提供的豐富的打印預覽和打印功能也為數據的輸出提供了便利,如圖4。
圖3 程序運行主界面
圖4 打印功能模塊界面
本系統是根據高校考試的需求,結合高校學生信息管理的特點開發的,整個系統具有良好的實用性和可擴充性,已經應用於院系的考試中,能滿足院系環境下的考試管理需求,使用該系統一方面可以減少相關教務和教學管理人員的工作量和勞動強度,增加工作效率,另一方面也提高了考試管理信息化的水平,使得考試管理工作上了一個新的台階,具有非常好的通用性和推廣價值。