前一篇 "九宮格智慧盤遊戲程式原理(上)" 說明了,「把方塊的排列順序弄亂」其實只是更改它們上面顯示的數字。接下來,我們就來看 "移動" 和 "判斷是否完成" 的原理。
因為網誌版面寬度有限,在這一篇中,我把程式裡的 CommandButton 全部改成 x。
方塊怎麼移動位置?
這個遊戲的操作方法,是點某個數字方塊,如果這個方塊的旁邊有空白方塊,這個數字方塊就會和空白方塊互換位置。程式的做法,其實是讓它們互換數字。我們首先來看那 9 個方塊按鈕,它們被點 (click) 的時候要執行的就像這樣:
Private Sub x1_Click()
BlockRoutine
End Sub
九個都一樣嗎?是的!x1_Click()、x2_Click()、x3_Click() ...... 程式碼都一樣,就是呼叫 BlockRoutine() 副程式。
Sub BlockRoutine() '方塊按鈕要做的事
If StartGame Then '若game已開始就
ThisBtn = Right(ActiveControl.Name, 1) '取得名稱最右的一個字元
Call SwapBlank(ThisBtn) '看看要不要交換?
If IsDone Then Call StopGame '若已完成,就停止遊戲
End If
End Sub
重點來了!在 BlockRoutine() 會取得這個 (被點到的) 按鈕的名稱最右的一個字元 (就是 x 右邊的那個數字),傳給 SwapBlank() 副程式,由 SwapBlank() 去判斷和執行交換數字的工作。
SwapBlank() 從 BlockRoutine() 傳給它的 "按鈕的名稱最右的一個字元" (參數 BtnNo),就可以得到 (被點到的這個) 按鈕方塊上的數字,請對照底下的程式碼,就是 Controls("x" & BtnNo).Caption,沒有問題。
SwapBlank() 要將 (被點到的這個) 按鈕方塊上的數字,與相鄰的空白方塊按鈕交換。它必須去檢查 "相鄰的" 按鈕方塊哪一個的 Caption 是空白的 (如果它自己的 Caption 是空白,就不需去檢查相鄰的),那誰是與它相鄰的呢?
我用一個二維陣列 (array) 把每個按鈕的鄰居 (neighbors) 列出來。請對照底下的程式碼,Neighbors 陣列的內容由
上往下看:Array("2", "4") 表示 x1 的鄰居有 x2 和 x4,Array("1", "3", "5") 表示 x2 的鄰居有 x1 和 x3 和 x5......。舉例來說,程式裡若要知道 x5 的鄰居有哪些要怎麼寫呢?像這樣查表:
Neighbors(5)(1) --> "2" --> x2
Neighbors(5)(2) --> "4" --> x4
Neighbors(5)(3) --> "6" --> x6
Neighbors(5)(4) --> "8" --> x8
*註:因為我的 Userform1 程式碼開頭第一列寫了 Option Base 1,所以陣列的最小註標 (index) 是從 1 開始。
請看程式碼裡面的註解,應該就可以了解 SwapBlank() 裡的邏輯。
Sub SwapBlank(BtnNo As Variant)
Dim i As Integer
Dim Neighbors
Neighbors = Array(Array("2", "4"), _
Array("1", "3", "5"), _
Array("2", "6"), _
Array("1", "5", "7"), _
Array("2", "4", "6", "8"), _
Array("3", "5", "9"), _
Array("4", "8"), _
Array("5", "7", "9"), _
Array("6", "8"))
If Controls("x" & BtnNo).Caption <> "" Then '若這不是空白方塊按鈕, 就
For i = 1 To UBound(Neighbors(BtnNo)) '檢查每個相鄰方塊按鈕上的數字
If Controls("x" & Neighbors(BtnNo)(i)).Caption = "" Then '若是鄰居是空白
Controls("x" & Neighbors(BtnNo)(i)).Caption = Controls("x" & BtnNo).Caption '就把數字給它
Controls("x" & BtnNo).Caption = "" '然後將此按鈕的顯示設為空白
Moves = Moves + 1 '移動次數增加一次
Label2.Caption = CStr(Moves) '更新移動次數顯示
Exit For '已完成交換就可以跳出迴圈
End If
Next i
End If
End Sub
怎麼知道已經完成了?
BlockRoutine() 呼叫 SwapBlank() 之後,就會呼叫 IsDone(),如果九個方塊上的數字都回到原位了,IsDone() 會傳回 True。九個方塊上的數字都回到原位,就是說:x1 上面的數字應 1, x2 上面的數字為 2,......依此類推:
Function IsDone() As Boolean
Dim i As Integer
IsDone = True
For i = 1 To 8
If Val(Controls("x" & i).Caption) <> i Then IsDone = False
Next i
End Function
這個函式用一個 for ...... next 迴圈迅速的做完 1~8 號按鈕的檢查,只要有任何一個不符合條件,就傳回 False。第九個 (x9) 上面的字應為空白, 但不需檢查。
相關文章:3x3九宮格智慧盤小遊戲
- 1樓. 錚2010/01/02 21:59有問題請教
不好意思~可以問一下
因為我有按照你寫的方法下去做
可是一直卡在移動數字的地方
我想問 是不是多設到一個StopGame
我看下面沒這個指令
還有Neighbors要假設嗎?
因為這樣怎麼知道他對應到哪個按鈕
不好意思~問題有點多