Excel+VBA製作小遊戲:掃雷

上次做完2048又收到一大波點贊和關注,誠惶誠恐。因為不善言辭,評論中的溢美之詞我只好暗搓搓的愧領,不知如何回復。WIN10的掃雷下載起來太麻煩,這周做了個掃雷自己玩,拿出來跟大家分享一下。

關於掃雷,這裡放一個傳送門:Excel 到底有多厲害? - 雨少主的回答 - 知乎,這位答主VBA水平甩我好幾個省外加一個電飯鍋,評論里還有輪子哥的回復,於是水平有限的我只好拿出一個粗糙又簡陋的掃雷來讓大家嘲笑。

一、準備界面

Win7之前自帶掃雷是能選擇難度的,簡單、普通、困難遊戲棋盤大小分別為9*9、16*16、16*30,雷的數量分別為10、40、99,支持自定義。遊戲基本操作包括:左鍵單擊 、右鍵單擊、左右鍵同時按下,受Excel限制,這些操作我們無法完全用滑鼠完成。

Excel工作表中自帶的事件與之類似的有:Worksheet_SelectionChange、Worksheet_BeforeRightClick、Worksheet_BeforeDoubleClick。不過可惜的是,後兩個事件在觸發前都會出發第一個事件,所以只好像頭圖那樣,把三個操作放到按鈕中……

我們先需要兩塊「內存」區域,來存放生成的雷區以及每個單元格的狀態,所以把Sheet1和Sheet2徵用,Sheet3作為遊戲界面。我們需要的界面是:列寬2,字體等線,加粗,單元格所有框線,粗外側框線。

這裡給每個格子不同數字添加不同顏色,我用了一個巧妙的方法,可惜這裡太小寫不下(劃掉)。我們都知道,如果對每個單元格都進行操作,因為Cell對象的十分複雜, 所以一定會影響運行速度。這裡我們使用的是條件格式的方法,在給單元格區域賦值後,讓他自動改變顏色。我設置的規則如下:

界面的樣式我們可以手動設置,也可以通過錄製宏的方法拿到代碼,然後通過遊戲初始化方法根據界面大小自動設置。代碼如下:

Private Sub Game_Interface_Init(ByVal r As Integer, ByVal c As Integer)Sheet3.UsedRange.ClearSheet3.Range(Cells(1, 1), Cells(r, c)).SelectWith Selection .ColumnWidth = 2 .Font.Bold = True .HorizontalAlignment = xlCenter .Borders.LineStyle = xlContinuous .Borders.Weight = xlThin .BorderAround Weight:=xlMedium .FormatConditions.Add(Type:=xlCellValue, Operator:=xlEqual, Formula1:="=1").Font.Color = RGB(0, 112, 192) .FormatConditions.Add(Type:=xlCellValue, Operator:=xlEqual, Formula1:="=2").Font.Color = RGB(0, 176, 80) .FormatConditions.Add(Type:=xlCellValue, Operator:=xlEqual, Formula1:="=3").Font.Color = RGB(192, 0, 0) .FormatConditions.Add(Type:=xlCellValue, Operator:=xlEqual, Formula1:="=4").Font.Color = RGB(0, 32, 96) .Interior.ColorIndex = 15End WithSheet3.Cells(1, 1).SelectEnd Sub

當然,錄製出來的代碼是不可能這麼簡潔的。

二、初始狀態

我們現在以普通難度為例,創建一個遊戲。

Public mineArr 雷區數組, 0 代表無雷, 9 代表有雷, 其他 代表周圍雷數Public statusArr 狀態數組,0 代表未標記, 1 代表標記為雷, 2 代表標記為?, 3 代表打開Public dr, dc 行列變換輔助Public Sub Medium()Call Game_Init(16, 16, 40)Call Game_Interface_Init(16, 16)End Sub

我們先初始化遊戲,再初始化遊戲界面。初始化遊戲時,我們要做的事情有:在16*16的數組中隨機生成40個雷,每生成一個雷的時候將周圍的有效單元格數值+1;生成完後將雷區數組放到Sheet1中,將狀態數組放到Sheet2中,將遊戲狀態標記為進行中(T為進行中,F為結束)。代碼如下:

Private Sub Game_Init(ByVal r As Integer, ByVal c As Integer, ByVal n As Integer)r,c 分別代表行數、列數、雷數ReDim mineArr(1 To r, 1 To c) As IntegerReDim statusArr(1 To r, 1 To c) As IntegerDim dr, dc 行列變換輔助dr = Array(-1, -1, -1, 0, 0, 1, 1, 1)dc = Array(-1, 0, 1, -1, 1, -1, 0, 1)Dim x%, y%, k%, sum% x,y 分別代表橫、縱坐標Randomize (Timer)Do k = Int(r * c * Rnd()) x = Int(k / c) + 1 y = k Mod c + 1 If mineArr(x, y) <> 9 Then Call Mine_Add(x, y, r, c) sum = sum + 1 End If Loop While (sum < n)Sheet1.ActivateSheet1.UsedRange.ClearContentsSheet1.Range(Cells(1, 1), Cells(r, c)) = mineArrSheet2.ActivateSheet2.UsedRange.ClearContentsSheet2.Range(Cells(1, 1), Cells(r, c)) = statusArrSheet3.ActivateSheet3.Range("zz1") = "T"End Sub

這裡規定r、c為行列數,x、y為橫縱坐標,m、n為改變後的橫縱坐標,統一定義一下,我懶得寫很長的變數名了,然而我英文也不好。

這裡的循環中,前三行代碼是很經典的一維轉二維的演算法,之前也有提過。然後是一個判斷,在沒有雷的地方才會增加一顆雷。增加雷的Mine_Add方法如下:

Private Sub Mine_Add(ByVal x As Integer, ByVal y As Integer, ByVal r As Integer, ByVal c As Integer)mineArr(x, y) = 9Dim m%, n% m,n 分別代表移動後的橫縱坐標For i = 0 To 7 m = x + dr(i) n = y + dc(i) If Cell_Effective(m, n) Then If mineArr(m, n) <> 9 Then mineArr(m, n) = mineArr(m, n) + 1 End IfNext iEnd Sub

這裡增加雷利用了之前定義的公共變數行列變換輔助數組,我們通過0到7的循環在原有坐標的基礎上改變坐標,來遍歷雷點位置周圍的8個單元格。當然先要經過有效性判斷,再往周圍不是雷的單元格數值上+1,單元格有效性判斷代碼如下:

Private Function Cell_Effective(ByVal m As Integer, ByVal n As Integer) As BooleanCell_Effective = Falser = UBound(statusArr)c = UBound(statusArr, 2)If m >= 1 And m <= r And n >= 1 And n <= c Then Cell_Effective = TrueEnd Function

三、遊戲操作

遊戲操作包括左鍵單擊、右鍵單擊、左右鍵同時按下(雙擊),分別對應的效果是:

左鍵單擊:打開單元格,如果打開的是0,則遞歸打開相鄰相鄰的方塊;如果是數字1~8,則只打開這一單元格;如果是數字9,則觸雷,遊戲結束。

右鍵單擊:單擊一次,標記為地雷;再單擊一次,標記為問號;再單擊一次,清除標記。

雙擊:如果周為標記的地雷和數字相同,則對其他未打開的單元格進行左鍵單擊的操作。

1、左鍵單擊

我們在Excel中將三個操作寫成三個方法,通過選擇單元格後,點擊按鈕來調用。因為雙擊需要調用左鍵方法,所以我們把左鍵的單擊事件和按鈕調用方法分離。代碼如下:

Public Sub Left_Click()If Sheet3.Range("zz1") = "F" Then Exit Subx = ActiveCell.Rowy = ActiveCell.ColumnmineArr = Sheet1.UsedRangestatusArr = Sheet2.UsedRangeCall Left_Click_Event(x, y)Call Game_Win()End SubPrivate Sub Left_Click_Event(ByVal x As Integer, ByVal y As Integer)Dim r%, c%r = UBound(statusArr)c = UBound(statusArr, 2)If Cell_Effective(x, y) = False Then Exit Subdr = Array(-1, -1, -1, 0, 0, 1, 1, 1)dc = Array(-1, 0, 1, -1, 1, -1, 0, 1)numlist = Array(-c - 1, -c, -c + 1, -1, 1, c - 1, c, c + 1)If mineArr(x, y) = 9 Then Call Game_Over(x, y) Exit SubElseIf mineArr(x, y) > 0 Then Call Open_Cell(x, y)Else Dim checkList, checkedList Set checkList = CreateObject("Scripting.Dictionary") Set checkedList = CreateObject("Scripting.Dictionary") checkList.Add (x - 1) * c + (y - 1), 1 Do While (checkList.Count > 0) Dim key, a%, b% For Each key In checkList a = Int(key / c) + 1 b = key Mod c + 1 Call Open_Cell(a, b) checkList.Remove (key) checkedList.Add key, 1 For i = 0 To 7 Dim m%, n% m = a + dr(i) n = b + dc(i) If Cell_Effective(m, n) Then If statusArr(m, n) = 0 And checkList.Exists(key + numlist(i)) = False And checkedList.Exists(key + numlist(i)) = False Then If mineArr(m, n) = 0 Then checkList.Add key + numlist(i), 1 Else checkedList.Add key + numlist(i), 1 Call Open_Cell(m, n) End If End If End If Next i Next Loop End IfEnd Sub

單擊左鍵的時候先判斷遊戲狀態是否是進行中,然後獲取坐標,觸發左鍵單擊的事件。事件結束,判斷一下遊戲是否勝利,代碼如下:

Private Sub Game_Win()Application.ScreenUpdating = FalseSheet2.ActivateSheet2.UsedRange = statusArrSheet3.ActivateApplication.ScreenUpdating = Truer = UBound(statusArr)c = UBound(statusArr, 2)For i = 1 To r For j = 1 To c If mineArr(i, j) = 9 And statusArr(i, j) <> 2 Then Exit Sub If mineArr(i, j) < 9 And statusArr(i, j) <> 3 Then Exit Sub Next jNext iSheet3.Range("zz1") = "F"MsgBox "遊戲勝利!", , "遊戲勝利"End Sub

判斷遊戲勝利的方法中,先把修改後的狀態數組存入到Sheet2的「內存」區域,然後遍曆數組進行判定。如果雷全部被找出,且其他區域全部被點開,則歐繫結束,判定為勝利。

左鍵單擊事件開始,先從「內存」中讀取雷區數組和狀態數組,然後計算出行列數,用我們之前寫的Cell_Effective函數來判斷選擇的單元格是否有效。接下來進入條件分支:

分支1:當該坐標為雷時,調用Game_Over方法,遊戲結束。代碼如下:

Private Sub Game_Over(ByVal x As Integer, ByVal y As Integer)Application.ScreenUpdating = TrueActiveCell.Interior.ColorIndex = 3r = UBound(mineArr)c = UBound(mineArr, 2)For i = 1 To r For j = 1 To c If mineArr(i, j) = 9 And statusArr(i, j) <> 1 Then Sheet3.Cells(i, j) = "●" If mineArr(i, j) <> 9 And statusArr(i, j) = 1 Then Sheet3.Cells(i, j) = "×": Sheet3.Cells(i, j).Font.ColorIndex = 1 Next jNext iSheet3.Range("zz1") = "F"MsgBox "遊戲結束!", , "遊戲結束"End Function

結束遊戲的過程,首先將踩到雷的單元格背景變成紅色,然後便利數組,把所有未標記的雷點找出,然後把標記錯誤的雷點變成×。

分支2:當該坐標為數字時,調用Open_Cell方法,打開單元格。代碼如下:

Private Sub Open_Cell(ByVal x As Integer, ByVal y As Integer)statusArr(x, y) = 3Sheet3.Cells(x, y).Interior.ColorIndex = 0Sheet3.Cells(x, y).Value = mineArr(x, y)End Sub

打開單元格就是把狀態數組標記為3,然後把背景色變成白色,把雷區數組中的數字賦值到單元格中。

分支3:當該坐標為空時,遞歸打開周圍的單元格。這裡用到了一個自增演算法:

建立兩個列表,已檢查(checkedList)和未檢查(checkList),在未檢查列表中有元素時一直循環。先將該坐標單元格放入,遍歷周圍的有效單元格,如果單元格為0,則放入未檢查單元格,進入待檢狀態;如果單元格為數字,則放入已檢查單元格並打開該單元格。最後把該單元格打開,並放入已檢查列表中。

這個演算法的實現較為複雜,循環嵌套較多,我們把演算法代碼單獨拿出來一層一層拆開來講。

Dim checkList, checkedList Set checkList = CreateObject("Scripting.Dictionary") Set checkedList = CreateObject("Scripting.Dictionary") checkList.Add (x - 1) * c + (y - 1), 1 Do While (checkList.Count > 0) Dim key, a%, b% For Each key In checkList a = Int(key / c) + 1 b = key Mod c + 1 Call Open_Cell(a, b) checkList.Remove (key) checkedList.Add key, 1 For i = 0 To 7 Dim m%, n% m = a + dr(i) n = b + dc(i) If Cell_Effective(m, n) Then If statusArr(m, n) = 0 And checkList.Exists(key + numlist(i)) = False And checkedList.Exists(key + numlist(i)) = False Then If mineArr(m, n) = 0 Then checkList.Add key + numlist(i), 1 Else checkedList.Add key + numlist(i), 1 Call Open_Cell(m, n) End If End If End If Next i Next Loop

首先,我用字典對象來作為已檢查和未檢查的存放工具(因為之後要用到Exists方法),然後把單元格索引所謂Key,1作為Item放入字典。通過Do Loop循環,條件是當未檢查字典中元素個數大於0時。循環中,我們通過For Each來遍歷未檢查字典,通過Key也就是索引,計算出臨時單元格坐標a、b。然後調用Open_Cell方法,打開該單元格,並且同時把該Key從未檢查中移除,加入到已檢查中。

接下來,用和之前相同的方法遍歷周圍8個單元格,通過a、b算出臨時坐標m、n,用Cell_Effective確保單元格在有效區域內,還要同時滿足3個條件:未打開過、不在已檢查字典中、不在未檢查字典中。這樣的單元格,如果是空單元格,則加入未檢查中;如果是數字,則加入已檢查中,並打開。

2、右鍵單擊

右鍵單擊標記地雷,十分好實現,代碼如下:

Public Sub Right_Click()If Sheet3.Range("zz1") = "F" Then Exit Subx = ActiveCell.Rowy = ActiveCell.ColumnmineArr = Sheet1.UsedRangestatusArr = Sheet2.UsedRanger = UBound(statusArr)c = UBound(statusArr, 2)If Cell_Effective(x, y) = False Then Exit SubIf statusArr(x, y) <> 3 Then statusArr(x, y) = (statusArr(x, y) + 1) Mod 3 Select Case statusArr(x, y) Case 0 Sheet3.Cells(x, y) = "" Sheet3.Cells(x, y).Font.ColorIndex = 1 Case 1 Sheet3.Cells(x, y) = "" Sheet3.Cells(x, y).Font.ColorIndex = 3 Case 2 Sheet3.Cells(x, y) = "?" Sheet3.Cells(x, y).Font.ColorIndex = 1 End SelectEnd IfCall Game_WinEnd Sub

在未打開的有效單元格上,右鍵單擊是讓狀態數組中的值在0、1、2之間循環,分別對應未標記、標記為雷、標記為問號。結束後再檢查一下遊戲是否勝利。

3、雙擊

雙擊的實現也比較簡單,先計算周圍標記的雷數,如果和該單元格值相同,則遍歷周圍有效單元格,對周圍沒有標記為雷的單元格執行左鍵單擊事件。

Public Sub Chording()If Sheet3.Range("zz1") = "F" Then Exit SubIf ActiveCell.Value = 0 Then Exit SubmineArr = Sheet1.UsedRangestatusArr = Sheet2.UsedRangex = ActiveCell.Rowy = ActiveCell.Columndr = Array(-1, -1, -1, 0, 0, 1, 1, 1)dc = Array(-1, 0, 1, -1, 1, -1, 0, 1)Dim sum%sum = 0For i = 0 To 7 m = x + dr(i) n = y + dc(i) If Cell_Effective(m, n) Then If statusArr(m, n) = 1 Then sum = sum + 1 End IfNext iIf sum < ActiveCell.Value Then Exit SubFor i = 0 To 7 m = x + dr(i) n = y + dc(i) If Cell_Effective(m, n) Then If mineArr(m, n) = 9 And statusArr(m, n) <> 1 Then Call Game_Over(m, n) Exit Sub End If If mineArr(m, n) <> 9 And statusArr(m, n) = 1 Then Call Game_Over(m, n) Exit Sub End If End IfNext iFor i = 0 To 7 m = x + dr(i) n = y + dc(i) If Cell_Effective(m, n) Then If statusArr(m, n) <> 1 Then Call Left_Click_Event(m, n) End IfNext iCall Game_WinEnd Sub

這裡在打開周圍單元格時先做了預判,如果周圍有未標記的雷、或者標記錯的雷,都將直接導致遊戲結束。

以上,掃雷遊戲代碼部分結束,可以自己插入按鈕調用左鍵、右鍵、雙擊的方法,以及不同難度的遊戲初始化方法,也可以自定義難度。完整代碼照例在附錄中。

文件下載:微雲文件-掃雷-黃晨製作

附錄:

Public mineArr 雷區數組, 0 代表無雷, 9 代表有雷, 其他 代表周圍雷數Public statusArr 狀態數組,0 代表未標記, 1 代表標記為雷, 2 代表標記為?, 3 代表打開Public dr, dc 行列變換輔助Public Sub Medium()Call Game_Init(16, 16, 40)Call Game_Interface_Init(16, 16)End SubPrivate Sub Game_Interface_Init(ByVal r As Integer, ByVal c As Integer)Sheet3.UsedRange.ClearSheet3.Range(Cells(1, 1), Cells(r, c)).SelectWith Selection .ColumnWidth = 2 .Font.Bold = True .HorizontalAlignment = xlCenter .Borders.LineStyle = xlContinuous .Borders.Weight = xlThin .BorderAround Weight:=xlMedium .FormatConditions.Add(Type:=xlCellValue, Operator:=xlEqual, Formula1:="=1").Font.Color = RGB(0, 112, 192) .FormatConditions.Add(Type:=xlCellValue, Operator:=xlEqual, Formula1:="=2").Font.Color = RGB(0, 176, 80) .FormatConditions.Add(Type:=xlCellValue, Operator:=xlEqual, Formula1:="=3").Font.Color = RGB(192, 0, 0) .FormatConditions.Add(Type:=xlCellValue, Operator:=xlEqual, Formula1:="=4").Font.Color = RGB(0, 32, 96) .Interior.ColorIndex = 15End WithSheet3.Cells(1, 1).SelectEnd SubPrivate Sub Game_Init(ByVal r As Integer, ByVal c As Integer, ByVal n As Integer)r,c 分別代表行數、列數、雷數ReDim mineArr(1 To r, 1 To c) As IntegerReDim statusArr(1 To r, 1 To c) As Integerdr = Array(-1, -1, -1, 0, 0, 1, 1, 1)dc = Array(-1, 0, 1, -1, 1, -1, 0, 1)Dim x%, y%, k%, sum% x,y 分別代表橫、縱坐標Randomize (Timer)Do k = Int(r * c * Rnd()) x = Int(k / c) + 1 y = k Mod c + 1 If mineArr(x, y) <> 9 Then Call Mine_Add(x, y) sum = sum + 1 End If Loop While (sum < n)Sheet1.ActivateSheet1.UsedRange.ClearContentsSheet1.Range(Cells(1, 1), Cells(r, c)) = mineArrSheet2.ActivateSheet2.UsedRange.ClearContentsSheet2.Range(Cells(1, 1), Cells(r, c)) = statusArrSheet3.ActivateSheet3.Range("zz1") = "T"End SubPrivate Sub Mine_Add(ByVal x As Integer, ByVal y As Integer)mineArr(x, y) = 9Dim m%, n% m,n 分別代表移動後的橫縱坐標For i = 0 To 7 m = x + dr(i) n = y + dc(i) If Cell_Effective(m, n) Then If mineArr(m, n) <> 9 Then mineArr(m, n) = mineArr(m, n) + 1 End IfNext iEnd SubPrivate Function Cell_Effective(ByVal m As Integer, ByVal n As Integer) As BooleanCell_Effective = Falser = UBound(statusArr)c = UBound(statusArr, 2)If m >= 1 And m <= r And n >= 1 And n <= c Then Cell_Effective = TrueEnd FunctionPublic Sub Left_Click()If Sheet3.Range("zz1") = "F" Then Exit Subx = ActiveCell.Rowy = ActiveCell.ColumnmineArr = Sheet1.UsedRangestatusArr = Sheet2.UsedRangeCall Left_Click_Event(x, y)Call Game_WinEnd SubPrivate Sub Game_Win()Application.ScreenUpdating = FalseSheet2.ActivateSheet2.UsedRange = statusArrSheet3.ActivateApplication.ScreenUpdating = Truer = UBound(statusArr)c = UBound(statusArr, 2)For i = 1 To r For j = 1 To c If mineArr(i, j) = 9 And statusArr(i, j) <> 1 Then Exit Sub If mineArr(i, j) < 9 And statusArr(i, j) <> 3 Then Exit Sub Next jNext iSheet3.Range("zz1") = "F"MsgBox "遊戲勝利!", , "遊戲勝利"End SubPrivate Sub Left_Click_Event(ByVal x As Integer, ByVal y As Integer)Dim r%, c%r = UBound(statusArr)c = UBound(statusArr, 2)If Cell_Effective(x, y) = False Then Exit Subdr = Array(-1, -1, -1, 0, 0, 1, 1, 1)dc = Array(-1, 0, 1, -1, 1, -1, 0, 1)numlist = Array(-c - 1, -c, -c + 1, -1, 1, c - 1, c, c + 1)If mineArr(x, y) = 9 Then Call Game_Over(x, y) Exit SubElseIf mineArr(x, y) > 0 Then Call Open_Cell(x, y)Else Dim checkList, checkedList Set checkList = CreateObject("Scripting.Dictionary") Set checkedList = CreateObject("Scripting.Dictionary") checkList.Add (x - 1) * c + (y - 1), 1 Do While (checkList.Count > 0) Dim key, a%, b% For Each key In checkList a = Int(key / c) + 1 b = key Mod c + 1 Call Open_Cell(a, b) checkList.Remove (key) checkedList.Add key, 1 For i = 0 To 7 Dim m%, n% m = a + dr(i) n = b + dc(i) If Cell_Effective(m, n) Then If statusArr(m, n) = 0 And checkList.Exists(key + numlist(i)) = False And checkedList.Exists(key + numlist(i)) = False Then If mineArr(m, n) = 0 Then checkList.Add key + numlist(i), 1 Else checkedList.Add key + numlist(i), 1 Call Open_Cell(m, n) End If End If End If Next i Next Loop End IfEnd SubPrivate Sub Open_Cell(ByVal x As Integer, ByVal y As Integer)statusArr(x, y) = 3Sheet3.Cells(x, y).Interior.ColorIndex = 0If mineArr(x, y) <> 0 Then Sheet3.Cells(x, y).Value = mineArr(x, y)End SubPrivate Sub Game_Over(ByVal x As Integer, ByVal y As Integer)Application.ScreenUpdating = Truer = UBound(mineArr)c = UBound(mineArr, 2)For i = 1 To r For j = 1 To c If mineArr(i, j) = 9 And statusArr(i, j) <> 1 Then Sheet3.Cells(i, j) = "●" If mineArr(i, j) <> 9 And statusArr(i, j) = 1 Then Sheet3.Cells(i, j) = "×": Sheet3.Cells(i, j).Font.ColorIndex = 1 Next jNext iSheet3.Cells(x, y).Interior.ColorIndex = 3Sheet3.Range("zz1") = "F"MsgBox "遊戲結束!", , "遊戲結束"End SubPublic Sub Right_Click()If Sheet3.Range("zz1") = "F" Then Exit Subx = ActiveCell.Rowy = ActiveCell.ColumnmineArr = Sheet1.UsedRangestatusArr = Sheet2.UsedRanger = UBound(statusArr)c = UBound(statusArr, 2)If Cell_Effective(x, y) = False Then Exit SubIf statusArr(x, y) <> 3 Then statusArr(x, y) = (statusArr(x, y) + 1) Mod 3 Select Case statusArr(x, y) Case 0 Sheet3.Cells(x, y) = "" Sheet3.Cells(x, y).Font.ColorIndex = 1 Case 1 Sheet3.Cells(x, y) = "" Sheet3.Cells(x, y).Font.ColorIndex = 3 Case 2 Sheet3.Cells(x, y) = "?" Sheet3.Cells(x, y).Font.ColorIndex = 1 End SelectEnd IfCall Game_WinEnd SubPublic Sub Chording()If Sheet3.Range("zz1") = "F" Then Exit SubIf ActiveCell.Value = 0 Then Exit SubmineArr = Sheet1.UsedRangestatusArr = Sheet2.UsedRangex = ActiveCell.Rowy = ActiveCell.Columndr = Array(-1, -1, -1, 0, 0, 1, 1, 1)dc = Array(-1, 0, 1, -1, 1, -1, 0, 1)Dim sum%sum = 0For i = 0 To 7 m = x + dr(i) n = y + dc(i) If Cell_Effective(m, n) Then If statusArr(m, n) = 1 Then sum = sum + 1 End IfNext iIf sum < ActiveCell.Value Then Exit SubFor i = 0 To 7 m = x + dr(i) n = y + dc(i) If Cell_Effective(m, n) Then If mineArr(m, n) = 9 And statusArr(m, n) <> 1 Then Call Game_Over(m, n) Exit Sub End If If mineArr(m, n) <> 9 And statusArr(m, n) = 1 Then Call Game_Over(m, n) Exit Sub End If End IfNext iFor i = 0 To 7 m = x + dr(i) n = y + dc(i) If Cell_Effective(m, n) Then If statusArr(m, n) <> 1 Then Call Left_Click_Event(m, n) End IfNext iCall Game_WinEnd Sub

推薦閱讀:

《小朋友齊打交2》十幾年過去了,但它依舊讓我熱淚盈眶。
哪些經典的小遊戲讓你百玩不厭?
製作的第一款遊戲沒有人下載,有大神支招嗎?
有什麼能解悶的單機小遊戲?
如何看待 4399 上市不利?

TAG:VBA | Excel编程 | 小游戏 |