天天日天天干天天搞_亚洲性色AV无码久久精品色欲_亚洲精品免费在线观看_午夜视频在线免费观看

時(shí)代商業(yè)網(wǎng)
ad2

手把手教你用Excel編寫(xiě)俄羅斯方塊

來(lái)源:IT之家  時(shí)間:2022-11-30 14:47  編輯:沐瑤   閱讀量:10644   

我相信看到這個(gè)題目你會(huì)很驚訝什么,Excel居然能開(kāi)發(fā)游戲沒(méi)錯(cuò),Excel的強(qiáng)弱取決于用戶強(qiáng)則強(qiáng),弱則弱但本文并不是為了展示Excel使用中的巧思,主要是寫(xiě)給準(zhǔn)備學(xué)習(xí)編程但計(jì)算機(jī)基礎(chǔ)不多的人,或者對(duì)Excel感興趣的人

手把手教你用Excel編寫(xiě)俄羅斯方塊

對(duì)于正在學(xué)習(xí)編程的人,尤其是從其他領(lǐng)域進(jìn)入這個(gè)領(lǐng)域的人,興趣是最大的動(dòng)力從事計(jì)算機(jī)編程這么久,感覺(jué)編程是一件很有意義的事情但是,我經(jīng)常聽(tīng)到一些人,尤其是那些在校的學(xué)生,抱怨編程太枯燥,堅(jiān)持不下去我覺(jué)得這群人一方面是方向不對(duì),另一方面是在實(shí)際學(xué)習(xí)過(guò)程中對(duì)自己的成績(jī)沒(méi)有任何成就感,而后者往往占據(jù)了重要的原因

我認(rèn)為對(duì)于編程初學(xué)者來(lái)說(shuō),選擇第一語(yǔ)言應(yīng)該具備以下兩個(gè)特點(diǎn):

1),盡可能簡(jiǎn)單,盡可能少與底層硬件相關(guān)聯(lián)(如內(nèi)存管理等)。),調(diào)試方便,IDE接口簡(jiǎn)單,

2)比較強(qiáng)大,可以開(kāi)發(fā)各種插件工具,

目前業(yè)界常用的編程語(yǔ)言中,只有Python,Office for VBA和Java能夠同時(shí)滿足以上兩個(gè)特性不過(guò)Python雖然簡(jiǎn)單強(qiáng)大,但是需要配置環(huán)境,安裝臃腫的IDE,無(wú)形中增加了初學(xué)者的學(xué)習(xí)成本,更別說(shuō)Java了,剩下的就是VBA了VbA是visual basic語(yǔ)言的子集除了繼承了一些VB的功能,還特別封裝了一些軟件接口,使用起來(lái)很方便有人說(shuō)VBA語(yǔ)法太隨意,這對(duì)初學(xué)者來(lái)說(shuō)不是一件好事如果學(xué)了C,以后學(xué)C++就容易多了我不同意這種觀點(diǎn)對(duì)于前者,不同的人有不同的看法,但后者是無(wú)稽之談,因?yàn)镃++是一門(mén)極其復(fù)雜的編程語(yǔ)言,它不僅繼承了C語(yǔ)言繁瑣的指針,還衍生出了多重繼承,類模板,智能指針等恐怖的編程范式所以,對(duì)于初學(xué)者來(lái)說(shuō),我不建議直接學(xué)習(xí)C++

你為什么選擇VBA語(yǔ)作為初學(xué)者的語(yǔ)言。因?yàn)槌藵M足上述兩個(gè)特征之外,它還有一些其他的優(yōu)點(diǎn),如:

1),簡(jiǎn)單易用:不需要安裝開(kāi)發(fā)工具,也不需要安裝環(huán)境和語(yǔ)言包,只要電腦里有office軟件即可。

2)應(yīng)用廣泛:幾乎所有工程軟件和辦公軟件都支持用VBA進(jìn)行二次開(kāi)發(fā)比如財(cái)務(wù)人員發(fā)現(xiàn)Excel自己的公式有局限性,完全可以用VBA開(kāi)發(fā)自己需要的控件,如果機(jī)械設(shè)計(jì)師學(xué)習(xí)VBA,可以開(kāi)發(fā)一些自己需要的代碼塊,這將大大提高自己CAD的繪圖速度如果不了解VBA,很難想象Excel的重度用戶,尤其是財(cái)務(wù)人員的工作量有多可怕

3),調(diào)試簡(jiǎn)單方便。

所以,這一次,我也選擇了VBA作為編寫(xiě)演示的語(yǔ)言為了照顧更多的初學(xué)者,我盡可能的呈現(xiàn)了每一步的細(xì)節(jié)由于每個(gè)Excel版本都不一樣,我的電腦用的是2010版,所以我就用2010版來(lái)解釋其他版本相同,只是界面可能略有不同我相信只要你親手制作了這個(gè)游戲,你不僅會(huì)體會(huì)到Excel的強(qiáng)大,也會(huì)逐漸體會(huì)到編程的樂(lè)趣鑒于時(shí)間有限,內(nèi)容可能會(huì)有所疏漏希望大家指正

下面是正文:

先來(lái)看看游戲最終的大致效果圖:

我們先來(lái)思考一下俄羅斯方塊的總體架構(gòu):

1),初始化界面:創(chuàng)建廣場(chǎng)所需的地圖。

2)隨機(jī)生成俄羅斯方塊:俄羅斯方塊共有7種形式,每種形式由4幀組成,每個(gè)方塊對(duì)應(yīng)一種顏色您可以創(chuàng)建一個(gè)數(shù)組來(lái)存儲(chǔ)每個(gè)正方形的坐標(biāo),然后使用另一個(gè)數(shù)組來(lái)存儲(chǔ)正方形的相應(yīng)顏色

3),移動(dòng)旋轉(zhuǎn)方塊:分左,右,下擦拭后重畫(huà),產(chǎn)生移動(dòng)旋轉(zhuǎn)的效果

4)如果沒(méi)有新的方塊產(chǎn)生,它們都以一定的速度下落一旦碰到障礙物,就不能掉下來(lái),然后生成新的方塊

5),不斷掃描是否有行被填充如果是真的,這條線就刪了,頂?shù)袅嗣織l線有10個(gè)點(diǎn)

首先創(chuàng)建一個(gè)Excel文件,隨意命名。打開(kāi)后,因?yàn)閛ffice默認(rèn)隱藏了開(kāi)發(fā)工具的狀態(tài)欄,所以我們需要選擇Excel選項(xiàng)gt,自定義功能區(qū)以調(diào)出,檢查并確認(rèn):

隨后,我們發(fā)現(xiàn)主界面有更多的開(kāi)發(fā)工具選項(xiàng):

然后,在Sheet1表格中,我們將A~K列的列寬調(diào)整為與行高大致相同,并讓它大致稱為正方形區(qū)域:

我們點(diǎn)擊Visual Basic菜單打開(kāi)寫(xiě)代碼的界面,我們插入一個(gè)代碼模塊來(lái)寫(xiě)我們自己的代碼:

因?yàn)檎叫斡?個(gè)形狀,為了讓程序繪圖方便,我用一個(gè)三維數(shù)組來(lái)存儲(chǔ)所有形狀的坐標(biāo),每個(gè)形狀都有一個(gè)中心坐標(biāo),其他三個(gè)正方形的坐標(biāo)都是根據(jù)中心坐標(biāo)計(jì)算出來(lái)的,比如一個(gè)T型正方形:

如果中心的坐標(biāo)為,剩下的三個(gè)坐標(biāo)從右到左分別是(0,1),(—1,0),和(0,1)之所以把垂直方向作為X軸,是因?yàn)镋xcel坐標(biāo)的固有屬性例如,單元格(1,2)表示單元格的第一行和第二列每個(gè)方塊的對(duì)象都有中心坐標(biāo),顏色,形狀等屬性

optixplicitdimysheetworksheetlimitcentercentowasinteger '正方形中心行DimcenterColasinteger '正方形中心列Dimcolorar ' 7種正方形DimShapeArr 7種正方形DimiColorIndexAsInteger '顏色索引dimmyblock (4,2) as integer '每個(gè)正方形的坐標(biāo)數(shù)組將伴隨著正方形的移動(dòng)而變化DimbIsObjectEndAsBoolean '此正方形是否降到最低點(diǎn)DimiScoreAsInteger '分?jǐn)?shù)

考慮到每個(gè)方塊坐標(biāo)不一樣,我用一個(gè)三維數(shù)組來(lái)存儲(chǔ)方塊坐標(biāo)為了方便起見(jiàn),我使用VBA自己接口的數(shù)組函數(shù)來(lái)給我的ShapeArr賦值

' Initialize by yaxi _ liurivatesubinitsetmysheet = sheets( " sheet 1 ")color = Array(3,4,5,6,7,8,9) shapearr = array (array (0,0),array (0,1),array (0,1),Array(0,—1),Array(—1),Array(0,0),Array(0,1),Array(0,—1),Array(—1,1),_Array(Array(0,0Range("B1:K20 "),Interior.Pattern=xlNoneBorders.LineStyle=xlNone邊框(xlEdgeBottom)重量=xlMedium邊框(xlEdgeRight)重量=xlMedium邊框(xlEdgeLeft)Weight=xlMediumEndWith '設(shè)置縱橫比mysheet.columns ( "a: l ")列寬= 2mesheet.rows ( "1: 30 ")

這時(shí)候我們初始化變量和函數(shù)的功能就基本實(shí)現(xiàn)了接下來(lái),我們將編寫(xiě)一個(gè)函數(shù)來(lái)生成一個(gè)新的正方形為了實(shí)現(xiàn)程序的模塊化和低耦合,我們把這個(gè)功能封裝成一個(gè)獨(dú)立的功能

由于繪圖函數(shù)DrawBlock需要根據(jù)傳遞的標(biāo)記數(shù)組進(jìn)行繪制,并且我們需要知道這個(gè)正方形的中心坐標(biāo)在哪里以及對(duì)應(yīng)的顏色,所以需要傳遞四個(gè)參數(shù),其中數(shù)組需要被尋址(ByRef)。代碼如下:

'畫(huà)一個(gè)正方形,by yaxi _ liurivatesubdrawblock integer,byvalicolasinteger)dimrowasininteger,colasinteger = 0 to 3 row = center _ row+block(I,0) col = center _ col+block (I,1) mysheet.cells (row,col)interior . colorindex = icolor ' color index my sheet . cells(row,col)borders . line style = XL continuous '帶大綱線NextEndSub

至此,繪圖功能已經(jīng)完成為了防止bug,我們需要測(cè)試它我們會(huì)定義一個(gè)入口函數(shù),Start,同時(shí)定義一個(gè)臨時(shí)的方形數(shù)組,調(diào)用DrawBlock進(jìn)行測(cè)試

啟動(dòng)功能代碼如下:

substartcalliniticertrow = 5 iCenterCol = 6 iColorIndex = 4 dimiasintegerfori = 0 to 3 MyBlock(I,0)= shape arr(iColorIndex)(I)(0)my block(I,1)= shape arr(iColorIndex)(I)(1)NextCallDrawBlock(iCenterRow,iCenterCol,my block,ColorArr(iColorIndex))EndSub

讓我們運(yùn)行它,看看效果:

好的,檢測(cè)結(jié)果顯示完全沒(méi)有問(wèn)題。

后期需要在表格頂部的固定位置隨機(jī)生成新的方塊,所以要把這個(gè)函數(shù)重新包裝成一個(gè)獨(dú)立的函數(shù)為了防止偽隨機(jī)數(shù)的產(chǎn)生,我們使用Timer作為當(dāng)前種子,隨機(jī)生成0到6之間的數(shù)組,每個(gè)數(shù)組對(duì)應(yīng)形狀數(shù)組和顏色數(shù)組的索引

'由yaxi _ liurivatesubgetblockrandomize(timer)dimasintegericolor index = int(7 * rnd)ice interrow = 2 icenter col = 6 fori = 0 to 3 myblock(I,0)= ShapeArr(iColorIndex)(I)(0)my block(I,1)= ShapeArr(iColorIndex)(I)(1)NextCallDrawBlock(ice interrow,iCenterCol,my block,colorrar(iColorIndex))EndSub

現(xiàn)在正方形生成了,我們要讓正方形左右移動(dòng),分成三個(gè)方向移動(dòng)的方法是先擦除當(dāng)前的方塊,然后按照指定的移動(dòng)方向計(jì)算新的坐標(biāo),再按照新的坐標(biāo)重新繪制,這樣就產(chǎn)生了移動(dòng)的現(xiàn)象但是,在搬家之前,我們需要判斷自己是否可以搬家

首先我們需要寫(xiě)函數(shù)CanMoveRotate來(lái)判斷它是否可以移動(dòng)或者旋轉(zhuǎn)這個(gè)函數(shù)很簡(jiǎn)單,就是我們可以通過(guò)移動(dòng)或者旋轉(zhuǎn)后的坐標(biāo)來(lái)判斷是否越界或者當(dāng)前位置是否有其他顏色

'函數(shù)是否可以移動(dòng)或旋轉(zhuǎn),由yaxi _ liurivatefunctioncanmoverotateasinteger)作為boolean '此函數(shù)的參數(shù)是變換后的坐標(biāo) '首先判斷是否越界,DimRowAsInteger,colasintegercanmoverotate = true fori = 0 to 3 row = center _ row+block(I,0)Col=center_col+block(i,1)IfRowgt,20OrRowlt0OrColgt11或收集,2Then '出界可以移動(dòng)rotate = false endifmyshet . cells(row,col)interior.patternltgt,XLONETHEN '只要有一種顏色,它就是blocking can move rotate = false endifnextendfunction

我們還需要一個(gè)函數(shù)EraseBlock來(lái)擦除當(dāng)前的方塊,可以根據(jù)傳遞過(guò)來(lái)的坐標(biāo)直接擦除。代碼如下:

' Erase block by yaxi _ liurivateseuberaselblocksetter)dimrowasinterer,colas interdimisinterfori = 0 to 3 row = center _ row+block(I,0) col = center _ col+block (i,1)MySheetCells(Row,Col). interior . pattern = xlNoneMySheet

我們來(lái)寫(xiě)移動(dòng)塊的函數(shù)MoveBlock我們規(guī)定參數(shù)direction代表方向,—1代表左,0代表下,1代表右注意,移動(dòng)后需要保存當(dāng)前坐標(biāo)

'移動(dòng)框by yaxi _ liurivatessubmoveblocksetter,byvalicolosetter,byvaldirectionassetter)dimrowasininteger,colas integer dimold _ row為整數(shù),old _ colasinteger '保存最早的中心坐標(biāo)old _ row = Center _ row old _ col = center _ col '首先擦除caller seblock(Center _ row,Center _ col,block)'—1為左,1為右,0代表農(nóng)村selectcasedirectioncases =—1 Center _ col = Center _ col—1 case 然后畫(huà)ifcanmovestate (center _ row,center _ col,block)然后畫(huà)calldrawblock (center _ row,center _ col,block,icolor) 保存中心坐標(biāo)ice interrow = center _ rowicentercol = center _ collsecalldrawblock(old _ row,old _ col,block,icolor) 保存中心坐標(biāo)ice interrow = old _ rowicentercol = old _ colifdirection = 0 thenbibjectend = true endfendif '保存平方坐標(biāo)fori = 0to3myblock (I,0) = block (I

移動(dòng)塊實(shí)現(xiàn)后,我們就寫(xiě)RotateBlock函數(shù),定義為逆時(shí)針旋轉(zhuǎn)就像移動(dòng)函數(shù)一樣,方法是先擦除舊坐標(biāo),然后根據(jù)新坐標(biāo)畫(huà)一個(gè)新方塊只是旋轉(zhuǎn)起來(lái)有點(diǎn)麻煩

如果一個(gè)向量逆時(shí)針旋轉(zhuǎn)90度后坐標(biāo)為(—y,x),就不難計(jì)算了根據(jù)這個(gè)公式,寫(xiě)出旋轉(zhuǎn)函數(shù)但需要注意的是,要提前判斷是否滿足輪換的條件

' Rotate block function by yaxi _ liurivatesubrotateBlockasinteger,byvalicorasinteger)dimiasinteger ' Erase block(center _ row,center _ col,block) dimtemparr (4,2)as integer ' save array for I = 0 to 3 temparr(I,0) = block (i,0)= block(I,1) next '重新分配旋轉(zhuǎn)后的坐標(biāo)fori = 0to3block (i,0) =—temparr (i,0) icolor) '保存平方坐標(biāo)Fori=0To3MyBlock(i,0)=block(i,0) myblock (I,1) = block (I,1)nextelsecalldrawblock(center _ row,center _ col,temparr,icolor) '保存平方坐標(biāo)fori = 0to3 myblock (I,0) = temparr (I,0) myblock (I,1) 1)NextEndIf '保存中心坐標(biāo)ice interrow = center _ rowice intercol = center _ colend sub。

這時(shí),旋轉(zhuǎn)和移動(dòng)函數(shù)已經(jīng)寫(xiě)好了為了讓游戲?qū)?yīng)鍵盤(pán)事件,我們需要在對(duì)應(yīng)的工作表代碼層添加事件函數(shù)注意,這里我們需要調(diào)用Windows API我們規(guī)定鍵盤(pán)左鍵為方形向左移動(dòng)對(duì)象,右鍵為方形向右移動(dòng)對(duì)象(1),下鍵為方形向下移動(dòng)對(duì)象(0),上鍵為方形旋轉(zhuǎn)對(duì)象()

'鍵盤(pán)事件代碼,byyaxi _ Liu # ifvba 7 and win 64 thenrivateclareptsafeffunction getkeyboardstatelib " user 32 " AsLong # elsepropivatedclairefunction getkeyboardstatelib " user 32 " AsLong # EndIfPrivateSubWorksheet _ selection change(ByValTargetAsRange)dim key code(0到255)asbytegetkeyboardstatekey code(0)if key code(38)gt,127 then ' callrotateobjectelsifkeycode(39)gt,27然后 ' right callmoveobject(1)else if keycode(40)gt,127Then,callmoveobject(0)else if keycode(37)gt,127 then ' left CallMoveObject(—1)EndIfEndSub

因?yàn)槲覀冏约憾x的MoveBlock和RotateBlock包類對(duì)象的形參,所以不能在事件響應(yīng)中直接調(diào)用這里我們將再次在類模塊中封裝兩個(gè)公共的MoveObject和RotateObject函數(shù),方便事件調(diào)用

' Move object by yaxi _ liuppublicsubmoveobjectcallmoveblock(icenterrow,icentercol,myblock,color (icon index),dir) end sub

'旋轉(zhuǎn)對(duì)象by yaxi _ liuppublicsubrotateobjectcallrotateblock(ice interrow,icentercol,myblock,color (icolor index)) endsub。

至此,平方功能已經(jīng)完全實(shí)現(xiàn)。我們隨機(jī)生成一個(gè)用于測(cè)試:

為了方便起見(jiàn),我們將按鈕1中的文本改為開(kāi)始游戲的四個(gè)詞:

然后,開(kāi)始編寫(xiě)程序自動(dòng)運(yùn)行的代碼伴隨著俄羅斯方塊的生成,它以一定的速度下降一旦碰到障礙物,俄羅斯方塊結(jié)束,然后生成新的俄羅斯方塊,以此類推因?yàn)閂BA不支持定時(shí)器,我們使用while循環(huán)方法來(lái)連續(xù)生成方塊為了避免對(duì)CPU資源的過(guò)度占用,我們?cè)谘h(huán)之間增加了一個(gè)延遲函數(shù),用于循環(huán)調(diào)用

' Delay function by yaxi _ liurivatesubdelaydimt 1 assinglet1 = timerdodoeventslopwhiletimer—t1lt,TEndSub

在下降的過(guò)程中,我們需要知道某條線是否已滿判斷的方法很簡(jiǎn)單,只需檢查整條線是否上色即可如果滿了,我們就刪除這一行,把第一行填到這一行同時(shí)更新分?jǐn)?shù)

'消除整行函數(shù)by yaxi _ liurivatesubdeletefullrowdimiasinger,jasintegerfori = 1 to 20 forj = 2 to 11 if my shet . cells(I,j)interior.colorindexlt0 thenexitforelseifj = 11 thenmysheet范圍(單元格(1,2),單元格(i—1,j))CutDestination:=MySheetRange(Cells(2,2),Cells(i,j)) ' Range( " B2:K18 ")is core = is core+10 endifnextjnextimyshet . Range( " n1 ")value = " fraction " my shet . range( " O1 ")

在Start函數(shù)中添加while循環(huán),上述兩個(gè)函數(shù)添加的代碼相同,如下所示:

'啟動(dòng)函數(shù)by yaxi _ liussubstartcalnitwhile(true)callgetblocksobjectend = false '此方塊的對(duì)象是否結(jié)束while(bisobjectend = false)call delay(0.5)callmoveblock(icenterrow,iCenterCol,MyBlock,colorrar(iColorIndex),0)MySheetrange( " L21 "). selectwithmysheet . range( " B1:K20 ")邊框(xlEdgeBottom)重量=xlMedium邊框(xlEdgeRight)重量=xlMedium邊框(xlEdgeLeft)

至此,這個(gè)游戲的編寫(xiě)就算完全完成了,點(diǎn)擊Sheet1界面上的按鈕1按鈕開(kāi)始游戲讓我們?cè)僭囈淮巫箧I代表左,右鍵代表右,上鍵代表旋轉(zhuǎn),下鍵代表下降

哈哈,試玩結(jié)束沒(méi)問(wèn)題,很完美雖然過(guò)程漫長(zhǎng),但值得你認(rèn)真學(xué)習(xí),希望你能從中體會(huì)到編程的樂(lè)趣如果你認(rèn)為你學(xué)到了知識(shí),我希望你能把這篇文章分享給更多的人

。

鄭重聲明:此文內(nèi)容為本網(wǎng)站轉(zhuǎn)載企業(yè)宣傳資訊,目的在于傳播更多信息,與本站立場(chǎng)無(wú)關(guān)。僅供讀者參考,并請(qǐng)自行核實(shí)相關(guān)內(nèi)容。