網路城邦
上一篇 回創作列表 下一篇   字體:
[Excel VBA] 九宮格智慧盤遊戲程式原理(下)
2009/03/14 19:39:02瀏覽5542|回應1|推薦1

前一篇 "九宮格智慧盤遊戲程式原理(上)" 說明了,「把方塊的排列順序弄亂」其實只是更改它們上面顯示的數字。接下來,我們就來看 "移動" 和 "判斷是否完成" 的原理。

因為網誌版面寬度有限,在這一篇中,我把程式裡的 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九宮格智慧盤小遊戲

( 興趣嗜好電腦3C )
回應 推薦文章 列印 加入我的文摘
上一篇 回創作列表 下一篇

引用
引用網址:https://classic-blog.udn.com/article/trackback.jsp?uid=WayCheng&aid=2744458

 回應文章


有問題請教
2010/01/02 21:59

不好意思~可以問一下

因為我有按照你寫的方法下去做

可是一直卡在移動數字的地方

我想問 是不是多設到一個StopGame

我看下面沒這個指令

還有Neighbors要假設嗎?

因為這樣怎麼知道他對應到哪個按鈕

不好意思~問題有點多