陣列與清單控制項 [學生成績管理][井字遊戲] 10 陣列與清單控制項 [學生成績管理][井字遊戲] 10-1 陣列的基礎 10-2 一維陣列的處理 10-3 建立多維陣列 10-4 動態陣列 10-5 清單控制項 10-6 陣列排序與搜尋
10-1 陣列的基礎-說明 「陣列」(Arrays)是一種程式語言的基本資料結構,屬於一種循序性的資料結構。日常生活最常見的範例是一排信箱,如下圖所示:
10-1 陣列的基礎-VB陣列 Visual Basic語言的陣列屬於參考資料型態,它可以將相同資料型態的變數集合起來,使用一個名稱代表,以索引值存取元素,每一個元素相當於是一個變數,如下圖所示:
10-2 一維陣列的處理 10-2-1 建立一維陣列 10-2-2 For Each迴圈走訪陣列元素 ViLLE – 5.1 陣列的宣告與初值 10-2-2 For Each迴圈走訪陣列元素 ViLLE – 5.2 使用For/Next迴圈走訪陣列
10-2-1 建立一維陣列-說明 「一維陣列」(One-dimensional Arrays)是最基本的陣列結構,擁有一個索引,可以直接使用索引值來存取陣列元素。 陣列是一組變數,如果在程式中需要使用很多相同資料型態的變數時,我們可以直接宣告陣列,而不用宣告一堆變數。陣列是使用索引值來存取陣列的元素值。
10-2-1 建立一維陣列-宣告語法 在Visual Basic語言的陣列也是使用【Dim】關鍵字來宣告,我們可以在宣告同時指定陣列尺寸。一維陣列的宣告語法,如下所示: Dim 陣列名稱(最大索引) As 資料型態 或 Dim 陣列名稱(0 To 最大索引) As 資料型態 上述語法宣告一個名為「陣列名稱」的陣列,其元素個數為括號的最大索引數加一,也可以使用To關鍵字指出其範圍,「資料型態」可以是Visual Basic基本資料型態、String資料型態、結構和類別物件等。
10-2-1 建立一維陣列-宣告範例 例如:宣告一維陣列來儲存學生姓名和期中考成績,如下所示: Dim Names(4) As String Dim MidTerm(0 To 4) As Integer
10-2-1 建立一維陣列-指定初值 在宣告陣列時,我們也可以不指定陣列最大索引值,而直接指定陣列元素的初值,如下所示: Dim Final() As Integer = {60, 89, 75, 68, 90} 上述程式碼宣告的一維陣列Final並沒有指定大小,其大小是初值的個數,陣列索引的最大值是初值個數減一。
10-2-1 建立一維陣列-存取元素 如果宣告的一維陣列沒有指定初值,我們可以使用指定敘述來指定陣列值,如下所示: MidTerm(0) = 70 MidTerm(1) = 79 MidTerm(2) = 65 MidTerm(3) = 98 MidTerm(4) = 60 同樣方式,可以使用索引值來取出陣列元素值,如下所示: Dim grade1, grade2 As Integer grade1 = MidTerm(3) grade2 = Final(3)
10-2-1 建立一維陣列-範例專案 範例專案:Ch10-2-1\學生成績管理 在Windows應用程式建立學生姓名的字串陣列、期中和期末考成績的整數陣列,學號是陣列索引值,只需在TextBox控制項輸入學號的索引值,就可以取得陣列元素值,即查詢學生姓名和成績資料,其執行結果如下圖所示:
ViLLE – 5.1 陣列的宣告與初值 請啟動ViLLE,在【五. 陣列】目錄下,選【1. 陣列的宣告與初值】,按【Run】鈕模擬執行此範例程式,如下圖所示:
10-2-2 For Each迴圈走訪陣列元素-語法 如果需要計算所有學生的總分和平均,我們需要從陣列的第1個元素走訪到最後1個元素。Visual Basic語言的For Each迴圈可以輕鬆走訪整個一維陣列,其語法如下所示: For Each 變數 In 陣列 程式區塊 Next 上述「變數」可以取得陣列的一個元素,變數需要和陣列屬於相同資料型態,迴圈自動從索引0開始,每執行一次迴圈取得一個元素值並且自動移至下一個元素,直到沒有元素為止。
10-2-2 For Each迴圈走訪陣列元素-範例 例如:計算上一節MidTerm陣列元素值的總和,如下所示: For Each element In MidTerm total += element Next 上述程式碼的變數element是陣列元素,每執行一次,就將陣列元素值加到total,最後變數total是陣列元素的總和。
10-2-2 For Each迴圈走訪陣列元素-For/Next迴圈 For index = 0 To 4 sum += Final(index) Next index 上述程式碼使用For/Next迴圈計算Final陣列元素的總和。
10-2-2 For Each迴圈走訪陣列元素-範例專案 這個Windows應用程式是修改與擴充第10-2-1節的【學生成績管理】,新增2個按鈕控制項來計算期中和期末考的總分與平均,程式是使用MsgBox()函數來顯示計算結果,其執行結果如下圖所示:
ViLLE – 5.2 使用For/Next迴圈走訪陣列 請啟動ViLLE,在【五. 陣列】目錄下,選【2. 使用For/Next迴圈走訪陣列】,按【Run】鈕模擬執行此範例程式,如下圖所示:
10-3 建立多維陣列-說明 「二維陣列」(Two-dimensional Array)或多維陣列都是一維陣列的擴充。如果將一維陣列想像成一度空間的線,二維陣列就是二度空間的平面;三維陣列即空間。 在日常生活中的二維陣列應用非常廣泛,只要是平面的表格,都可以轉換成二維陣列來表示。例如:月曆、功課表和成績單等。 ViLLE – 5.4 二維陣列
10-3 建立多維陣列-宣告二維陣列 在Visual Basic語言宣告二維與多維陣列和一維陣列相似,只是每多一個維度,就需新增1個索引,所以,二維陣列在宣告時需要指定2個維度的陣列尺寸,例如:將第10-2-1節2個一維陣列的考試成績改為1個二維陣列,如下所示:如下所示: Dim Grades(1, 4) As Integer 上述程式碼可以宣告2x5的二維陣列,其元素數就是2個尺寸5的一維陣列。
10-3 建立多維陣列-指定元素初值 二維陣列也可以不指定陣列最大索引值,直接指定陣列元素的初值,如下所示: Dim Grades(,) As Integer = { {70, 79, 65, 98, 60}, _ {60, 89, 75, 68, 90} } 上述程式碼宣告二維陣列Grades,並且指定元素值,在第一維有2個元素,每一個元素是一次考試的全班學生成績,這是一維陣列{70, 79, 65, 98, 60}和{60, 89, 75, 68, 90},各擁有5個元素,二維陣列有2x5共10個元素。
10-3 建立多維陣列-圖例 二維陣列擁有2個索引,左索引(Left Index)指出元素位在哪一列,右索引(Right Index)指出位在哪一欄,使用2個索引值就可以存取指定的二維陣列元素,如下圖所示:
10-3 建立多維陣列-存取陣列元素 在宣告二維陣列後,我們可以使用指定敘述來指定二維陣列的元素值,如下所示: Grades(0,0)=70 : Grades(0,1)=79 Grades(0,2)=65 : Grades(0,3)=98 Grades(0,4)=60 : Grades(1,0)=60 Grades(1,1)=89 : Grades(1,2)=75 Grades(1,3)=68 : Grades(1,4)=90
10-3 建立多維陣列-走訪陣列元素 我們可以使用二層巢狀迴圈來走訪二維陣列,如下所示: For i = 0 To 1 For j = 0 To 4 Sums(i) += Grades(i, j) Next j Next i 上述程式碼的第一層迴圈取得第一維陣列,第二層迴圈是第二維陣列。
10-3 建立多維陣列-範例專案 範例專案:Ch10-3\學生成績管理 這個Windows應用程式是修改與擴充第10-2-2節的【學生成績管理】,改為使用二維陣列儲存成績資料,可以計算期中和期末考的總分與平均,程式是在唯讀TextBox多行文字方塊顯示計算結果。其執行結果如下圖所示:
ViLLE – 5.4 二維陣列 請啟動ViLLE,在【五. 陣列】目錄下,選【4. 二維陣列】,按【Run】鈕模擬執行此範例程式,如下圖所示:
10-4 動態陣列-說明 在Visual Basic語言的陣列可以動態調整尺寸,換句話說,如果當初宣告的陣列不夠使用時,我們可以擴充陣列尺寸;如果太大時,可以縮小尺寸,以便有效的進行記憶體管理。 Visual Basic語言是使用【ReDim】關鍵字在程式執行時,重新調整其尺寸,如下所示: Dim Names(4) As Integer ……… ReDim Names(5)
10-4 動態陣列-保留原陣列內容 因為Visual Basic語言的陣列在變更陣列尺寸後可能遺失陣列資料,如果陣列已經擁有內容,請使用Preserve關鍵字來保留原陣列的內容,如下所示: ReDim Preserve Names(5) 上述程式碼可以放大陣列尺寸,當然放大陣列尺寸並不會有問題,如果縮小陣列的話,陣列裁剪部分的資料還是會遺失。
10-4 動態陣列-二維陣列 對於是二維以上的多維陣列,我們可以變更指定維度的尺寸,如果使用Preserve關鍵字,就只能變更最後1個維度的尺寸,如下所示: Dim arrTable(10, 20) ………. ReDim Preserve arrTable(10, 30)
10-4 動態陣列-範例專案 範例專案:Ch10-4\學生成績管理 這個Windows應用程式是修改與擴充第10-2-1節的【學生成績管理】,提供基本管理功能,可以新增和更新學生的成績資料。其執行結果如下圖所示:
10-5 清單控制項 10-5-1 清單控制項的基礎 10-5-2 下拉式清單方塊控制項 10-5-3 清單與核取清單方塊控制項
10-5-1 清單控制項的基礎-說明 清單控制項也是一種選擇功能的控制項,支援單選和複選,其項目是一個「集合物件」(Collections),如同其名就是一組物件的集合,即多個項目控制項物件的集合,可以使用Items屬性來存取此集合物件。
10-5-1 清單控制項的基礎-種類 清單方塊(ListBox):顯示項目清單,使用者可以選取1到多個選項,如右圖所示: 下拉式清單方塊(ComboBox):使用下拉式選單來顯示項目清單,擁有多種顯示方式,如下圖所示: 核取清單方塊(CheckedListBox):它是ListBox控制項的擴充,其中每一個項目都是一個核取方塊,如下圖所示:
10-5-2 下拉式清單方塊控制項-說明 下拉式清單方塊ComboBox擁有多種顯示樣式來選擇項目,並且提供文字方塊來輸入與新增項目資料。ComboBox控制項的常用屬性說明,如下表所示:
10-5-2 下拉式清單方塊控制項- 取得選取的項目 當使用者在ComboBox控制項cboName選取項目後,我們可以使用SelectedIndex屬性來取得索引值,如下所示: index = cboName.SelectedIndex 上述程式碼可以取得使用者選取項目的索引值。
10-5-2 下拉式清單方塊控制項- 編輯項目清單的方法 以ComboBox控制項cboName為例的相關方法說明,如下表所示:
10-5-2 下拉式清單方塊控制項- 範例專案 範例專案:Ch10-5-2\學生成績管理 這個Windows應用程式是修改第10-4節的【學生成績管理】,改為使用ComboBox控制項以姓名來查詢學生成績,一樣提供基本管理功能,可以新增和更新學生的成績資料,其執行結果如下圖所示:
10-5-3 清單與核取清單方塊控制項-ListBox控制項的常用屬性
10-5-3 清單與核取清單方塊控制項-CheckedListBox控制項的常用屬性 CheckedListBox控制項的常用屬性(與ListBox控制項不重複的屬性),如下表所示:
10-5-3 清單與核取清單方塊控制項-取得選取項目(單選) 在Visual Basic程式碼取得ListBox控制項的選取項目,單選是使用SelectedIndex屬性來取得索引值後,使用Items屬性取得項目名稱,如下所示: index = ltbName.SelectedIndex name = ltbName.Items(index) 上述程式碼取得使用者選取項目的索引值後,就可以取得項目名稱字串。
10-5-3 清單與核取清單方塊控制項-取得選取項目(複選) CheckedListBox控制項勾選的項目可能不只一個,此時需要使用For Each迴圈,從CheckedItems集合物件來取得所有勾選的項目,如下所示: For Each name In clbName.CheckedItems ……… Next
10-5-3 清單與核取清單方塊控制項-範例專案 範例專案:Ch10-5-3\學生成績管理 在Windows應用程式使用ListBox控制項來查詢學生成績資料,以複選的CheckedListBox控制項來選擇計算總分與平均的學生清單,其執行結果如下圖所示:
10-6 陣列排序與搜尋 10-6-1 陣列的排序 10-6-2 陣列的搜尋 10-6-3 二維陣列的應用 - 井字遊戲
10-6-1 陣列的排序-基礎 排序工作是將一些資料依照特定原則排列成遞增或遞減的順序。例如:整數陣列Data的內容,如下所示: 原始:Data(0)=89 Data(1)=34 Data(2)=78 Data(3)=45 排序:Data(0)=34<Data(1)=45<Data(2)=78<Data(3)=89 上述陣列以整數值的大小,將陣列內容依遞增的順序來排序。
10-6-1 陣列的排序- 泡沫排序法(說明) 泡沫排序法(Bubble Sort)是使用交換方式進行排序,可以將較小元素逐漸移動至陣列開始,較大元素慢慢浮向陣列的最後,如同水缸中的泡沫,慢慢往上浮,故稱為泡沫排序法。
10-6-1 陣列的排序- 泡沫排序法(過程) 泡沫排序法的排序過程是使用交換方法,在陣列中找尋最大值,例如:排序Data陣列內容,依序比較陣列元素0和1,元素1和2,元素2和3,如果各組的第1個元素比較大,就交換陣列元素,如下所示: Data(0)=89 > Data(1)=34 => Data(0)=34 Data(1)=89 交換 Data(1)=89 > Data(2)=78 => Data(1)=78 Data(2)=89 交換 Data(2)=89 > Data(3)=45 => Data(2)=45 Data(3)=89 交換 上述陣列的最大值89一步一步往陣列尾端移動。完成後,陣列索引3的元素是最大值。接著重複上述步驟,每次縮小1個元素後,再重新比較陣列元素,就可以完成陣列元素的排序。
10-6-1 陣列的排序- 陣列的參數傳遞 程序與函數的參數如果是陣列,因為陣列是一種參考資料型態,使用ByVal傳值呼叫時,可以更改陣列元素的值(成員),如下所示: Sub Bubble(ByVal Data() As Integer) …………. End Sub
10-6-2 陣列的搜尋-基礎 搜尋是在資料中找出是否存在與鍵值相同的資料,如果資料存在就進行後續的資料處理。例如:查尋電話簿是為了找朋友的電話號碼,然後與他連絡。在書局找書也是為了找到後買回家閱讀。搜尋方法依照搜尋的資料分為兩種,如下所示: 沒有排序的資料:針對沒有排序的資料執行搜尋,我們需要從資料的第1個元素開始比較,從頭到尾以確認資料是否存在。 已經排序的資料:因為資料已經排序,所以搜尋就不需從頭開始一一比較。例如:在電話簿找電話,相信沒有人是從電話簿的第1頁開始找,而是直接從姓名出現的頁數開始找,因為電話簿已經依照姓名進行排序。
10-6-2 陣列的搜尋-循序搜尋法 循序搜尋法是從陣列的第1個元素開始走訪整個陣列,然後一個一個比較是否擁有搜尋的鍵值,Visual Basic程式可以使用迴圈走訪陣列,一一比較陣列元素來找出是否有指定的鍵值。
10-6-2 陣列的搜尋-二元搜尋法 二元搜尋法是一種分割資料的搜尋方法,搜尋資料是已經排序的資料。二元搜尋法先檢查排序資料的中間元素,如果等於鍵值就找到;如果小於鍵值,表示資料在前半段;否則在後半段。然後繼續分割半段資料來重覆上述操作,直到找到或已經沒有資料可以分割為止。 例如:Data陣列索引的上下範圍分別是low和high,中間元素mid是(low + high)\2。在執行二元搜尋時分成三種情況,如下所示: 搜尋鍵值小於陣列的中間元素:鍵值在資料陣列的前半部。 搜尋鍵值大於陣列的中間元素:鍵值在資料陣列的後半部。 搜尋鍵值等於陣列的中間元素:找到搜尋的鍵值。
10-6-2 陣列的搜尋-二元搜尋法 範例專案:Ch10-6-2\學生成績管理 這個Windows應用程式是修改第10-5-3節的【學生成績管理】,新增搜尋和排序功能,可以使用二元搜尋和泡沫排序法來搜尋與排序考試的平均成績,其執行結果如下圖所示:
10-6-3 二維陣列的應用 - 井字遊戲 (說明) 井字遊戲是一個大家都一定玩過的小遊戲,在本節範例專案是使用9個按鈕控制項來建立遊戲使用介面,使用二維陣列儲存哪一個位置的按鈕控制項是「O」或「X」,其對應的陣列元素值分別為0和1。 因為使用二維陣列儲存遊戲過程,並且將陣列元素初值指定為-3,所以,只需使用二層巢狀迴圈就可以計算二維陣列的哪一列或哪一欄的和是0(每一個「O」對應的元素值是0,3個0的和是0)或3(每一個「X」對應的元素值是1,3個1的和是3),就表示遊戲結束。
10-6-3 二維陣列的應用 - 井字遊戲 (遊戲結束) 巢狀迴圈走訪整個二維陣列計算total的每一列和,和total1是每一欄的和,If Then條件判斷和是否是0或3,就可以知道遊戲是否結束,如果和是0,表示「O」贏;3表示「X」贏,如下所示: For i As Integer = 0 To 2 total = 0 : total1 = 0 For j As Integer = 0 To 2 total += board(i, j) total1 += board(j, i) Next j …… Next i
10-6-3 二維陣列的應用 - 井字遊戲 (遊戲結束) 至於2個對角線部分是使用運算式來計算其和,如下所示: total = board(0, 0) + board(1, 1) + board(2, 2) total1 = board(2, 0) + board(1, 1) + board(0, 2)
10-6-3 二維陣列的應用 - 井字遊戲 (範例專案) 範例專案:Ch10-6-3\井字遊戲 在Windows應用程式建立井字遊戲,遊戲介面共有9個按鈕,按下按鈕,可以在Button控制項顯示「O」或「X」,如果有任何一欄、一列和對角線是相同的「O」或「X」,就表示贏了且遊戲結束,其執行結果如右圖所示: