看到這個(gè)題目,想必你一定會(huì)感到非常驚訝,什么,Excel 居然能開(kāi)發(fā)游戲?沒(méi)錯(cuò),Excel 的強(qiáng)大取決于使用者,遇強(qiáng)則強(qiáng),遇弱則弱。但我這篇文章并不是為了展示 Excel 使用過(guò)程中的奇技淫巧,而是主要寫(xiě)給那些準(zhǔn)備學(xué)習(xí)編程但又沒(méi)什么計(jì)算機(jī)基礎(chǔ)的那些人,或者對(duì) Excel 感興趣的那些人。
對(duì)于那些正在學(xué)習(xí)編程的人,尤其是那些從其他領(lǐng)域跨入這個(gè)行業(yè)的人,興趣才是最大的動(dòng)力。我從事計(jì)算機(jī)編程這么長(zhǎng)時(shí)間,感覺(jué)編程是一件非常有意義的事情。然而我卻我經(jīng)常聽(tīng)到有些人,尤其是那些在校學(xué)生們抱怨說(shuō)編程學(xué)起來(lái)太枯燥了,堅(jiān)持不下去。我覺(jué)得這部分人一方面是方向錯(cuò)了,另一方面就是在實(shí)際學(xué)習(xí)過(guò)程中對(duì)自己做出成果沒(méi)有任何的成就感,而后者,往往占據(jù)了重要原因。
我認(rèn)為,對(duì)于編程的初學(xué)者,選擇第一門(mén)語(yǔ)言應(yīng)該具備下面兩個(gè)特點(diǎn):
1),盡可能簡(jiǎn)單,盡量少與底層硬件(諸如內(nèi)存管理等)相關(guān)聯(lián),調(diào)試方便,IDE 界面簡(jiǎn)單;
2),功能相對(duì)強(qiáng)大,能開(kāi)發(fā)各種小插件工具;
就目前行業(yè)內(nèi)比較常用的編程語(yǔ)言中,能夠同時(shí)滿(mǎn)足上述兩個(gè)特點(diǎn)的也就數(shù) Python,office for VBA,Java 了,然而,Python 雖然簡(jiǎn)單功能又強(qiáng)大,但是需要配置環(huán)境,而且要安裝臃腫的 IDE,這些對(duì)于初學(xué)者來(lái)說(shuō),無(wú)形之中又增加了學(xué)習(xí)成本,更別說(shuō) Java 了,所以剩下的就數(shù) VBA (Visual Basic for Application) 了。VBA 屬于 visual basic 語(yǔ)言的子集,除了繼承了部分 vb 功能外,還特意針對(duì)一些軟件做了接口封裝,使用方便。有人說(shuō) VBA 語(yǔ)法太隨意,對(duì)于初學(xué)者不是件好事,如果學(xué) C 的話(huà),將來(lái)學(xué) C++ 就簡(jiǎn)單很多了。我不同意這種觀(guān)點(diǎn),對(duì)于前者,仁者見(jiàn)仁,但后者就是在扯淡,因?yàn)?C++ 是一門(mén)極其復(fù)雜的編程語(yǔ)言,除了繼承了 C 的繁瑣指針以外,還衍生出了諸如多重繼承、類(lèi)模板、智能指針等恐怖級(jí)別的編程范式,所以說(shuō),對(duì)于初學(xué)者,我不建議直接就去學(xué) C++.
為什么選擇 VBA 作為初學(xué)者的語(yǔ)言呢,因?yàn)樗藵M(mǎn)足上面所說(shuō)的兩個(gè)特點(diǎn)外,還有一些其他的優(yōu)點(diǎn),諸如:
1),使用簡(jiǎn)單:不需要安裝開(kāi)發(fā)工具,更不需要配環(huán)境、安裝語(yǔ)言包,只要你電腦里面有 office 軟件即可。
2),用途廣泛:幾乎所有的工程軟件、辦公軟件都支持用 VBA 做二次開(kāi)發(fā),例如財(cái)務(wù)人員如果發(fā)現(xiàn) Excel 自帶的公式有局限性的話(huà),完全可以自己用 VBA 開(kāi)發(fā)自己需要的控件;機(jī)械設(shè)計(jì)人員如果學(xué)了 VBA 后可以開(kāi)發(fā)一些自己需要的代碼塊,極大程度地提高自己 CAD 的繪圖速度。很難想象,Excel 的重度用戶(hù)尤其是財(cái)務(wù)人員不懂 VBA 的話(huà)他的工作量有多可怕。
3),調(diào)試簡(jiǎn)單方便。
所以,這次我也選擇 VBA 作為這次編寫(xiě) Demo 的語(yǔ)言,為了照顧更多的初學(xué)者,我將每一步的細(xì)節(jié)都盡可能地呈現(xiàn)出來(lái),由于每個(gè) Excel 版本不一樣,我電腦用的是 2010 版的,所以,我就用 2010 版進(jìn)行說(shuō)明,其他版本也一樣,只是界面可能稍有區(qū)別。我相信,只要親手按照我的方法做出這個(gè)游戲,除了你將認(rèn)識(shí)到 Excel 的強(qiáng)大之處外,你也將逐步體會(huì)到編程的樂(lè)趣。鑒于時(shí)間所限,內(nèi)容可能有部分疏忽之處,還望大家提出改正。
下面是正文:
首先看一下游戲最終大致的效果圖:
首先我們思考一下俄羅斯方塊游戲的大致架構(gòu):
1),初始化界面:創(chuàng)建方塊所需要的地圖。
2),隨機(jī)生成俄羅斯方塊:俄羅斯方塊總共有 7 種形態(tài),每種形態(tài)均有 4 個(gè)框格組成,每種方塊各對(duì)應(yīng)一種顏色。可以創(chuàng)建一個(gè)數(shù)組存儲(chǔ)每種方塊的坐標(biāo),再用另外一個(gè)數(shù)組存儲(chǔ)方塊的對(duì)應(yīng)的顏色。
3),移動(dòng)旋轉(zhuǎn)方塊:分為向左,向右,向下。擦拭完后重新繪制,產(chǎn)生移動(dòng)旋轉(zhuǎn)的效果。
4),沒(méi)產(chǎn)生新的方塊,都進(jìn)行一定速度的下落,一旦碰到障礙物,不能下落,再生成新的方塊。
5),不斷掃描是否有任何一行填滿(mǎn),如果為真,則本行刪除,上面下落。每行積分為 10 分。
首先創(chuàng)建一個(gè) Excel 文件,隨意命名。打開(kāi)后,由于 office 默認(rèn)隱藏了開(kāi)發(fā)工具狀態(tài)欄,所以我們需要在 Excel 選項(xiàng) > 自定義功能區(qū)將其調(diào)出來(lái),將其勾選后確認(rèn):
隨后,我們發(fā)現(xiàn)主界面多了開(kāi)發(fā)工具的選項(xiàng):
我們?cè)僭?Sheet1 表格里面將 A~K 列的列寬大致調(diào)成跟行高一樣,讓它大致稱(chēng)為一個(gè)正方形的區(qū)域:
我們點(diǎn)擊 Visual Basic 菜單,打開(kāi)編寫(xiě)代碼界面,我們插入首先插入一個(gè)代碼模塊,用于編寫(xiě)我們自己的代碼:
由于方塊有 7 中形狀,為了讓程序繪制方便,我用一個(gè)三維數(shù)組存儲(chǔ)所有形狀的坐標(biāo),每種形狀都有一個(gè)中心坐標(biāo) (0,0),其余三個(gè)方框的坐標(biāo)按照中心坐標(biāo)來(lái)計(jì)算相對(duì)坐標(biāo),例如丁字形狀的方塊:
如果中心的坐標(biāo)為 (0,0) 的話(huà),剩余三個(gè)從右到左逆時(shí)針三個(gè)坐標(biāo)分別為 (0,1),(-1,0),(0,-1),之所以將垂直方向作為 X 軸是因?yàn)?Excel 坐標(biāo)的固有屬性,例如 Cells (1,2) 代表第一行第二列個(gè)單元格。每個(gè)方塊的對(duì)象有中心坐標(biāo),顏色,形狀等屬性,所以我們需要定義幾個(gè)模塊變量,代碼如下:
Option Explicit Dim MySheet As Worksheet Dim iCenterRow As Integer '方塊中心行 Dim iCenterCol As Integer '方塊中心列 Dim ColorArr() '7種顏色 Dim ShapeArr() '7種方塊 Dim iColorIndex As Integer '顏色索引 Dim MyBlock(4, 2) As Integer '每個(gè)方框的坐標(biāo)數(shù)組,會(huì)隨著方塊的移動(dòng)而變化 Dim bIsObjectEnd As Boolean '本個(gè)方塊是否下降到最低點(diǎn) Dim iScore As Integer '分?jǐn)?shù)
考慮到每種方塊坐標(biāo)的不一樣,所以我采用一個(gè)三維數(shù)組來(lái)存儲(chǔ)方塊坐標(biāo),為了方便,我采用 VBA 自帶的接口 Array () 函數(shù)給自己的 ShapeArr () 賦值。同時(shí)要在主界面上顯示出玩家的分?jǐn)?shù),所以這兩個(gè)功能我們作為一個(gè)初始化函數(shù),我們定義一個(gè) Init () 子過(guò)程,代碼如下:
'初始化 By@yaxi_li uPrivate Sub Init() Set MySheet = Sheets("Sheet1") ColorArr = Array(3, 4, 5, 6, 7, 8, 9) ShapeArr = Array(Array(Array(0, 0), Array(0, 1), Array(0, -1), Array(0, 2)), _ Array(Array(0, 0), Array(0, 1), Array(0, -1), Array(-1, -1)), _ Array(Array(0, 0), Array(0, 1), Array(0, -1), Array(-1, 1)), _ Array(Array(0, 0), Array(-1, 1), Array(-1, 0), Array(0, 1)), _ Array(Array(0, 0), Array(0, -1), Array(-1, 0), Array(-1, 1)), _ Array(Array(0, 0), Array(0, 1), Array(-1, 0), Array(-1, -1)), _ Array(Array(0, 0), Array(0, 1), Array(0, -1), Array(-1, 0))) With MySheet.Range("B1:K20") .Interior.Pattern = xlNone .Borders.LineStyle = xlNone .Borders(xlEdgeBottom).Weight = xlMedium .Borders(xlEdgeRight).Weight = xlMedium .Borders(xlEdgeLeft).Weight = xlMedium End With '設(shè)定長(zhǎng)寬比例 MySheet.Columns("A:L").ColumnWidth = 2 MySheet.Rows("1:30").RowHeight = 13.5 iScore = 0 MySheet.Range("N1").Value = "分?jǐn)?shù)" MySheet.Range("O1").Value = iScore End Sub
這時(shí)候,我們初始化變量與功能的函數(shù)基本上實(shí)現(xiàn)了。下一步我們要編寫(xiě)生成一個(gè)新方塊的函數(shù),為了實(shí)現(xiàn)程序的模塊化,低耦合,我們將本功能封裝成一個(gè)獨(dú)立的函數(shù)。
由于繪制函數(shù) DrawBlock () 需要根據(jù)傳遞過(guò)來(lái)的做標(biāo)數(shù)組來(lái)進(jìn)行繪制,同時(shí)我們需要知道這個(gè)方塊的中心坐標(biāo)在哪里,還有對(duì)應(yīng)的顏色,所以我們需要傳遞 4 個(gè)參數(shù),其中數(shù)組需要傳址 (ByRef),代碼如下:
'繪制方塊,By@yaxi_liu Private Sub DrawBlock(ByVal center_row As Integer, ByVal center_col As Integer, ByRef block() As Integer, ByVal icolor As Integer) Dim Row As Integer, Col As Integer Dim i As Integer For i = 0 To 3 Row = center_row + block(i, 0) Col = center_col + block(i, 1) MySheet.Cells(Row, Col).Interior.ColorIndex = icolor '顏色索引 MySheet.Cells(Row, Col).Borders.LineStyle = xlContinuous '周?chē)油饪蚓€(xiàn) Next End Sub
至此,繪制函數(shù)已經(jīng)完成,為了防止 Bug 出現(xiàn),我們需要測(cè)試一下,我們?cè)俣x一個(gè)入口函數(shù),Start (), 同時(shí)定義一個(gè)臨時(shí)方塊數(shù)組,調(diào)用 DrawBlock () 進(jìn)行測(cè)試。在主界面添加一個(gè)按鈕,將其指定到 Start 函數(shù),并將其拖入合適的位置:
Start 函數(shù)代碼如下:
Sub Start() Call Init iCenterRow = 5 iCenterCol = 6 iColorIndex = 4 Dim i As Integer For i = 0 To 3 MyBlock(i, 0) = ShapeArr(iColorIndex)(i)(0) MyBlock(i, 1) = ShapeArr(iColorIndex)(i)(1) Next Call DrawBlock(iCenterRow, iCenterCol, MyBlock, ColorArr(iColorIndex)) End Sub
我們運(yùn)行一下,看看效果:
好,測(cè)試結(jié)果顯示完全沒(méi)問(wèn)題。
由于后期我們需要在表格最上方的固定位置不斷隨機(jī)生成新的方塊,所以我們應(yīng)該將此功能再次封裝為一個(gè)獨(dú)立函數(shù),為了防止產(chǎn)生偽隨機(jī)數(shù),我們采用 Timer 作為當(dāng)前種子,隨機(jī)生成 0~6 之間的數(shù)組,每個(gè)對(duì)應(yīng)形狀數(shù)組與顏色數(shù)組的索引,代碼如下:
'隨機(jī)生成新的方塊函數(shù) By@yaxi_liu Private Sub GetBlock() Randomize (Timer) Dim i As Integer iColorIndex = Int(7 * Rnd) iCenterRow = 2 iCenterCol = 6 For i = 0 To 3 MyBlock(i, 0) = ShapeArr(iColorIndex)(i)(0) MyBlock(i, 1) = ShapeArr(iColorIndex)(i)(1) Next Call DrawBlock(iCenterRow, iCenterCol, MyBlock, ColorArr(iColorIndex)) End Sub
既然生成了方塊,我們就要讓方塊能夠左右下移動(dòng),分為三個(gè)方向。移動(dòng)的方法是首先擦除掉當(dāng)前的方塊,再根據(jù)規(guī)定的移動(dòng)方向,計(jì)算新的坐標(biāo),再根據(jù)新的坐標(biāo)重新繪制,這樣就產(chǎn)生了移動(dòng)的現(xiàn)象。但是,在移動(dòng)之前,我們需要判斷是否可以移動(dòng)。
首先,我們需要編寫(xiě)判斷是否能夠移動(dòng)或者旋轉(zhuǎn)的函數(shù) CanMoveRotate,此函數(shù)很簡(jiǎn)單,也就是將移動(dòng)后或者旋轉(zhuǎn)后的坐標(biāo)傳遞過(guò)來(lái),判斷是否越界,或者當(dāng)前位置上是否有其他顏色即可,代碼如下:
'是否能夠移動(dòng)或者旋轉(zhuǎn)函數(shù),By@yaxi_liu Private Function CanMoveRotate(ByVal center_row As Integer, ByVal center_col As Integer, ByRef block() As Integer) As Boolean '本函數(shù)形參均為變換后的坐標(biāo) '首先判斷是否越界 Dim Row As Integer, Col As Integer Dim i As Integer CanMoveRotate = True For i = 0 To 3 Row = center_row + block(i, 0) Col = center_col + block(i, 1) If Row > 20 Or Row < 0 Or Col > 11 Or Col < 2 Then '越界 CanMoveRotate = False End If If MySheet.Cells(Row, Col).Interior.Pattern <> xlNone Then '只要有一個(gè)顏色,則為阻擋 CanMoveRotate = False End If Next End Function
我們還需要一個(gè)擦除當(dāng)前方塊的函數(shù) EraseBlock,根據(jù)傳遞過(guò)來(lái)的坐標(biāo)直接擦拭掉,代碼如下:
'擦除方塊 By@yaxi_liu Private Sub EraseBlock(ByVal center_row As Integer, ByVal center_col As Integer, ByRef block() As Integer) Dim Row As Integer, Col As Integer Dim i As Integer For i = 0 To 3 Row = center_row + block(i, 0) Col = center_col + block(i, 1) MySheet.Cells(Row, Col).Interior.Pattern = xlNone MySheet.Cells(Row, Col).Borders.LineStyle = xlNone Next End Sub
我們?cè)倬帉?xiě)移動(dòng)方塊的函數(shù) MoveBlock,我們規(guī)定,形參 direction 代表方向,-1 代表向左,0 代表向下,1 代表向右,注意移動(dòng)后需要保存當(dāng)前坐標(biāo)。新增形參 direction,代碼如下:
'移動(dòng)方塊 By@yaxi_liu Private Sub MoveBlock(ByVal center_row As Integer, ByVal center_col As Integer, ByRef block() As Integer, ByVal icolor As Integer, ByVal direction As Integer) Dim Row As Integer, Col As Integer Dim i As Integer Dim old_row As Integer, old_col As Integer '保存最早的中心坐標(biāo) old_row = center_row old_col = center_col '首先擦除掉原來(lái)位置的 Call EraseBlock(center_row, center_col, block) '-1 代表向左,1 代表向右,0 代表鄉(xiāng)下 Select Case direction Case Is = -1 center_col = center_col - 1 Case Is = 1 center_col = center_col + 1 Case Is = 0 center_row = center_row + 1 End Select '再繪制 If CanMoveRotate(center_row, center_col, block) Then Call DrawBlock(center_row, center_col, block, icolor) '保存中心坐標(biāo) iCenterRow = center_row iCenterCol = center_col Else Call DrawBlock(old_row, old_col, block, icolor) '保存中心坐標(biāo) iCenterRow = old_row iCenterCol = old_col If direction = 0 Then bIsObjectEnd = True End If End If '保存方塊坐標(biāo) For i = 0 To 3 MyBlock(i, 0) = block(i, 0) MyBlock(i, 1) = block(i, 1) Next End Sub
移動(dòng)方塊實(shí)現(xiàn)后,我們?cè)賮?lái)編寫(xiě)旋轉(zhuǎn)方塊函數(shù) RotateBlock,這里我們統(tǒng)一規(guī)定為逆時(shí)針旋轉(zhuǎn)。跟移動(dòng)函數(shù)一樣,方法也是先擦除掉舊坐標(biāo)的后,再根據(jù)新坐標(biāo)繪制出新的方塊。只不過(guò)旋轉(zhuǎn)稍微麻煩一點(diǎn)。
不難計(jì)算出,假如一個(gè)向量 (x,y) 在逆時(shí)針旋轉(zhuǎn) 90 度后的坐標(biāo)為 (-y,x).根據(jù)這個(gè)公式,編寫(xiě)旋轉(zhuǎn)函數(shù)。但是注意事先應(yīng)該先判斷是否達(dá)到旋轉(zhuǎn)的條件。代碼如下:
'旋轉(zhuǎn)方塊函數(shù) By@yaxi_liu Private Sub RotateBlock(ByVal center_row As Integer, ByVal center_col As Integer, ByRef block() As Integer, ByVal icolor As Integer) Dim i As Integer '先擦除原來(lái)的 Call EraseBlock(center_row, center_col, block) Dim tempArr(4, 2) As Integer '保存數(shù)組 For i = 0 To 3 tempArr(i, 0) = block(i, 0) tempArr(i, 1) = block(i, 1) Next '旋轉(zhuǎn)后的坐標(biāo)重新賦值 For i = 0 To 3 block(i, 0) = -tempArr(i, 1) block(i, 1) = tempArr(i, 0) Next i '重新繪制新的方塊 If CanMoveRotate(center_row, center_col, block) Then Call DrawBlock(center_row, center_col, block, icolor) '保存方塊坐標(biāo) For i = 0 To 3 MyBlock(i, 0) = block(i, 0) MyBlock(i, 1) = block(i, 1) Next Else Call DrawBlock(center_row, center_col, tempArr, icolor) '保存方塊坐標(biāo) For i = 0 To 3 MyBlock(i, 0) = tempArr(i, 0) MyBlock(i, 1) = tempArr(i, 1) Next End If '保存中心坐標(biāo) iCenterRow = center_row iCenterCol = center_col End Sub
這時(shí)候,旋轉(zhuǎn)、移動(dòng)函數(shù)均已編寫(xiě)完畢。為了能夠讓游戲相應(yīng)鍵盤(pán)事件,我們需要在對(duì)應(yīng)的工作表代碼層添加事件函數(shù),注意這里我們需要調(diào)用 Windows API。我們規(guī)定鍵盤(pán)的左鍵為方塊向左 MoveObject (-1),右鍵為方塊向右 MoveObject (1),下鍵為方塊向下 MoveObject (0),上鍵為方塊旋轉(zhuǎn) RotateObject ()。我們?cè)?Sheet1 工作表里面編寫(xiě)如下 WorkSheet 事件代碼:
'鍵盤(pán)事件代碼,By@yaxi_liu #If VBA7 And Win64 Then Private Declare PtrSafe Function GetKeyboardState Lib "user32" (pbKeyState As Byte) As Long #Else Private Declare Function GetKeyboardState Lib "user32" (pbKeyState As Byte) As Long #End If Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim keycode(0 To 255) As Byte GetKeyboardState keycode(0) If keycode(38) > 127 Then '上 Call RotateObject ElseIf keycode(39) > 127 Then '右 Call MoveObject(1) ElseIf keycode(40) > 127 Then '下 Call MoveObject(0) ElseIf keycode(37) > 127 Then '左 Call MoveObject(-1) End If End Sub
由于我們自己定義的 MoveBlock 與 RotateBlock 包類(lèi)對(duì)象的形參,因此事件響應(yīng)中不能直接調(diào)用。在這里我們將用兩個(gè) Public 的 MoveObject 與 RotateObject 函數(shù)在類(lèi)模塊里面再次封裝,方便事件調(diào)用,代碼如下:
'移動(dòng)對(duì)象 By@yaxi_liu Public Sub MoveObject(ByVal dir As Integer) Call MoveBlock(iCenterRow, iCenterCol, MyBlock, ColorArr(iColorIndex), dir) End Sub
'旋轉(zhuǎn)對(duì)象 By@yaxi_liu Public Sub RotateObject() Call RotateBlock(iCenterRow, iCenterCol, MyBlock, ColorArr(iColorIndex)) End Sub
至此,方塊功能方面已經(jīng)完全實(shí)現(xiàn),我們隨機(jī)生成一個(gè)進(jìn)行測(cè)試:
為了方便,我們將按鈕 1 里面的文字更改成“啟動(dòng)游戲四個(gè)字”:
隨后,開(kāi)始編寫(xiě)程序自動(dòng)運(yùn)行的代碼。由于俄羅斯方塊是生成方塊后,按照一定的速度進(jìn)行下降,一旦碰到障礙物后本方塊結(jié)束,再生成新的方塊,如此循環(huán)。由于 VBA 不支持定時(shí)器,所以我們采用 while (true) 循環(huán)的方法進(jìn)行不斷生成方塊。為了避免 CPU 資源過(guò)度占用,我們?cè)谘h(huán)之間加入延時(shí)函數(shù),供循環(huán)調(diào)用,代碼如下:
'延時(shí)函數(shù) By@yaxi_liu Private Sub delay(T As Single) Dim T1 As Single T1 = Timer Do DoEvents Loop While Timer - T1 < T End Sub
在下降過(guò)程中,我們需要知道是否某一行已經(jīng)滿(mǎn)了,判斷的方法很簡(jiǎn)單,查詢(xún)整行是否全部涂色即可。如果滿(mǎn)了,我們刪除本行,同時(shí)將第一行到本行下降填充。同時(shí)更新分?jǐn)?shù)。因此我們?cè)僖胍粋€(gè)函數(shù) DeleteFullRow,代碼如下:
'消除滿(mǎn)行函數(shù) By@yaxi_liu Private Sub DeleteFullRow() Dim i As Integer, j As Integer For i = 1 To 20 For j = 2 To 11 If MySheet.Cells(i, j).Interior.ColorIndex < 0 Then Exit For ElseIf j = 11 Then MySheet.Range(Cells(1, 2), Cells(i - 1, j)).Cut Destination:=MySheet.Range(Cells(2, 2), Cells(i, j)) 'Range("B2:K18") iScore = iScore + 10 End If Next j Next i MySheet.Range("N1").Value = "分?jǐn)?shù)" MySheet.Range("O1").Value = iScore End Sub
再在 Start () 函數(shù)里面添加 while 循環(huán),上面兩個(gè)函數(shù)一樣添加進(jìn)去代碼如下:
'啟動(dòng)函數(shù) By@yaxi_liu Sub Start() Call Init While (True) Call GetBlock bIsObjectEnd = False '本方塊對(duì)象是否結(jié)束 While (bIsObjectEnd = False) Call delay(0.5) Call MoveBlock(iCenterRow, iCenterCol, MyBlock, ColorArr(iColorIndex), 0) MySheet.Range("L21").Select With MySheet.Range("B1:K20") .Borders(xlEdgeBottom).Weight = xlMedium .Borders(xlEdgeRight).Weight = xlMedium .Borders(xlEdgeLeft).Weight = xlMedium End With Wend Call DeleteFullRow Wend End Sub
到這里,本游戲的編寫(xiě)就算徹底結(jié)束了,點(diǎn)擊 Sheet1 界面上面的“按鈕 1”按鈕即可開(kāi)始游戲。我們?cè)僭囃嬉幌?,向左鍵代表向左,右鍵代表向右,上鍵代表旋轉(zhuǎn),下鍵代表下降。看一下效果:
哈哈,試玩結(jié)束沒(méi)問(wèn)題,非常完美,過(guò)程雖然長(zhǎng)久,但值得你細(xì)細(xì)研究,也希望你能從中夠體會(huì)到編程的樂(lè)趣。如果您覺(jué)得學(xué)到了知識(shí),希望您將這篇文章分享給更多的人,謝謝!
如果你想要源代碼文件,請(qǐng)?jiān)谖恼麻_(kāi)頭部分點(diǎn)擊我的名字關(guān)注我的公眾號(hào),在對(duì)話(huà)欄里面回復(fù)“俄羅斯方塊”五個(gè)字即可,我會(huì)將源代碼以及文件都發(fā)送給你,方便你后期研究代碼學(xué)習(xí)。
本文來(lái)自微信公眾號(hào):編碼珠璣 (ID:gh_f65e0111d17a),作者:劉亞曦
廣告聲明:文內(nèi)含有的對(duì)外跳轉(zhuǎn)鏈接(包括不限于超鏈接、二維碼、口令等形式),用于傳遞更多信息,節(jié)省甄選時(shí)間,結(jié)果僅供參考,IT之家所有文章均包含本聲明。