前言
看到這個(gè)題目,想必你一定會(huì)感到非常驚訝,什么,Excel居然能開發(fā)游戲?
沒錯(cuò),Excel的強(qiáng)大取決于使用者,遇強(qiáng)則強(qiáng),遇弱則弱。
但我這篇文章并不是為了展示Excel使用過程中的奇技淫巧,而是主要寫給那些準(zhǔn)備學(xué)習(xí)編程但又沒什么計(jì)算機(jī)基礎(chǔ)的那些人,或者對(duì)Excel感興趣的那些人。
如果這篇文章對(duì)你有一定幫助,我希望你能夠?qū)⑦@片文章分享出去,讓更多的人看到;如果你已經(jīng)是一名有經(jīng)驗(yàn)的開發(fā)者,我也希望你能提出寶貴的意見。
對(duì)于那些正在學(xué)習(xí)編程的人,尤其是那些從其他領(lǐng)域跨入這個(gè)行業(yè)的人,興趣才是最大的動(dòng)力。我從事計(jì)算機(jī)編程這么長時(shí)間,感覺編程是一件非常有意義的事情。
然而我卻我經(jīng)常聽到有些人,尤其是那些在校學(xué)生們抱怨說編程學(xué)起來太枯燥了,堅(jiān)持不下去。
覺得這部分人一方面是方向錯(cuò)了,另一方面就是在實(shí)際學(xué)習(xí)過程中對(duì)自己做出成果沒有任何的成就感,而后者,往往占據(jù)了重要原因。
我認(rèn)為,對(duì)于編程的初學(xué)者,選擇第一門語言應(yīng)該具備下面兩個(gè)特點(diǎn):
1)盡可能簡單,盡量少與底層硬件(諸如內(nèi)存管理等)相關(guān)聯(lián),調(diào)試方便,IDE界面簡單;
2)功能相對(duì)強(qiáng)大,能開發(fā)各種小插件工具;
就目前行業(yè)內(nèi)比較常用的編程語言中,能夠同時(shí)滿足上述兩個(gè)特點(diǎn)的也就數(shù)Python,office for VBA,Java了,然而,Python雖然簡單功能又強(qiáng)大,但是需要配置環(huán)境,而且要安裝臃腫的IDE,這些對(duì)于初學(xué)者來說,無形之中又增加了學(xué)習(xí)成本,更別說Java了,所以剩下的就數(shù)VBA(Visual Basic for Application)了。
VBA屬于visual basic語言的子集,除了繼承了部分vb功能外,還特意針對(duì)一些軟件做了接口封裝,使用方便。有人說VBA語法太隨意,對(duì)于初學(xué)者不是件好事,如果學(xué)C的話,將來學(xué)C++就簡單很多了。
我不同意這種觀點(diǎn),對(duì)于前者,仁者見仁,但后者就是在扯淡,因?yàn)镃++是一門極其復(fù)雜的編程語言,除了繼承了C的繁瑣指針以外,還衍生出了諸如多重繼承、類模板、智能指針等恐怖級(jí)別的編程范式,所以說,對(duì)于初學(xué)者,我不建議直接就去學(xué)C++.
為什么選擇VBA作為初學(xué)者的語言呢,因?yàn)樗藵M足上面所說的兩個(gè)特點(diǎn)外,還有一些其他的優(yōu)點(diǎn),諸如:
1)使用簡單:不需要安裝開發(fā)工具,更不需要配環(huán)境、安裝語言包,只要你電腦里面有office軟件即可。
2)用途廣泛:幾乎所有的工程軟件、辦公軟件都支持用VBA做二次開發(fā),例如財(cái)務(wù)人員如果發(fā)現(xiàn)Excel自帶的公式有局限性的話,完全可以自己用VBA開發(fā)自己需要的控件;
機(jī)械設(shè)計(jì)人員如果學(xué)了VBA后可以開發(fā)一些自己需要的代碼塊,極大程度地提高自己CAD的繪圖速度。很難想象,Excel的重度用戶尤其是財(cái)務(wù)人員不懂VBA的話他的工作量有多可怕。
3)調(diào)試簡單方便。
所以,這次我也選擇VBA作為這次編寫Demo的語言,為了照顧更多的初學(xué)者,我將每一步的細(xì)節(jié)都盡可能地呈現(xiàn)出來,由于每個(gè)Excel版本不一樣,我電腦用的是2010版的。
所以,我就用2010版進(jìn)行說明,其他版本也一樣,只是界面可能稍有區(qū)別。我相信,只要親手按照我的方法做出這個(gè)游戲,除了你將認(rèn)識(shí)到Excel的強(qiáng)大之處外,你也將逐步體會(huì)到編程的樂趣。
鑒于時(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)沒產(chǎn)生新的方塊,都進(jìn)行一定速度的下落,一旦碰到障礙物,不能下落,再生成新的方塊。
5)不斷掃描是否有任何一行填滿,如果為真,則本行刪除,上面下落。每行積分為10分。
開發(fā)過程
首先創(chuàng)建一個(gè)Excel文件,隨意命名。打開后,由于office默認(rèn)隱藏了開發(fā)工具狀態(tài)欄,所以我們需要在Excel選項(xiàng)>自定義功能區(qū)將其調(diào)出來,將其勾選后確認(rèn):
隨后,我們發(fā)現(xiàn)主界面多了開發(fā)工具的選項(xiàng):
我們再在Sheet1表格里面將A~K列的列寬大致調(diào)成跟行高一樣,讓它大致稱為一個(gè)正方形的區(qū)域:
我們點(diǎn)擊Visual Basic菜單,打開編寫代碼界面,我們插入首先插入一個(gè)代碼模塊,用于編寫我們自己的代碼:
由于方塊有7中形狀,為了讓程序繪制方便,我用一個(gè)三維數(shù)組存儲(chǔ)所有形狀的坐標(biāo),每種形狀都有一個(gè)中心坐標(biāo)(0,0),其余三個(gè)方框的坐標(biāo)按照中心坐標(biāo)來計(jì)算相對(duì)坐標(biāo),例如丁字形狀的方塊:
如果中心的坐標(biāo)為(0,0)的話,剩余三個(gè)從右到左逆時(shí)針三個(gè)坐標(biāo)分別為(0,1),(-1,0),(0,-1),之所以將垂直方向作為X軸是因?yàn)镋xcel坐標(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ù)組來存儲(chǔ)方塊坐標(biāo),為了方便,我采用VBA自帶的接口Array()函數(shù)給自己的ShapeArr()賦值。
同時(shí)要在主界面上顯示出玩家的分?jǐn)?shù),所以這兩個(gè)功能我們作為一個(gè)初始化函數(shù),我們定義一個(gè)Init()子過程,代碼如下:
'初始化 By@yaxi_liu
Private 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è)定長寬比例
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)了。下一步我們要編寫生成一個(gè)新方塊的函數(shù),為了實(shí)現(xiàn)程序的模塊化,低耦合,我們將本功能封裝成一個(gè)獨(dú)立的函數(shù)。
由于繪制函數(shù)DrawBlock()需要根據(jù)傳遞過來的做標(biāo)數(shù)組來進(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 '周圍加外框線
Next
End Sub
至此,繪制函數(shù)已經(jīng)完成,為了防止Bug出現(xiàn),我們需要測試一下,我們再定義一個(gè)入口函數(shù),Start(),同時(shí)定義一個(gè)臨時(shí)方塊數(shù)組,調(diào)用DrawBlock()進(jìn)行測試。在主界面添加一個(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)行一下,看看效果:
好,測試結(jié)果顯示完全沒問題。
由于后期我們需要在表格最上方的固定位置不斷隨機(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)。
首先,我們需要編寫判斷是否能夠移動(dòng)或者旋轉(zhuǎn)的函數(shù)CanMoveRotate,此函數(shù)很簡單,也就是將移動(dòng)后或者旋轉(zhuǎn)后的坐標(biāo)傳遞過來,判斷是否越界,或者當(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ù)傳遞過來的坐標(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
我們再編寫移動(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
'首先擦除掉原來位置的
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)后,我們再來編寫旋轉(zhuǎn)方塊函數(shù)RotateBlock,這里我們統(tǒng)一規(guī)定為逆時(shí)針旋轉(zhuǎn)。跟移動(dòng)函數(shù)一樣,方法也是先擦除掉舊坐標(biāo)的后,再根據(jù)新坐標(biāo)繪制出新的方塊。只不過旋轉(zhuǎn)稍微麻煩一點(diǎn)。
不難計(jì)算出,假如一個(gè)向量(x,y)在逆時(shí)針旋轉(zhuǎn)90度后的坐標(biāo)為(-y,x).根據(jù)這個(gè)公式,編寫旋轉(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
'先擦除原來的
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ù)均已編寫完畢。為了能夠讓游戲相應(yīng)鍵盤事件,我們需要在對(duì)應(yīng)的工作表代碼層添加事件函數(shù),注意這里我們需要調(diào)用Windows API。
我們規(guī)定鍵盤的左鍵為方塊向左MoveObject(-1),右鍵為方塊向右MoveObject(1),下鍵為方塊向下MoveObject(0),上鍵為方塊旋轉(zhuǎn)RotateObject()。我們再Sheet1工作表里面編寫如下WorkSheet事件代碼:
'鍵盤事件代碼,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包類對(duì)象的形參,因此事件響應(yīng)中不能直接調(diào)用。
在這里我們將用兩個(gè) Public 的MoveObject與RotateObject函數(shù)在類模塊里面再次封裝,方便事件調(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)行測試:
為了方便,我們將按鈕1里面的文字更改成“啟動(dòng)游戲四個(gè)字”:
隨后,開始編寫程序自動(dòng)運(yùn)行的代碼。由于俄羅斯方塊是生成方塊后,按照一定的速度進(jìn)行下降,一旦碰到障礙物后本方塊結(jié)束,再生成新的方塊,如此循環(huán)。由于VBA不支持定時(shí)器,所以我們采用while(true)循環(huán)的方法進(jìn)行不斷生成方塊。
為了避免CPU資源過度占用,我們在循環(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
在下降過程中,我們需要知道是否某一行已經(jīng)滿了,判斷的方法很簡單,查詢整行是否全部涂色即可。
如果滿了,我們刪除本行,同時(shí)將第一行到本行下降填充。同時(shí)更新分?jǐn)?shù)。因此我們再引入一個(gè)函數(shù)DeleteFullRow,代碼如下:
'消除滿行函數(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_liuSubStart()CallInit 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 WendEnd Sub
到這里,本游戲的編寫就算徹底結(jié)束了,點(diǎn)擊Sheet1界面上面的“按鈕1”按鈕即可開始游戲。
我們再試玩一下,向左鍵代表向左,右鍵代表向右,上鍵代表旋轉(zhuǎn),下鍵代表下降??匆幌滦Ч?/p>
哈哈,試玩結(jié)束沒問題,非常完美,過程雖然長久,但值得你細(xì)細(xì)研究,也希望你能從中夠體會(huì)到編程的樂趣。
審核編輯:劉清
-
編程語言
+關(guān)注
關(guān)注
10文章
1931瀏覽量
34553 -
Excel
+關(guān)注
關(guān)注
4文章
217瀏覽量
55425 -
python
+關(guān)注
關(guān)注
55文章
4774瀏覽量
84386 -
俄羅斯方塊
+關(guān)注
關(guān)注
0文章
22瀏覽量
10619
原文標(biāo)題:用Excel編寫俄羅斯方塊?沒錯(cuò)!
文章出處:【微信號(hào):All_best_xiaolong,微信公眾號(hào):大魚機(jī)器人】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論