Visual Basic .Net (VB.Net) 程式語言案例學習 (06. 題庫測驗系統)
Visual Basic .Net (VB.Net) 程式語言案例學習 (06. 題庫測驗系統)¶
6.1 問題¶
這是一個題庫練習的程式,分為循序練習及模擬(電腦亂數選題)練習,循序練習會依序將題庫中所有題目列出,讓受測者作答。而模擬練習則由電腦出題,抽出一百題讓受測者測驗。題型分為是非題跟選擇題,因此答題介面設計上就必須依照題型而有所變化。最後是成績顯示,顯示答對題數以及答錯題數,並計算出成績。成績計算之後便會顯示正確答案,受測者可以瀏覽所有的正確答案。
6.2 需求¶
表格 6-1 「題庫測驗系統」系統目的分析表
版本:1.0 | 要做什麼 | 不要做什麼(不要做不代表不會做) |
---|---|---|
能做什麼 | (第一格:必要項目) | (第二格:次要項目) |
建立是非題型與選擇題型可共用的資料結構,使用MS Access 2003資料庫。 | 可提供循序練習及模擬練習。 | |
答題區可依照不同題型而提供適當的選擇。 | 結束練習時可瀏覽正確答案。 | |
可以統計答錯題數及答對題數,和最後成績。 | ||
不能做什麼(不能做代表不需要做) | (第三格:不必要項目) | (第四格:不需要項目) |
提供答案的詳解。 | 將資料庫送上SQL,開發成網路版本。 |
表格 6‑2 「題庫測驗系統」系統目標分析表
版本: | 重要 | 不重要 |
---|---|---|
優先 | (重) | (急) |
建立是非題型與選擇題型可共用的資料結構,使用MS Access 2003資料庫。 | 可提供循序練習及模擬練習。 | |
答題區可依照不同題型而提供適當的選擇。 | ||
可以統計答錯題數及答對題數,和最後成績。 | ||
不急迫 | (輕) | (緩) |
結束練習時可瀏覽正確答案。 | 無。 |
表格 6‑3 「題庫測驗系統」系統規格表
規格項目 | 規格內容 | 備註 |
---|---|---|
題型 | 是非題及選擇題。 | … |
練習方式 | 循序測驗及模擬練習。 | … |
成績計算 | 答錯題數、答對題數、最後成績 | … |
瀏覽答案 | 作答完畢後可瀏覽正確答案。 | … |
6.3 特色¶
特點就是麻雀雖小五臟俱全,程式碼很少,卻能夠達到功能及目的。有循序出題及亂數出題的功能,可以做為測驗的工具。
6.4 使用工具¶
語言 | 軟體 |
---|---|
Visual Basic 2005 | MS Visual Studio 2005 .NET、MS Access |
6.5 系統架構¶
圖 6‑1
綜合以上的分析,我們可以很容易得找到使用者操作流程,而測驗軟體主要的使用者也就是受測者,因此介面上儘量依照使用者方便為主,因此由上而下,使用者只須依序點選就可以順利完成測驗,先選擇測驗形式,而後測驗完畢,看成績,瀏覽答案,完畢。
在系統設計方面,我們採用陣列,將題目資料讀入的好處是效率,而不必直接對資料庫作讀取動作,而且也方便往後改版成網路版時,差別只是由SQL Server下載題目資料到陣列而以,之後的動作就與資料庫無關,這樣不但具有效率而且也比較不會有錯誤。
6.6 程式實作¶
Public Class Form1 Inherits System.Windows.Forms.Form ‘宣告題目陣列 Private strExam(0, 0) As String ‘宣告答題陣列 Private strTest(0) As String ‘宣告答案陣列 Private strAnswer(0) As String ‘宣告題目索引 Private intPoint As Integer = 0 ‘宣告總題數 Private intTotalRows As Integer ‘宣告狀態字串 Private strStatus As String = “” ‘程式起始載入事件副程式 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ‘設定題目位置索引 intPoint = 0 ‘設定表單顯示到最大 SetFormScreen() ‘設定超連結 LinkLabel1.Links.Add(0, 35, “”) End Sub ‘開始測驗按鈕被點選事件副程式 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click ‘隱藏開始測驗按鈕 Button1.Visible = False ‘顯示測驗時要用的按鈕 Button2.Visible = True Button3.Visible = True Button4.Visible = True Button5.Visible = True Button6.Visible = True ‘隱藏完成按鈕 Button7.Visible = False ‘顯示文字框 RichTextBox1.Visible = True ‘顯示下拉式選單 ComboBox1.Visible = True ‘將題型選擇禁能 RadioButton1.Enabled = False RadioButton2.Enabled = False ‘顯示題號標籤 Label6.Visible = True ‘狀態設定為測驗 strStatus = “Test” ‘題號索引值設定為零 intPoint = 0 ‘若選擇循序測驗 If RadioButton1.Checked = True Then ‘設定循序測驗資料庫 SetDataBase(1) ‘倘若選擇模擬測驗 ElseIf RadioButton2.Checked = True Then ‘設定模擬測驗資料庫 SetDataBase(2) End If ‘開始測驗函式,並傳入測驗題號索引 ExamTest(intPoint) End Sub ‘測驗函式 Private Sub ExamTest(Optional ByVal intItem As Integer = 0) ‘顯示題數 Label6.Text = “第” & (intPoint + 1).ToString & “ 題/” & intTotalRows.ToString & “ 題” ‘清除下拉式選單 ComboBox1.Items.Clear() ‘增加不作答選項 ComboBox1.Items.Add(“不作答”) ‘藉由題目陣列判斷題型 Select Case strExam(1, intItem) Case “O”, “X” ComboBox1.Items.Add(“O”) ComboBox1.Items.Add(“X”) Case “1”, “2”, “3”, “4” ComboBox1.Items.Add(“1”) ComboBox1.Items.Add(“2”) ComboBox1.Items.Add(“3”) ComboBox1.Items.Add(“4”) End Select ‘顯示題目 RichTextBox1.Text = strExam(2, intItem) ‘設定預設選項為第一項 ComboBox1.SelectedIndex = 0 ‘若有答題 If IsNothing(strTest(intItem)) = False Then ‘設定下拉式選單索引值 Select Case strTest(intItem) Case “O” : ComboBox1.SelectedIndex = 1 Case “X” : ComboBox1.SelectedIndex = 2 Case “1” : ComboBox1.SelectedIndex = 1 Case “2” : ComboBox1.SelectedIndex = 2 Case “3” : ComboBox1.SelectedIndex = 3 Case “4” : ComboBox1.SelectedIndex = 4 End Select End If End Sub ‘答錯題數函式 Private Sub ExamError(Optional ByVal intItem As Integer = 0) ‘顯示題數 Label6.Text = “第” & (intPoint + 1).ToString & “ 題” ‘若為循序練習 If RadioButton1.Checked = True Then ‘清空下拉式選單 ComboBox1.Items.Clear() ‘加入正確答案項目 ComboBox1.Items.Add(strExam(1, strAnswer(intItem) – 1)) ‘設定索引值 ComboBox1.SelectedIndex = 0 ‘顯示題目 RichTextBox1.Text = strExam(2, strAnswer(intItem) – 1) ‘若為模擬練習 ElseIf RadioButton2.Checked = True Then ‘清空下拉式選單 ComboBox1.Items.Clear() ‘加入正確答案 ComboBox1.Items.Add(strExam(1, intItem)) ‘設定索引值 ComboBox1.SelectedIndex = 0 ‘顯示題目 RichTextBox1.Text = strExam(2, intItem) End If End Sub ‘設定表單最大化函式 Private Sub SetFormScreen() ‘宣告螢幕物件 Dim Screens As Screen ‘宣告區域物件 Dim Rect As System.Drawing.Rectangle ‘設定螢幕物件 Screens = Screen.PrimaryScreen ‘設定區域大小 Rect = Screen.GetWorkingArea(Rect) ‘設定表單位置及大小 Me.Top = Rect.Top Me.Left = Rect.Left Me.Height = Rect.Height Me.Width = Rect.Width ‘以下皆是調整控制項的位置及大小 GroupBox1.Left = 10 GroupBox1.Width = Me.Width – 30 GroupBox2.Left = 10 GroupBox2.Width = Me.Width – 30 GroupBox2.Height = Me.Height – GroupBox1.Height – GroupBox3.Height – 70 GroupBox2.Top = GroupBox1.Top + GroupBox1.Height + 10 GroupBox3.Left = 10 GroupBox3.Width = Me.Width – 30 GroupBox3.Top = GroupBox2.Top + GroupBox2.Height + 10 ComboBox1.Top = Button1.Top Button2.Top = GroupBox2.Top + GroupBox2.Height – Button2.Height – 100 Button3.Top = GroupBox2.Top + GroupBox2.Height – Button3.Height – 100 Button4.Top = GroupBox2.Top + GroupBox2.Height – Button4.Height – 100 Button5.Top = GroupBox2.Top + GroupBox2.Height – Button5.Height – 100 Button6.Top = GroupBox2.Top + GroupBox2.Height – Button6.Height – 100 RichTextBox1.Width = GroupBox2.Width – RichTextBox1.Left – 20 RichTextBox1.Height = GroupBox2.Height / 2 LinkLabel1.Top = GroupBox3.Top + GroupBox3.Height – 10 LinkLabel1.Left = GroupBox3.Left + GroupBox3.Width – LinkLabel1.Width – 10 Button7.Left = GroupBox3.Left + GroupBox3.Width – Button7.Width – 20 ‘以下是設定控制項顯示與隱藏 Button2.Visible = False Button3.Visible = False Button4.Visible = False Button5.Visible = False Button6.Visible = False Button7.Visible = False RichTextBox1.Visible = False ComboBox1.Visible = False RadioButton1.Enabled = True RadioButton2.Enabled = True Label6.Visible = False ‘以下是初始化控制項的內容 Label6.Text = “第” & (intPoint + 1).ToString & “ 題/” & intTotalRows.ToString & “ 題” Label4.Text = “0” Label5.Text = “0” Label8.Text = “0” End Sub ‘設定題目資料庫函式 Private Sub SetDataBase(Optional ByVal intSelect As Integer = 1) ‘宣告與資料庫連結的物件 Dim objCnn As New OleDb.OleDbConnection Dim strCnn As String Dim objCmd As New OleDb.OleDbCommand Dim strCmd As String Dim objCmdCount As New OleDb.OleDbCommand Dim strCmdCount As String ‘設定連結字串並建立連結 strCnn = “Provider=Microsoft.Jet.OLEDB.4.0;Data Source =” & Application.StartupPath & “\Exam.mdb” objCnn.ConnectionString = strCnn objCnn.Open() Select Case intSelect ‘循序練習 Case 1 ‘獲得總題數 strCmdCount = “Select Count(*) from 網頁設計丙級學科” objCmdCount.Connection = objCnn objCmdCount.CommandText = strCmdCount intTotalRows = objCmdCount.ExecuteScalar ‘取得資料庫 strCmd = “Select * from 網頁設計丙級學科” objCmd.Connection = objCnn objCmd.CommandText = strCmd ‘獲得資料表內容 Dim objRead As OleDb.OleDbDataReader = objCmd.ExecuteReader ‘宣告動態陣列 ReDim strExam(objRead.FieldCount – 1, intTotalRows) ReDim strTest(intTotalRows) Dim intI As Integer ‘將題目載入至陣列中 For intI = 0 To intTotalRows – 1 objRead.Read() strExam(0, intI) = objRead.Item(0) strExam(1, intI) = objRead.Item(1) strExam(2, intI) = objRead.Item(2) strExam(3, intI) = objRead.Item(3) strExam(4, intI) = objRead.Item(4) Next ‘關閉資料庫讀取物件 objRead.Close() ‘模擬練習 Case 2 ‘設定亂數種子 Randomize() ‘宣告題陣列 Dim aryRnd(100) As Integer Dim intRnd As Integer = 0 Dim intI As Integer = 0 Dim intJ As Integer = 0 Dim blnI As Boolean = False ‘是非題 For intI = 1 To 50 Do Until blnI = True blnI = True intRnd = Cint(Int((500 * Rnd()) + 1)) For intJ = 1 To 50 If aryRnd(intJ) = intRnd Then blnI = False Exit For End If Next Loop aryRnd(intI) = intRnd blnI = False Next ‘選擇題 For intI = 51 To 100 Do Until blnI = True blnI = True intRnd = Cint(Int((500 * Rnd()) + 1)) + 500 For intJ = 51 To 100 If aryRnd(intJ) = intRnd Then blnI = False Exit For End If Next Loop aryRnd(intI) = intRnd blnI = False Next ‘利用字串將題號都串起來 Dim strID As String = “” For intI = 1 To 100 strID = strID & aryRnd(intI) & “,” Next ‘查詢總題數 strCmdCount = “Select Count(*) from 網頁設計丙級學科Where [識別碼] in (“ & strID & “)” objCmdCount.Connection = objCnn objCmdCount.CommandText = strCmdCount intTotalRows = objCmdCount.ExecuteScalar ‘查詢題目內容 strCmd = “Select * from 網頁設計丙級學科Where [識別碼] in (“ & strID & “)” objCmd.Connection = objCnn objCmd.CommandText = strCmd ‘獲得題目內容 Dim objRead As OleDb.OleDbDataReader = objCmd.ExecuteReader ‘設定動態陣列 ReDim strExam(objRead.FieldCount – 1, intTotalRows) ReDim strTest(intTotalRows) ‘將題目讀入到陣列中 For intI = 0 To intTotalRows – 1 objRead.Read() strExam(0, intI) = objRead.Item(0) strExam(1, intI) = objRead.Item(1) strExam(2, intI) = objRead.Item(2) strExam(3, intI) = objRead.Item(3) strExam(4, intI) = objRead.Item(4) Next ‘關閉資料庫讀取物鍵 objRead.Close() End Select ‘關閉資料庫連結 objCnn.Close() End Sub ‘結束測驗按鈕事件副程式 Private Sub Button6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button6.Click ‘隱藏結束測驗按鈕 Button6.Visible = False ‘顯示完全按鈕 Button7.Visible = True ‘清除狀態 strStatus = “” Dim intI As Integer = 0 ‘錯誤題數 Dim intErr As Integer = 0 ‘得分 Dim intErrA As Integer = 0 ‘扣分 Dim dblErrB As Double = 0 ‘統計錯誤題數 For intI = 0 To intTotalRows – 1 If strExam(1, intI) <> strTest(intI) Then intErr += 1 End If Next ‘動態陣列宣告回答陣列 ReDim strAnswer(intErr – 1) Dim intJ As Integer = 0 intJ = 0 ‘紀錄正確答案 For intI = 0 To intTotalRows – 1 ‘當答錯題目時 If strExam(1, intI) <> strTest(intI) Then ‘設定正確答案到陣列中 strAnswer(intJ) = strExam(0, intI) intJ += 1 End If Next ‘顯示答對題數 Label4.Text = (intTotalRows – intErr).ToString ‘顯示答錯題數 Label5.Text = intErr.ToString ‘計算成績歸零 intErrA = 0 dblErrB = 0 ‘開始計算成績 For intI = 0 To intTotalRows – 1 If strExam(1, intI) <> strTest(intI) And strTest(intI) <> “不作答” Then dblErrB = dblErrB + CDbl(strExam(4, intI)) ElseIf strTest(intI) = “不作答” Then ElseIf strExam(1, intI) = strTest(intI) Then intErrA = intErrA + Cint(strExam(3, intI)) End If Next ‘顯示成績 Label8.Text = Iif((intErrA – dblErrB) <= 0, “0”, (intErrA – dblErrB).ToString) ‘重新初始化 intTotalRows = intErr intPoint = 0 ExamError(intPoint) End Sub ‘顯示題目文字框鍵盤事件副程式 Private Sub RichTextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles RichTextBox1.KeyPress ‘禁止輸入 e.Handled = True End Sub ‘第一題按鈕點選事件副程式 Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click strTest(intPoint) = ComboBox1.Text intPoint = 0 If strStatus = “Test” Then ExamTest(intPoint) ElseIf strStatus = “” Then ExamError(intPoint) End If End Sub ‘上一題按鈕點選事件副程式 Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click strTest(intPoint) = ComboBox1.Text intPoint = intPoint – 1 If intPoint < 0 Then intPoint = 0 End If If strStatus = “Test” Then ExamTest(intPoint) ElseIf strStatus = “” Then ExamError(intPoint) End If End Sub ‘下一題按鈕點選事件副程式 Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click strTest(intPoint) = ComboBox1.Text intPoint = intPoint + 1 If intPoint > intTotalRows – 1 Then intPoint = intTotalRows – 1 End If If strStatus = “Test” Then ExamTest(intPoint) ElseIf strStatus = “” Then ExamError(intPoint) End If End Sub ‘最後一題按鈕點選式鍵程式 Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click strTest(intPoint) = ComboBox1.Text intPoint = intTotalRows – 1 If strStatus = “Test” Then ExamTest(intPoint) ElseIf strStatus = “” Then ExamError(intPoint) End If End Sub ‘完成按鈕事件副程式 Private Sub Button7_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button7.Click ‘隱藏所有控制項 RichTextBox1.Visible = False ComboBox1.Visible = False Label6.Visible = False Button1.Visible = True RadioButton1.Enabled = True RadioButton2.Enabled = True Button7.Visible = False Button2.Visible = False Button3.Visible = False Button4.Visible = False Button5.Visible = False ‘初始化控制項內容 strStatus = “” Label4.Text = “0” Label5.Text = “0” Label8.Text = “0” End Sub ‘當下拉是選項有改變時 Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged ‘設定答題內容到陣列 strTest(intPoint) = ComboBox1.Text End Sub ‘當超連結被點選時 Private Sub LinkLabel1_LinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles LinkLabel1.LinkClicked ‘呼叫超連結網頁 System.Diagnostics.Process.Start(e.Link.LinkData.ToString()) End Sub End Class
6.7 修改重點¶
類似測驗的軟體通常都是要收費用的,自己開發一套就免去這種支出,題型方面由於只有是非題跟選擇題,而且皆以文字模式,因此建議讀者修改為可讀圖檔,圖形檔可以代碼為標示崁入在文字題目中,而後由程式判斷應該讀取哪一張圖檔,這種做法是市面上普遍測驗軟體的方法,這樣就可以解決數學公式或是化學符號以及英文看圖問答的題型,一般而言是將文字框置換成網頁瀏覽器物件,透過測驗軟體產生的網頁檔,來做顯示文圖並茂的題目,這種做法會相當方便移植到網頁上,變成網頁版的測試程式。不過並非最佳解,由於非資訊系的教師能力有限,因此有廠商依照教師手寫的考卷文稿,以一題一元新台幣的方式替教師作建檔的服務,這種方式可以說是互惠互利的模式。對於廠商來說有利,對於教師出卷有惠,教師出卷的時候只需要勾勾選選就可以出卷了。由程式設計來看,比較好的解法應該是讓所有題目內的元素皆看成物件,無論是圖形或文字還是符號,透過編輯器安排所在的位置,並將該題型儲存成一個可識別的規格檔,例如:XML。如此程式將更具彈性。
6.8 結論¶
這是一個單機版本的測驗軟體,有利於隨時安裝測驗,而且資料庫的題目可以用Excel匯入,是小而巧的程式。但隨著應用不同,會發現功能不及的地方,倘若是應用於班級上,必須修改成網路版,但若是小班制,其實只需要修改一點,就是透過網路磁碟機的方式,將題庫資料庫放置在主機上,其餘單機只需要連結到主機,設定成網路磁碟機,而程式只需要修改連結路徑,這樣也是另類的網路版測驗軟體。倘若有好幾個班級測驗,也只需要將Access資料庫上傳至SQL Server,當然程式連結的方式就要改成SQL版本,如此一來就變成SQL版本可提供更多學生測驗。
Lai Tai-Yu (賴岱佑)