《硬件趣學Python編程》 俄羅斯方塊_第1頁
《硬件趣學Python編程》 俄羅斯方塊_第2頁
《硬件趣學Python編程》 俄羅斯方塊_第3頁
《硬件趣學Python編程》 俄羅斯方塊_第4頁
《硬件趣學Python編程》 俄羅斯方塊_第5頁
已閱讀5頁,還剩42頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

+硬件趣學Python編程

做一個融入集體的方塊,俄羅斯方塊的游戲制作牛艾科技目錄ContentsSuccessWords2第二部分對象的封裝第三部分繼承和多態(tài)第四部分游戲基本設計思路第五部分俄羅斯方塊的代碼分析第一部分面向?qū)ο竽夸汣ontentsSuccessWords3第一部分面向?qū)ο?面向?qū)ο竺嫦噙^程和面相對象基本概念

面相過程——怎么做?把完成某一個需求的所有步驟從頭到尾逐步實現(xiàn)根據(jù)開發(fā)需求,將某些功能獨立的代碼封裝成一個又一個函數(shù)最后完成的代碼,就是順序地調(diào)用不同的函數(shù)

特點:注重步驟與過程,不注重職責分工如果需求復雜,代碼會變得很復雜開發(fā)復雜項目,沒有固定的套路,開發(fā)難度很大!5面向?qū)ο竺嫦驅(qū)ο蟆l來做?

相比較函數(shù),面向?qū)ο笫歉蟮姆庋b,根據(jù)職責在一個對象中封裝多個方法在完成某一個需求前,首先確定職責——要做的事情(方法)根據(jù)職責確定不同的對象,在對象內(nèi)部封裝不同的方法(多個)最后完成的代碼,就是順序地讓不同的對象調(diào)用不同的方法特點:注重對象和職責,不同的對象承擔不同的職責更加適合應對復雜的需求變化,是專門應對復雜項目開發(fā),提供的固定套路需要在面向過程基礎上,再學習一些面向?qū)ο蟮恼Z法6面向?qū)ο箢?/p>

類是對一群具有相同特征或者行為的事物的一個統(tǒng)稱,是抽象的,不能直接使用特征被稱為屬性行為被稱為方法類:就相當于制造飛機時的圖紙,是一個模板,是負責創(chuàng)建對象的7面向?qū)ο髮ο?/p>

對象是由類創(chuàng)建出來的一個具體存在,可以直接使用由哪一個類創(chuàng)建出來的對象,就擁有在哪一個類中定義的:屬性、方法對象就相當于用圖紙制造的飛機在程序開發(fā)中,應該先有類,再有對象目錄ContentsSuccessWords8第二部分對象的封裝對象的封裝內(nèi)置函數(shù)序號方法名類型作用01__new__方法創(chuàng)建對象時,會被自動調(diào)用02__init__方法對象被初始化時,會被自動調(diào)用03__del__方法對象被從內(nèi)存中銷毀前,會被自動調(diào)用04__str__方法返回對象的描述信息,print函數(shù)輸出使用10對象的封裝定義只包含方法的類方法的定義格式和之前學習過的函數(shù)幾乎一樣區(qū)別在于第一個參數(shù)必須是self,大家暫時先記住,稍后介紹self注意:類名的命名規(guī)則要符合大駝峰命名法class類名:def方法1(self,參數(shù)列表):pass

def方法2(self,參數(shù)列表):pass11對象的封裝創(chuàng)建對象對象變量=類名()第一個面向?qū)ο蟪绦蛐枨笮∝垚鄢贼~,小貓要喝水分析

定義一個貓類Cat定義兩個方法eat和drink按照需求——不需要定義屬性classCat:"""這是一個貓類"""defeat(self):print("小貓愛吃魚")defdrink(self):print("小貓在喝水")tom=Cat()tom.drink()tom.eat()12對象的封裝對象的屬性在Python中,要給對象設置屬性,非常的容易,但是不推薦使用因為:對象屬性的封裝應該封裝在類的內(nèi)部只需要在類的外部的代碼中直接通過.設置一個屬性即可注意:這種方式雖然簡單,但是不推薦使用!="Tom"...lazy_="大懶貓"13對象的封裝方法中的self參數(shù)由哪一個對象調(diào)用的方法,方法內(nèi)的self就是哪一個對象的引用在類封裝的方法內(nèi)部,self就表示當前調(diào)用方法的對象自己調(diào)用方法時,程序員不需要傳遞self參數(shù)在方法內(nèi)部可以通過self.訪問對象的屬性也可以通過self.調(diào)用其他的對象方法改造代碼如下:

classCat:defeat(self):print("%s愛吃魚"%)tom=Cat()="Tom"tom.eat()lazy_cat=Cat()lazy_="大懶貓"lazy_cat.eat()14對象的封裝初始化方法

之前代碼存在的問題——在類的外部給對象增加屬性將案例代碼進行調(diào)整,先調(diào)用方法再設置屬性,觀察一下執(zhí)行效果

在日常開發(fā)中,不推薦在類的外部給對象增加屬性如果在運行時,沒有找到屬性,程序會報錯對象應該包含有哪些屬性,應該封裝在類的內(nèi)部

tom=Cat()tom.drink()tom.eat()="Tom"print(tom)AttributeError:'Cat'objecthasnoattribute'name'屬性錯誤:'Cat'對象沒有'name'屬性15對象的封裝初始化方法

當使用類名()創(chuàng)建對象時,會自動執(zhí)行以下操作:為對象在內(nèi)存中分配空間——創(chuàng)建對象為對象的屬性設置初始值——初始化方法(init)這個初始化方法就是__init__方法,__init__是對象的內(nèi)置方法__init__方法是專門用來定義一個類具有哪些屬性的方法!

classCat:"""這是一個貓類"""def__init__(self):print("初始化方法")16對象的封裝初始化方法

在初始化方法內(nèi)部定義屬性在__init__方法內(nèi)部使用self.屬性名=屬性的初始值就可以定義屬性定義屬性之后,再使用Cat類創(chuàng)建的對象,都會擁有該屬性

classCat:def__init__(self):print("這是一個初始化方法")#定義用Cat類創(chuàng)建的貓對象都有一個name的屬性="Tom"defeat(self):print("%s愛吃魚"%)#使用類名()創(chuàng)建對象的時候,會自動調(diào)用初始化方法__init__tom=Cat()tom.eat()17對象的封裝初始化方法

改造初始化方法——初始化的同時設置初始值在開發(fā)中,如果希望在創(chuàng)建對象的同時,就設置對象的屬性,可以對__init__方法進行改造把希望設置的屬性值,定義成__init__方法的參數(shù)在方法內(nèi)部使用self.屬性=形參接收外部傳遞的參數(shù)在創(chuàng)建對象時,使用類名(屬性1,屬性2...)調(diào)用

classCat:def__init__(self,name):print("初始化方法%s"%name)=name...tom=Cat("Tom")...lazy_cat=Cat("大懶貓")...目錄ContentsSuccessWords18第三部分繼承和多態(tài)19繼承面向?qū)ο笕筇匦苑庋b根據(jù)職責將屬性和方法封裝到一個抽象的類中繼承實現(xiàn)代碼的重用,相同的代碼不需要重復的編寫多態(tài)不同的對象調(diào)用相同的方法,產(chǎn)生不同的執(zhí)行結(jié)果,增加代碼的靈活度

20繼承繼承的概念、語法和特點

繼承的概念:子類擁有父類的所有方法和屬性21繼承繼承的語法class類名(父類名):

pass子類繼承自父類,可以直接享受父類中已經(jīng)封裝好的方法,不需要再次開發(fā)子類中應該根據(jù)職責,封裝子類特有的屬性和方法例子:Dog類是Animal類的子類,Animal類是Dog類的父類,Dog類從Animal類繼承Dog類是Animal類的派生類,Animal類是Dog類的基類,Dog類從Animal類派生22繼承繼承的傳遞性C類從B類繼承,B類又從A類繼承那么C類就具有B類和A類的所有屬性和方法子類擁有父類以及父類的父類中封裝的所有屬性和方法提問哮天犬能夠調(diào)用Cat類中定義的catch方法嗎?答案不能,因為哮天犬和Cat之間沒有繼承關系23繼承方法的重寫子類擁有父類的所有方法和屬性子類繼承自父類,可以直接享受父類中已經(jīng)封裝好的方法,不需要再次開發(fā)當父類的方法實現(xiàn)不能滿足子類需求時,可以對方法進行重寫(override)24繼承重寫父類方法有兩種情況:

1)覆蓋父類的方法2)對父類方法進行擴展如果在開發(fā)中,父類的方法實現(xiàn)和子類的方法實現(xiàn),完全不同就可以使用覆蓋的方式,在子類中重新編寫父類的方法實現(xiàn)具體的實現(xiàn)方式,就相當于在子類中定義了一個和父類同名的方法并且實現(xiàn)重寫之后,在運行時,只會調(diào)用子類中重寫的方法,而不再會調(diào)用父類封裝的方法如果在開發(fā)中,子類的方法實現(xiàn)中包含父類的方法實現(xiàn)父類原本封裝的方法實現(xiàn)是子類方法的一部分就可以使用擴展的方式在子類中重寫父類的方法在需要的位置使用super().父類方法來調(diào)用父類方法的執(zhí)行代碼其他的位置針對子類的需求,編寫子類特有的代碼實現(xiàn)25多態(tài)多態(tài)是指不同的子類對象調(diào)用相同的父類方法,產(chǎn)生不同的執(zhí)行結(jié)果,也就是定義時的類型和運行時的類型不一樣,此時就稱為多態(tài),多態(tài)可以增加代碼的靈活度,多態(tài)以繼承和重寫父類方法為前提,是調(diào)用方法的技巧,不會影響到類的內(nèi)部設計。Python崇尚“鴨子類型”,“鴨子類型”可以這樣表述:“當看到一只鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那么這只鳥就可以被稱為鴨子”,也就是關注的不是對象的類型本身,而是它是如何使用的。26多態(tài)多態(tài)更容易編寫出出通用的代碼,做出通用的編程,以適應需求的不斷變化!目錄ContentsSuccessWords27第四部分游戲基本設計思路28游戲基本設計思路畫背景棋盤

俄羅斯方塊屏幕有兩個區(qū)域,一個是游戲區(qū)域,一個是方塊預覽區(qū)域。游戲區(qū)域用于下落方塊進行堆積。預覽區(qū)域用于顯示下一個要下落的方塊類型。

29游戲基本設計思路將界面拆分成若干個的網(wǎng)格每個格是10*10的大小將預覽窗口也同樣拆分成網(wǎng)格游戲就是控制在不同的時機渲染不同的網(wǎng)格30游戲基本設計思路消除機制:

當某行沒有空的方塊時,會消除這行,同時對這行以上的所有行進行移動,向下移動一行。失敗條件

當?shù)?行不為空時,則游戲結(jié)束目錄ContentsSuccessWords31第五部分俄羅斯方塊代碼分析32俄羅斯方塊的代碼分析畫背景網(wǎng)格

主要使用方法:

1、畫直線screen.drawline(x1,y1,x2,y2,pensize,pencolor)

#x1:起點橫坐標,y1:起點縱坐標,

#x2:終點橫坐標,y2:終點縱坐標,

#pensize:畫筆寬度,pencolor:畫筆顏色

2、輸出文本

text.draw(str,x,y,textColor,bgColor)

#str:文本,x:左上角頂點橫坐標,y:左上角頂點縱坐標,#textColor:前景顏色,bgColor:背景顏色33俄羅斯方塊的代碼分析畫背景網(wǎng)格classGrid(object):def__init__(self,master=None,x=10,y=10,w=193,h=303):self.x=xself.y=yself.w=wself.h=hself.rows=h//10self.cols=w//10self.bg=0x000000;print(self.rows,self.cols)

#畫背景foriinrange(320):screen.drawline(0,i,239,i,1,self.bg);

#畫邊界screen.drawline(x,y,x+w-1,y,1,0xFFFFFF);screen.drawline(x+w-1,y,x+w-1,y+h,1,0xFFFFFF);screen.drawline(x,y+h,x+w-1,y+h,1,0xFFFFFF);screen.drawline(x,y,x,y+h,1,0xFFFFFF);初始化參數(shù)渲染背景顏色畫左側(cè)區(qū)域的邊框34俄羅斯方塊的代碼分析畫背景網(wǎng)格#畫提示框邊界screen.drawline(204,10,204+32-1,10,1,0xFFFFFF);screen.drawline(204+32-1,10,204+32-1,10+32,1,0xFFFFFF);screen.drawline(204,10+32,204+32-1,10+32,1,0xFFFFFF);screen.drawline(204,10,204,10+32,1,0xFFFFFF);

defdrawgrid(self,pos,color):x=pos[1]*10+self.x+2y=pos[0]*10+self.y+2foriinrange(9):screen.drawline(x,y+i,x+9-1,y+i,1,color);

defdrawpre(self,pos,color):x=pos[1]*10+204+2y=pos[0]*10+10+2foriinrange(9):screen.drawline(x,y+i,x+9-1,y+i,1,color);渲染網(wǎng)格畫右側(cè)區(qū)域的邊框?qū)⒕W(wǎng)格坐標轉(zhuǎn)換為實際坐標畫預覽區(qū)域的網(wǎng)格35俄羅斯方塊的代碼分析方塊種類brick=[[[[1,1,1],[0,0,1],[0,0,0]],[[0,0,1],[0,0,1],[0,1,1]],[[0,0,0],[1,0,0],[1,1,1]],[[1,1,0],[1,0,0],[1,0,0]]],用嵌套列表,聲明可用的方塊的數(shù)據(jù)[[[0,0,0],[0,1,1],[0,1,1]],[[0,0,0],[0,1,1],[0,1,1]],[[0,0,0],[0,1,1],[0,1,1]],[[0,0,0],[0,1,1],[0,1,1]]],[

[[1,1,1],[0,1,0],[0,1,0]],[[0,0,1],[1,1,1],[0,0,1]],[[0,1,0],[0,1,0],[1,1,1]],[[1,0,0],[1,1,1],[1,0,0]]]]36俄羅斯方塊的代碼分析游戲類classGame(Grid):def__init__(self):super().__init__()self.back=[[0foriinrange(0,self.cols)]foriinrange(0,self.rows)]self.curRow=-10self.curCol=-10self.start=Trueself.shape=-1self.isDown=Trueself.oldrow=0self.oldcol=0self.haverow=29self.nextBrick=-1self.shape=0self.arr=[[0foriinrange(0,3)]foriinrange(0,3)]self.nextarr=[[0foriinrange(0,3)]foriinrange(0,3)]self.color={0:0x0000FF,1:0x00FF00,2:0xFF0000,3:0xFFFF00}初始化一個二維數(shù)組,用于保存屏幕上的網(wǎng)格數(shù)據(jù),1表示這個網(wǎng)格需要被渲染,0表示不需要繼承自Grid類,可以使用之前的渲染網(wǎng)格的方法儲存當前的方塊儲存預覽的方塊用字典保存顏色37俄羅斯方塊的代碼分析繪制當前的下落方塊defdrawRect(self):foriinrange(0,len(self.nextarr)):forjinrange(0,len(self.nextarr[i])):pos=(i,j)ifself.nextarr[i][j]==0:self.drawpre(pos,self.bg);elifself.nextarr[i][j]==1:self.drawpre(pos,self.color[self.nextBrick])foriinrange(0,3):forjinrange(0,3):ifself.oldrow+i>=self.rows)orself.oldcol+j>=self.colsorself.oldcol+j<-1:breakifself.oldcol+j<0:pos=(self.oldrow+i,0)else:pos=(self.oldrow+i,self.oldcol+j)ifself.back[self.oldrow+i][self.oldcol+j]==0:self.drawgrid(pos,self.bg);繪制預覽區(qū)域的方塊,雙重循環(huán)遍歷self.nextarr數(shù)組,調(diào)用父類的drawpre方法進行渲染渲染渲染下一個要顯示的方塊前,先將當前的位置渲染成背景顏色判斷是否已經(jīng)到達邊界調(diào)用父類渲染成背景顏色38俄羅斯方塊的代碼分析繪制當前的下落方塊if(self.curRow!=-10)and(self.curCol!=-10):foriinrange(0,len(self.arr)):forjinrange(0,len(self.arr[i])):ifself.arr[i][j]==1:pos=(self.curRow+i,self.curCol+j)ifself.isDown:ifi<self.haverow:self.haverow=iself.drawgrid(pos,0x00FFFF)else:self.drawgrid(pos,self.color[self.curBrick])ifself.isDown:foriinrange(0,3):forjinrange(0,3):ifself.arr[i][j]!=0:self.back[self.curRow+i][self.curCol+j]=self.arr[i][j]self.oldrow=0self.oldcol=0self.removeRow()self.isDead()self.getCurBrick()else:self.oldrow=self.curRowself.oldcol=self.curCol繪制當前正在下落的方塊,循環(huán)遍歷arr數(shù)組,根據(jù)arr中的數(shù)據(jù)進行渲染如果方塊已經(jīng)到底則改變方塊的顏色為藍色調(diào)用父類方法渲染當前方塊方塊到底之后,更新back數(shù)組,back數(shù)組中存放當前所有固定的方塊的位置調(diào)用removeRow進行消除判斷調(diào)用isDead判斷游戲失敗條件取下一個方塊的數(shù)據(jù)更新當前行和列的值39俄羅斯方塊的代碼分析行的消除defremoveRow(self):rownum=0foriinrange(0,self.rows):tag1=Trueforjinrange(0,self.cols):ifself.back[i][j]==0:tag1=Falsebreakiftag1==True:print(i,j)rownum=iforminrange(i-1,0,-1):forninrange(0,self.cols):self.back[m+1][n]=self.back[m][n]ifrownum>0:self.drawBack(rownum)行的消除判斷函數(shù)可以消除則,從當前行向上到0行開始循環(huán),將方塊向下移動從0行0列開始循環(huán)發(fā)現(xiàn)有為空的網(wǎng)格,則說明本行沒有被填滿,不能消除直接break可能存在同時消除多行的情況,處理完back數(shù)組之后調(diào)drawBack進行渲染40俄羅斯方塊的代碼分析已固定的方塊的渲染defdrawBack(self,rownum):foriinrange(self.haverow,rownum+1):forjinrange(0,self.cols):pos=(i,j)ifself.back[i][j]==0:self.drawgrid(pos,self.bg)else:self.drawgrid(pos,0x00FFFF)self.haverow+=1ifself.haverow>=self.rows:self.haverow=self.rows-1循環(huán)遍歷所有已有的固定行根據(jù)back數(shù)組,如果為0則渲染背景色,為1則渲染藍色defgetCurBrick(self):self.shape=0ifself.nextBrick==-1:self.curBrick=randint(0,len(brick)-1)self.nextBrick=randint(0,len(brick)-1)elifself.isDown:self.curBrick=self.nextBrickself.nextBrick=randint(0,len(brick)-1)self.nextarr=brick[self.nextBrick][self.shape]self.arr=brick[self.curBrick][self.shape]self.curRow=-1self.curCol=8self.isDown=False第一次調(diào)用時,同時隨機產(chǎn)生當前的方塊和預覽方塊當前方塊已經(jīng)落到底之后,則用預覽方塊替換當前方塊,并隨機產(chǎn)生新的預覽方塊更新nextarr和arr兩個數(shù)組的數(shù)據(jù)41俄羅斯方塊的代碼分析按鍵控制defonKeyboardEvent(self,key):keymatch=["Down","Left","Up","Right"]ifself.start==False:returntempCurCol=self.curColtempCurRow=self.curRowtempShape=self.shapetempArr=self.arrdirection=-1ifkeymatch[key]=="Left":self.curCol-=1direction=1elifkeymatch[key]=="Up":self.shape+=1direction=2ifself.shape>=4:self.shape=0self.arr=brick[self.curBrick][self.shape]elifkeymatch[key]=="Right":direction=3self.curCol+=1elifkeymatch[key]=="Down":direction=4self.curRow+=2ifself.isEdge(direction)==False:self.curCol=tempCurColself.curRow=tempCurRowself.shape=tempShapeself.arr=tempArrreturnTrue將鍵值對應的列表初始化向左,則更改當前列-1,方向為1向上,則更改方塊形狀,shape+1方向還是向下,如果shape已經(jīng)到4了則變回第一個形狀0調(diào)用isEdage進行邊界判斷,如果到達邊界則恢復原始位置defisEdge(self,direction):tag=Trueifdirection==1:foriinrange(0,3):forjinrange(0,3):if(self.arr[j][i]!=0)and(self.curCol+i<0orself.back[self.curRow+j][self.curCol+i]!=0):tag=Falsebreakelifdirection==3:foriinrange(0,3):forjinrange(0,3):if(self.arr[j][i]!=0)and(self.curCol+i>=self.colsorself.back[self.curRow+j][self.curCol+i]!=0):tag=Falsebreakelifdirection==4:foriinrange(0,

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論