Contents ...
udn網路城邦
[Excel VBA] 九宮格智慧盤遊戲程式原理(上)
2009/03/13 21:05
瀏覽9,006
迴響3
推薦1
引用0

前一篇介紹的九宮格智慧盤遊戲,程式分成兩個部份,一個是模組裡的部份 ,一個是 Userform 的部份。模組裡的是計時的 Timer 程式碼,它不是這個遊戲的重點 (不計時也可以),在此暫且略過。我想介紹的是遊戲視窗 (也就是 Userform) 裡那些方塊按鈕的原理。

製作主要的元件

開始設計的時候,首先在Excel VBE 編輯環境裡新增一個表單, 也就是 Userform,然後在這個 Userform 上做一個正方形的 CommandButton 按鈕,它的控制項名稱 (Name屬性) 為 "CommandButton1"。把 CommandButton1 的 "Font" 屬性改成粗體而且較大的字型,然後把個這按鈕複製出另外 8 個,所以就有 CommandButton1~CommandButton9 總共 9 個按鈕。把 CommandButton1 的 "Caption" 屬性,也就是按鈕上顯示的文字,改成 "1"

、CommandButton1 的 "Caption" 屬性改成 "2"......依此類推,惟有 CommandButton9 的 "Caption" 屬性改成空的(什麼都沒有)。

把這 9 個按鈕依上圖的順序排成所謂的「九宮格」,於是我們就把智慧盤的九個方塊做好了。讀到後面你就會知道,這 CommandButton1~CommandButton9 的排列位置非常重要。最後,再增加一個 CommandButton10做為 "開始/重玩" 鈕。

怎麼改變方塊按鈕的屬性?

接下來,就從 UserForm 被 show 出來的時候講起。在 UserForm_Initialize() 裡面要做的初始化工作包括:把計時與計次等等的變數歸零、用 Inputbox 請玩家輸入姓名,還有就是使那 9 個方塊按鈕無效 (呈現淡色的狀態)。

"使按鈕無效" 就是要把它的 "Enabled" 屬性設為 "False",當遊戲開始的時候,要 "使按鈕有效" 就是要把它的 "Enabled" 屬性設為 "True"。因為程式裡會重複用到,所以我寫成兩個副程式:


 Sub DisableBlocks() '使那 9 個方塊按鈕無效
Dim i As Integer
For i = 1 To 9
    Controls("CommandButton" & i).Enabled = False
Next i
End Sub

Sub EnableBlocks() '使那 9 個方塊按鈕有效
Dim i As Integer
For i = 1 To 9
    Controls("CommandButton" & i).Enabled = True
Next i
End Sub


在兩個副程式裡,你可以看到「Controls(控制項名稱).屬性」這樣的寫法來改按鈕的屬性,這裡也示範了利用方塊按鈕名稱的特徵,以 for......next 迴圈一次解決 9 個按鈕的屬性更改。

這 9 個按鈕的名稱特徵,就是最右邊依序是 1~9 的數字,在這個遊戲的程式裡,這是非常非常重要的。我們可以在 VBE 裡,手動更改按鈕的名稱,也就是它的 "Name"屬性。事實上,可以把 "CommandButton" 統統改成 "c" 和 "x"、"Block"......etc. 都可以,只要有那個數字在,而且程式碼裡寫的和按鈕的名稱一致就可以。為了讓大家容易了解程式正在處理的控制項是按鈕,我刻意不改掉 "CommandButton" 。

怎麼把方塊的排列順序弄亂?

當玩家按下 "開始/重玩" 鈕的時候,CommandButton10_Click() 裡會做底下這幾件事:


Private Sub CommandButton10_Click() '開始/重玩 鈕
Call ResetGame '重設比賽
StartGame = True
Call EnableBlocks '使那 9 個方塊按鈕有效
Call StartTimer '開始計時
End Sub

"重設比賽" 除了把移動次數和使用時間歸零之外,最重要工作是,要把方塊的排列順序弄亂。「把方塊的排列順序弄亂」其實並沒有移動那九個按鈕,而是更改它們上面顯示的數字,也就是更改它們的 "Caption" 屬性。

在 ResetGame() 裡,For ...... Next 迴圈會執行 9 次,依次會決定一個按鈕上要顯示的數字。For ...... Next 迴圈裡要設給按鈕上的數字,是以 Rnd() 產生亂數運算出 0~8 的整數,為了避免重複,把已過用的數儲存到陣列裡,用來核對。


Sub ResetGame()      '重設比賽
Dim RndNum As Integer, a(9) As Integer, i As Integer
Dim NewNum As Boolean

Randomize '亂數產生器初始化

For i = 1 To 9
    Do
        RndNum = Int(Rnd() * 9) '產生 0~8 的亂數
        NewNum = True
        If i > 1 Then   '檢查 a 陣列裡是否已有此整數
            For j = 1 To i - 1
                If a(j) = RndNum Then NewNum = False
            Next j
        End If
    Loop While Not NewNum '重覆此迴圈直到產生的整數是 a 陣列裡沒有的

    a(i) = RndNum '把這個整數加入 a 陣列
   
    If RndNum = 0 Then
        Controls("CommandButton" & i).Caption = ""       '0 號是空白方塊, 上面不要字
    Else
        Controls("CommandButton" & i).Caption = Str(a(i)) '把這個整數 show 在第 i 個按鈕
    End If
Next i

Moves = 0 '移動次數歸零
LapseTime = 0 '使用時間歸零
Label2.Caption = CStr(Moves)
Label4.Caption = CStr(LapseTime)

End Sub



所以,ResetGame() 被呼叫之後,玩家看到的情況可能會是這樣:CommandButton1 上面顯示的是 "7"、CommandButton2 上面顯示的是 "4"、CommandButton3 上面顯示的是空白......等等,其實每個 CommandButton 都還在它的原位上沒動。

接下來,玩家就會用滑鼠指標去點他想移動的方塊。

移動?......對啦!現在你知道了吧!所謂的「移動」也只是「改

 上面顯示的數字」而已!我們下回分解。

相關文章:3x3九宮格智慧盤小遊戲  九宮格智慧盤遊戲程式原理(下)

有誰推薦more
迴響(3) :
3樓. VBA
2017/06/10 13:00

能否將這個遊戲的程式碼寄給我呢

照著您的程式碼作有些地方無法執行耶

可以麻煩您將程式寄給我嗎B10321034@yuntech.edu.tw

感信您了

(B10321034@yuntech.edu.tw)
2樓. 路人
2011/05/17 20:05
關於重設盤面數字的邏輯
如果不是真的在背景模擬每一塊拼圖的移動,
而只是隨機將數字印到每一個拼圖上,
是否有可能會產生無解的拼圖呢?
嗯,"solution 是不是一定存在? " 很有趣的問題!
我自己用經驗玩出一套方法 "似乎" 可以解所有的情況,
只是不見得是最佳 (移動次數最少的)。
很久沒玩,那套方法現在已記不清楚了!
ThisIsTheWay2011/06/21 11:54回覆
1樓. Diane
2009/03/20 12:39
圖形和數字有不同嗎?

我之前都是玩5x5的,所以看到9格的就直覺以為是數讀,真是糟糕^^

如果推推遊戲是由圖形構成,對寫程式的人而言,會比較難嗎?破解的方法也是和數字一樣,一定要依序(1~24)移動到正確位置,才會是最快的解法嗎?

這裡可以連結到圖形的推推遊戲,http://slidingpuzzle.net/default.aspx?Go=H,右邊可以選擇難度

那個網站的圖形推推遊戲是依特定順序把圖形弄亂的, 所以依相反順序推回原狀就是最佳解法

我寫的數字推推樂是用亂數決定數字的位置, 所以不知最佳解是什麼!!

那個圖形的遊戲, 它的程式是真的移動圖形, 所以程式比我的複雜很多......N倍吧!

玩起來的困難度也較高, 我弄了一個黃小鴨的圖形的, 你玩玩看, 很難喔......

 http://slidingpuzzle.net?PicURL=http://album.udn.com/community/img/PSN_PHOTO/WayCheng/f_3006440_1.jpg&Size=50&Go=E&Hd=Duck+Puzzle

(因為有一塊是白的  )

ThisIsTheWay2009/03/21 14:27回覆

發表迴響

會員登入