張貼者:2010年5月29日 上午6:33Administrator ExcelHelp
[
已更新 2010年5月29日 上午6:34
]
這個遊戲大家還沒有上學該已學會了,但是要放在Excel裡卻不是件簡單的事情,必須掌握自訂表單(Userform)的技巧。
由於我主要想示範一下表單與Static的用法,所以沒有加進什麼 AI(人功智能),電腦不懂跟你玩,只能人與人玩,電腦提供「場地」和當評判。
首先畫一個表單,上有九個按鈕,代表九個格,用戶按一下,我們就在其上「畫」上「○」或「╳」。另外還要一個「離開」按鈕,讓用戶可以提早結束遊戲。

我想表單並不難,最難還是背後的程序:
' 過三關
' Player函數用的常數,代表各動作背後的值。參考Player函數的說明。 Const cInit = 0 ' 起始 Const cRead = 1 ' 報告當前玩家 Const cSwap = 2 ' 轉玩家
' Player函數負責記錄現在到哪一方玩家(○或╳)下棋。 ' 要記錄的只是一個Boolean,對代表○,錯代表╳,其實可以把它放在一個工作表上的 ' 儲存格裡,但為了一個數值而開一個工作表不是很「划算」,所以這裡用了Static,經 ' Static定義的變數,只要程序在運行,它的數值就不會消失。 ' 除了儲存外,這函數還要提供三個動作:起始、報告當前玩家和轉玩家,這三個動作均 ' 由引數決定: ' 引數:cInit - 起始,把當前玩家設定為○(對),也就是說○先下棋 ' cRead - 報告當前玩家,如果沒有引數,這個是默認工作 ' cSwap - 轉玩家,由於只有兩個玩家,所以把Boolean的值對調就可以 ' 返回:不論引數內動作為何,函數均會返回當前玩家,也就是○或╳。 ' ' 注意:1) 為什麼要儲存Boolean值,而不直接儲存文字(字串)「○」或「╳」呢? ' 答案:用文字的話,在轉玩家時很麻煩,用數字或Boolean的話就簡單多了。 ' 2) 這個函數是內部用的,不應該給用戶看到,所以加上「Private」字樣。 Private Function Player(Optional iAction As Integer = cRead) As String Static bPlayer As Boolean
Select Case iAction Case Is = cInit bPlayer = True ' ○先下棋 Case Is = cSwap bPlayer = Not bPlayer ' 對調 End Select
Player = IIf(bPlayer, "○", "╳") End Function
' 當這自訂表格(Userform)顯示出來的時候,需要起始化(initialization) Private Sub Userform_Activate() Player (cInit) ' 起始 LabelMessage.Caption = "開始!請" & Player() & "先下棋" ' 顯示指示 End Sub
' 按動任何一個按鈕,也會執行ButtonPressed程序。 ' 這裡只顯示其中一個按鈕的程式 Private Sub Button11_Click() ButtonPressed ("11") End Sub
' ButtonPressed處理按鈕被鈕後的工作,包括 ' 1)把當前的玩家寫在按鈕上; ' 2)決定當前玩家是否勝出; ' 3)決定遊戲是否完結(和局); ' 4)不然則繼續遊戲。 ' ' 引數:HitButton - 被按按紐的座標(文字) ' ' 注意:如果按鈕上已寫有東西,那代表按鈕只是給重按,不用理會。 Private Sub ButtonPressed(HitButton As String) With Controls("Button" & HitButton) If .Caption = "" Then ' 按鈕上沒有寫任何東西才用理會 .Caption = Player() ' 把當前的玩家寫在按鈕上
If Win(Player()) Then ' 看看當前玩家有沒有勝出 LabelMessage.Caption = Player() & "勝!" ' 顯示適當訊息 DisableButtons ' 把所有沒有選過的按鈕改為失效 Else If Not GameOver() Then ' 沒有玩家勝出的話,看看遊戲完結了沒有 Player (cSwap) ' 更換當前玩家 LabelMessage.Caption = "請" & Player() & "下棋" Else LabelMessage.Caption = "和局" ' 九個格也選了,又沒有人勝出,就是和局 End If End If End If End With End Sub
' Win函數決定引數內的玩家有沒有勝出 ' 引數:sP - 玩家 ' 返回:True - 勝出;False - 沒有勝出 ' ' 注意:這裡沒有用上For...Next迴圈,只是很原始地逐一方向查看玩家是否能連成一線, ' 主要是因為就算用了迴圈也不能省下多少句,反而會很複雜,這樣寫一看就懂,有 ' 它的好處。 Private Function Win(sP As String) As Boolean Win = (Button11.Caption = sP And Button12.Caption = sP And Button13.Caption = sP) Or _ (Button21.Caption = sP And Button22.Caption = sP And Button23.Caption = sP) Or _ (Button31.Caption = sP And Button32.Caption = sP And Button33.Caption = sP) Or _ (Button11.Caption = sP And Button21.Caption = sP And Button31.Caption = sP) Or _ (Button12.Caption = sP And Button22.Caption = sP And Button32.Caption = sP) Or _ (Button13.Caption = sP And Button23.Caption = sP And Button33.Caption = sP) Or _ (Button11.Caption = sP And Button22.Caption = sP And Button33.Caption = sP) Or _ (Button31.Caption = sP And Button22.Caption = sP And Button13.Caption = sP) End Function
' DisableButtons會把所有還沒有選過(空白)的按鈕改為失效(disable),使玩家 ' 在遊戲完結後不能再下棋,否則會擾亂程式。 ' 不乾脆把所有按鈕改為失效,主要因為失效按鈕上的文字會給轉成陰影,看得不清楚。 Private Sub DisableButtons() Dim i As Integer, j As Integer
For i = 1 To 3 For j = 1 To 3 If Controls("Button" & i & j).Caption = "" Then Controls("Button" & i & j).Enabled = False End If Next j Next i End Sub
' GameOver函數看看遊戲是否已完結。如果九個按鈕都已經給選過了(按鈕不是空白), ' 那就代表和局,遊戲已經完結。 Private Function GameOver() As Boolean Dim bTemp As Boolean Dim i As Integer, j As Integer
bTemp = True For i = 1 To 3 For j = 1 To 3 bTemp = bTemp And (Controls("Button" & i & j).Caption <> "") Next j Next i GameOver = bTemp End Function
' 結束遊戲 Private Sub CommandButtonQuit_Click() Unload Me End Sub
結果 執行後,○可以先下棋,只要在適當的按鈕上按一下便可以。

每走一步,Excel也會在適當的方格上「畫」上○或╳,並顯示到哪一方下棋。 玩家可以隨時按「離開」結束遊戲。

當有一方勝出後,Excel會顯示哪一方勝出,並會把沒有選過的按鈕改為失效,不讓玩家們繼續。

如果選完九個格也沒有定勝負的話,Excel會顯示「和局」。

|
|
|
|
|
 Updating...
Administrator ExcelHelp, 2010年5月29日 上午6:34
|