记事本贪吃蛇游戏代码_如何用Python10分钟绘制贪吃蛇小游戏?
貪吃蛇是一款經(jīng)典的益智游戲,有PC和手機等多種版本,既簡單又耐玩。玩家通過上下左右鍵控制蛇的方向,尋找食物,每吃到一次食物,就能得到一定的積分,而且蛇的身體會越來越長。隨著蛇的身體變長,游戲的難度就會變大。當蛇碰到四周的墻壁,或者碰到自己的身體的某一個部位的時候,游戲就結(jié)束了。
我們來看一下用Python編寫這款游戲的主要思路。帶上娃一起編程既好玩又增長知識。
地圖
我們將整個游戲界面看成是由許多個小方塊組成的,每個方塊代表一個單位。這樣一來,游戲界面就由若干個小方塊形成一個地圖,地圖上的每個位置都可以表示為小方塊的整數(shù)倍,如圖1所示。
圖1
貪吃蛇的長度也用這個小方塊來表示,每次吃到食物,蛇身的長度就會增加一個單位。
程序界面
這是一款完整的游戲,所以我們一共為其設計了3個界面,除了游戲界面以外,還包括游戲開始界面和游戲結(jié)束界面。
自定義函數(shù)
我們要創(chuàng)建的函數(shù)包括:main(主程序)、startGame(游戲開始)、runGame(運行游戲)、drawFood(繪制食物)、drawSnake(繪制貪吃蛇)、drawScore(繪制成績)、moveSnake(移動貪吃蛇)、isEattingFood(是否吃到食物)、isAlive(判斷貪吃蛇是否死掉了)、gameOver(游戲結(jié)束)和terminate(終止游戲)。
事件
我們要用到的事件是鍵盤事件。鍵盤事件是玩家操控貪吃蛇移動的時候發(fā)生的事件。我們會在后面介紹的startGame()函數(shù)和gameOver()函數(shù)中監(jiān)聽鍵盤事件,并且根據(jù)事件類型,來做相應的處理。
聲音
我們會在游戲開始后,調(diào)用Sound對象的play()方法,播放的背景音樂。
導入模塊
首先,將在程序中用到的模塊都導入。我們要使用Pygame的函數(shù),因此需要導入Pygame模塊。除此之外,我們還會用到sys模塊和random模塊。sys模塊負責程序與Python解釋器的交互,用于操控Python運行時的環(huán)境,程序要使用sys模塊的exit()函數(shù)來退出游戲。random模塊用于生成隨機數(shù)。導入這3個模塊的語句如下所示:
初始化設置
為了進行游戲啟動和運行前的準備工作,程序需要做一些初始化設置工作,包括定義程序要用到的顏色、方向變量,確定游戲窗口和地圖的大小,定義游戲需要用到的一些其他變量等。先來看看這部分初始化代碼。
定義顏色變量
游戲中要用到的顏色主要包括如下幾種。
定義方向變量
為了能夠讓玩家能夠操控貪吃蛇的方向,我們在程序中定義了4個方向變量,分別和玩家操控貪吃蛇移動的上下左右相對應。
定義窗口大小
我們要為貪吃蛇游戲定義一個窗口,讓貪吃蛇在這個窗口中移動。我們通過兩個變量來定義窗口的寬和高,這是一個寬800像素、高600像素的矩形窗口。
定義地圖大小
我們使用變量mapWidth 和mapHeight 來表示地圖的寬和高。需要注意的是,地圖的寬和高都是基礎單位cellSize的整數(shù)倍。
其他變量
程序還會用到如下兩個變量:
基礎函數(shù)
程序最終要以通過函數(shù)來定義所要執(zhí)行的功能,并且通過函數(shù)調(diào)用來完成和實現(xiàn)這些功能。前面介紹了貪吃蛇這款游戲需要定義的函數(shù),這些函數(shù)是游戲程序的核心代碼,接下來,我們依次來看看這些函數(shù)是如何實現(xiàn)的。
main()函數(shù)
main()函數(shù)是程序執(zhí)行的入口。先來看一下main()函數(shù)的詳細代碼。
首先,初始化Pygame,調(diào)用pygame.init()函數(shù)進行模塊初始化。然后調(diào)用了pygame.display.set_mode()函數(shù),創(chuàng)建了一個寬800像素、高600像素的顯示窗口,返回了用于該窗口的pygame.Surface 對象并將其存儲在名為screen的變量中。接下來,調(diào)用pygame.display.set_caption()函數(shù)來設置窗口的標題,這里給游戲窗口起名為“貪吃蛇”。調(diào)用screen.fill()函數(shù),將窗口用白色填充。然后創(chuàng)建了一個時鐘(Clock)對象,將其賦值給snakeSpeedClock變量,用它來控制幀速率。
然后,調(diào)用startGame這個自定義函數(shù),這是負責啟動游戲的函數(shù),給它傳遞的參數(shù)是變量screen,后面的小節(jié)會詳細介紹這個函數(shù)。
接下來,為了保持Pygame事件循環(huán)一直運行,我們使用while循環(huán),并且循環(huán)條件就是布爾值True,這表示循環(huán)會一直進行,而退出這個循環(huán)的唯一方式是程序終止。在本書前面的示例中,我們通常都會使用一個變量作為循環(huán)條件,當程序退出時,修改這個變量來結(jié)束循環(huán)。這兩種做法的效果是相同的,相比之下,這里的用法要更加簡單一些。
在循環(huán)體中,我們先初始化混合器,然后將一段背景音樂snake.wav加載到一個Sound對象中,并且將其存儲到變量music中。接下來調(diào)用play()函數(shù)播放音樂,參數(shù)?1表示會一直循環(huán)播放。通過上述代碼,我們就為游戲添加了背景音樂。然后調(diào)用runGame函數(shù),傳遞給它的參數(shù)是變量screen和snakeSpeedClock,這個函數(shù)負責游戲運行,后面的小節(jié)還會詳細介紹這個函數(shù)。當這個函數(shù)執(zhí)行完后,就會調(diào)用music.stop()函數(shù)來停止背景音樂播放。然后,調(diào)用gameOver函數(shù)結(jié)束游戲,傳遞給它的參數(shù)是變量screen。
startGame()函數(shù)
這個函數(shù)負責控制我們的程序啟動,它接收的參數(shù)是窗口的pygame.Surface對象。我們來看一下該函數(shù)的代碼。
首先,調(diào)用image()函數(shù)在Pygame窗口中加載“gameStart.png”圖片,并創(chuàng)建一個名為gameStart的Surface對象。然后,調(diào)用blit()函數(shù),將像素從一個Surface復制到另一個Surface之上。就是把gameStart對象復制到Screen這個Surface上。通過blit()將gameStart復制到指定位置(70, 30)。
然后,調(diào)用pygame.font.SysFont函數(shù)來創(chuàng)建Font對象,并將其賦值給名為font的變量,這個對象允許我們以40點的SimHei字體繪制到Pygame的Surface上。接下來,在所創(chuàng)建的font對象上使用render()命令,把字符串“按任意鍵開始游戲”繪制到Surface上。然后,調(diào)用blit()函數(shù),將像素從一個Surface復制到另一個Surface之上。screen.blit(tip, (240, 550))負責把tip對象復制到screen這個Surface上的指定位置。
調(diào)用pygame.display.update()函數(shù),把繪制到Surface對象上的所有內(nèi)容都顯示到窗口上。
接下來,為了保持Pygame事件循環(huán)一直運行,我們使用while循環(huán)。在事件循環(huán)中,判斷事件類型如果是QUIT(關(guān)閉窗口),就調(diào)用terminate()函數(shù)終止程序,我們稍后會介紹terminate()函數(shù)。否則,如果事件類型是KEYDOWN,那么事件對象將有一個key屬性來識別按下的是哪個鍵。如果key屬性等于K_ESCAPE,表示用戶按下的是Esc鍵,意味著玩家希望結(jié)束程序,那么程序的處理方式和點擊關(guān)閉窗口一樣,調(diào)用terminate()函數(shù)終止程序。否則,表示用戶按下的是其他鍵,退出這個函數(shù),表示游戲開始運行。
當這個函數(shù)執(zhí)行后,會出現(xiàn)如圖1所示的游戲界面,這個時候,玩家可以按Esc鍵關(guān)閉程序,如果按其他的任意鍵則會開始玩游戲。
runGame()函數(shù)
這個函數(shù)控制著游戲程序運行,它接受的參數(shù)是窗口的pygame.Surface對象和Pygame的時鐘對象。runGame()函數(shù)的代碼如下所示:
首先使用random.randint()函數(shù)在3到mapWidth?8之間選取一個隨機整數(shù)賦值給變量startX,在3到mapHeight?8之間選取一個隨機整數(shù)賦值給變量startY,這兩個變量分別表示貪吃蛇初始的x坐標和y坐標。選取隨機數(shù)的目的是讓貪吃蛇出現(xiàn)的位置不是固定的,這樣就增加了游戲的不確定性。
然后,用嵌套字典的一個列表來表示貪吃蛇。每個字典表示地圖上的一個坐標,{'x': startX, 'y': startY}表示蛇頭的位置,{'x': startX - 1, 'y': startY}和{'x': startX - 2, 'y': startY}表示蛇的身體。這是一條水平放置的蛇,蛇頭靠右,有兩節(jié)蛇身。
將direction設置為RIGHT,表示方向向右。RIGHT是我們前面定義過的方向變量。
然后使用random.randint()函數(shù)在0到mapWidth?1之間選取一個隨機整數(shù)作為字典中x鍵的值,在0到mapHeight?1之間選取一個隨機整數(shù)作為字典中y鍵的值,將字典賦值給變量food。用這個變量表示食物的坐標位置。
接下來,為了保持Pygame事件循環(huán)一直運行,我們使用while循環(huán)。在事件循環(huán)中,判斷事件類型,如果是QUIT,那么調(diào)用terminate()函數(shù)終止程序。否則,如果事件類型是KEYDOWN,那么事件對象將有一個key屬性來識別按下的是哪個鍵。
如果key屬性等于K_LEFT,表示用戶按下的是向左方向鍵,并且direction != RIGHT,那么將變量direction設置為LEFT,也就是將方向設置為向左。這里,direction != RIGHT的含義是蛇頭不向右,因為蛇頭向右的話,是沒有辦法再將方向設置為向左的(因為要避免貪吃蛇直接掉頭導致頭部和身體相碰撞的情況),只有蛇頭向上、向下或向左的時候,我們才可以將蛇頭方向設置為向左。
如果key屬性等于K_RIGHT,并且direction != LEFT,那么將變量direction設置為RIGHT;如果key屬性等于K_UP,并且direction != DOWN,那么將變量direction設置為UP;如果key屬性等于K_DOWN,并且direction !=UP,那么將變量direction設置為DOWN。
如果key屬性等于K_ESCAPE,表示用戶按下的是Esc 鍵,意味著玩家希望結(jié)束程序,那么處理方式和玩家點擊關(guān)閉窗口是一樣的,調(diào)用terminate()函數(shù)終止程序。
然后,調(diào)用moveSnake()函數(shù)移動貪吃蛇,該函數(shù)的參數(shù)是變量direction和snakeCoords,稍后我們還會詳細介紹moveSnake()函數(shù)。
接下來調(diào)用isEattingFood()函數(shù),判斷貪吃蛇是否吃到食物,該函數(shù)參數(shù)是變量snakeCoords和 food,稍后我們還會詳細介紹isEattingFood()函數(shù)。
然后調(diào)用isAlive()函數(shù),判斷貪吃蛇是否死亡,該函數(shù)的參數(shù)是變量snakeCoords,并且將它的返回結(jié)果賦值給變量ret,稍后會詳細介紹isAlive()函數(shù)。判斷變量ret是否是True,如果不是,跳出while循環(huán),表示貪吃蛇已經(jīng)死了,游戲結(jié)束。
調(diào)用image.load()函數(shù)加載游戲背景圖片,并創(chuàng)建一個名為gameRun的Surface對象。調(diào)用blit()函數(shù),把gameRun對象復制到screen這個Surface上,指定位置是左上角。
然后調(diào)用drawFood()函數(shù)繪制食物,該函數(shù)的參數(shù)是變量screen和food,稍后我們還會介紹drawFood()函數(shù)。
然后調(diào)用drawSnake()函數(shù)繪制貪吃蛇,該函數(shù)的參數(shù)是變量screen和snakeCoords,稍后我們還會詳細介紹drawFood()函數(shù)。
接下來調(diào)用drawScore()函數(shù)繪制分數(shù),該函數(shù)的參數(shù)是變量screen和len(snakeCoords) – 3的結(jié)果。len(snakeCoords)表示貪吃蛇的長度。減去3,是因為貪吃蛇最初有一個蛇頭和兩節(jié)身體,也就是snakeCoords初始有3個元素,減去3就是新增的身體部分,也就是相應的得分。
調(diào)用pygame.display.update()函數(shù),把繪制到Surface對象上的所有內(nèi)容,都顯示到窗口上。調(diào)用時鐘對象的tick()方法,表示游戲運行的幀速率是snakeSpeed FPS,即每秒snakeSpeed次。
當runGame()函數(shù)執(zhí)行后,會出現(xiàn)如圖3所示的游戲界面。
圖3
下面分別介紹一下runGame()函數(shù)中用到的其他的自定義函數(shù)。
drawFood()函數(shù)
drawFood()函數(shù)用來繪制食物,它接受的參數(shù)是窗口的pygame.Surface對象和表示坐標的字典對象。drawFood()函數(shù)的代碼如下所示。
將字典food的鍵“x”對應的值乘以變量cellSize的結(jié)果賦值給變量x,將字典food的鍵“y”對應的值乘以變量cellSize的結(jié)果賦值給變量y。因為food的坐標是相對于地圖上的坐標,而不是真正窗口的坐標,只有在乘以cellSize后才能夠得到窗口上對應的像素位置。然后,調(diào)用pygame.draw.rect()函數(shù)繪制用黃色填充的一個小方塊。
drawSnake()函數(shù)
drawSnake()函數(shù)用來繪制貪吃蛇,它接受的參數(shù)是窗口的pygame.Surface對象和表示貪吃蛇的列表。drawSnake()函數(shù)的代碼如下所示。
用一個for循環(huán)來遍歷snakeCoords列表中所有的元素,把每個元素賦值給變量coord。
在每個循環(huán)體中,將字典coord的鍵“x”對應的值乘以變量cellSize,再把結(jié)果賦值給變量x,將字典coord的鍵“y”對應的值乘以變量cellSize,再把結(jié)果賦值給變量y。變量x和y對應的是窗口上的像素位置。然后調(diào)用pygame.draw.rect()函數(shù)繪制一個用深綠色填充的小方塊,再次調(diào)用pygame.draw.rect()函數(shù)在深綠色方塊中繪制一個淺綠色的小方塊。一個大方塊和一個小方塊,一起構(gòu)成了蛇的一節(jié)身體。
drawScore()函數(shù)
drawScore()函數(shù)用來繪制分數(shù),它接受的參數(shù)是窗口的pygame.Surface對象和表示分數(shù)的變量。drawScore()函數(shù)的代碼如下所示。
調(diào)用pygame.font.SysFont()函數(shù),把字符串"得分:"以及變量score的值繪制到界面上,以抗鋸齒方式繪制,文本顏色為白色,將生成的這個Font對象賦值給變量scoreSurf。然后獲取scoreSurf的矩形對象并將其賦值給變量scoreRect。指定scoreRect的左上角的坐標為(windowsWidth - 200, 50)。然后,調(diào)用blit()函數(shù),把scoreSurf對象復制到screen這個Surface上。
moveSnake()函數(shù)
moveSnake()函數(shù)用來移動貪吃蛇,它接受的參數(shù)是表示方向的變量和表示貪吃蛇的列表。moveSnake()函數(shù)會根據(jù)方向,來增加一個蛇頭的元素到列表中。moveSnake()函數(shù)的代碼如下所示。
如果變量direction等于UP,表示貪吃蛇的方向是向上,那么創(chuàng)建一個新的蛇頭元素,“x”鍵的值是原來蛇頭的“x”鍵的值不變,“y”鍵的值是原來蛇頭的“y”鍵的值減去1個單位。
否則,如果變量direction等于DOWN,表示貪吃蛇的方向是向下,那么創(chuàng)建一個新的蛇頭元素,“x”鍵的值是原來蛇頭的“x”鍵的值不變,“y”鍵的值是原來蛇頭的“y”鍵的值加上1個單位。
否則,如果變量direction等于LEFT,表示貪吃蛇的方向是向左,那么創(chuàng)建一個新的蛇頭元素,“x”鍵的值是原來蛇頭的“x”鍵的值減去1個單位,“y”鍵的值是原來蛇頭的“y”鍵的值不變。
否則,如果變量direction等于RIGHT,表示貪吃蛇的方向是向右,那么創(chuàng)建一個新的蛇頭元素,“x”鍵的值是原來蛇頭的“x”鍵的值加上1個單位,“y”鍵的值是原來蛇頭的“y”鍵的值不變。
然后,把這個新創(chuàng)建的字典元素插入到貪吃蛇列表的第一個位置。
isEattingFood()函數(shù)
isEattingFood()函數(shù)用來判斷貪吃蛇是否吃到了食物,它接受的參數(shù)是表示貪吃蛇的列表和表示食物位置的變量。isEattingFood()函數(shù)的代碼如下所示。
首先判斷列表snakeCoords的第一個元素的“x”鍵和“y”鍵的值是否等于變量food的“x”鍵和“y”鍵的值。變量HEAD等于0。
如果相等,表示蛇頭碰到了食物。那么重新設置變量food的“x”鍵和“y”鍵的值。請注意,對于列表或字典,在函數(shù)內(nèi)修改參數(shù)的內(nèi)容,會影響到函數(shù)之外的對象。
如果不相等,刪除snakeCoords列表中最后一個元素。在介紹moveSnake()函數(shù)的時候提到過,移動貪吃蛇,其實就是增加一個新的元素。例如,最初是3個元素,向右移動一步,就變成了4個元素。如果這個時候沒有吃到食物,那么為了保證元素數(shù)量不變,就要刪除最后一個元素,這樣才能確保snakeCoords列表中的元素數(shù)量沒有變化,仍然是3個元素。
isAlive()函數(shù)
isAive()函數(shù)用來判斷貪吃蛇是否死亡,它接受的參數(shù)是表示貪吃蛇的列表。isAive()函數(shù)的代碼如下所示。
首先,將變量tag設置為True。然后,判斷在地圖上的蛇頭的x坐標是否等于?1,或者蛇頭的x坐標是否等于mapWidth,或者蛇頭的y坐標是否等于?1,或者蛇頭的y坐標是否等于mapHeight,只要滿足其中的任何一個條件,就表示蛇頭碰到了墻壁,那么就將變量tag設置為False。
然后用一個for循環(huán),來遍歷snakeCoords列表中的第2個元素以及之后的元素,把每個元素賦值給變量snake_body,表示蛇的身體。
在循環(huán)體內(nèi),判斷字典snake_body的鍵“x”和“y”對應的值是否等于snakeCoords列表第一個元素,也就是蛇頭的鍵“x”和“y”對應的值,如果相等,表示蛇頭碰到了蛇的身體,那么就將變量tag設置為False。
最后,該函數(shù)返回了變量tag。如果tag是True,表示蛇還活著;如果tag是False,表示蛇死掉了。
gameOver()函數(shù)
gameOver()函數(shù)控制整個程序的結(jié)束,它接受的參數(shù)是窗口的pygame.Surface對象。gameOver()函數(shù)的代碼如下所示。
首先調(diào)用screen.fill()函數(shù),用白色填充窗口。
然后調(diào)用image()函數(shù)在Pygame窗口中加載“gameover.png”圖片,并創(chuàng)建一個名為gameOver的Surface對象。然后我們調(diào)用blit()函數(shù),把gameOver對象復制到screen這個Surface上。通過blit()將gameOver復制到指定左上角位置(0, 0)。
然后調(diào)用pygame.font.SysFont函數(shù),把字符串"按Q或者ESC退出游戲,按其他鍵重新開始游戲"繪制到界面上。然后我們調(diào)用blit()函數(shù)把tip對象復制到screen這個Surface上。
調(diào)用pygame .display.update()函數(shù),把繪制到Surface對象上的所有內(nèi)容,都顯示到窗口上。
接下來,使用while循環(huán)監(jiān)聽鍵盤事件。在事件循環(huán)中,判斷事件類型,如果是QUIT,那么調(diào)用terminate函數(shù)終止程序。否則,如果事件類型是KEYDOWN,那么事件對象將有一個key屬性來識別按下的是哪個鍵。如果key屬性等于K_ESCAPE或K_q,表示用戶按下的是Esc或Q鍵,意味著玩家希望結(jié)束程序,那么處理方式和點擊關(guān)閉窗口是一樣的,調(diào)用terminate()函數(shù)終止程序。否則,表示用戶按下的是其他鍵,結(jié)束這個函數(shù),重新開始游戲。
當這個函數(shù)執(zhí)行后,會出現(xiàn)如圖4所示的游戲界面,這個時候,可以按Q鍵和Esc鍵結(jié)束程序,也可以按任意鍵重新開始一局游戲。
圖4
terminate()函數(shù)
terminate()函數(shù)終止程序。我們來看一下該函數(shù)的代碼。
調(diào)用pygame.quit()函數(shù),它是和init()相對應的一個函數(shù)。在退出程序之前,需要調(diào)用它。然后才會退出Pygame。調(diào)用sys.exit()函數(shù),退出主程序退。
調(diào)用入口函數(shù)
最后,我們只要調(diào)用入口函數(shù)main(),程序就可以開始運行了。
到這里,我們的貪吃蛇游戲就完成了。這是一個真正意義上的完整游戲,有開始界面和結(jié)束界面,有游戲背景,還有背景音樂。嘗試著玩一玩,然后再回過頭來看看游戲的程序代碼,這樣會更有助于對代碼的理解。
《Python少兒趣味編程》
李強 李若瑜 著
編輯推薦
● 少兒編程暢銷圖書作者精心編寫 。
●全彩印刷, 提供代碼和素材下載,方便親子互動和少兒自學 。
Python簡單易學,功能強大,是少兒學習編程的首選語言。本書是少兒學習Python編程的趣味指南,全書共17章,按照由簡到難、逐步深入的方式組織各章內(nèi)容。
本書精心選取內(nèi)容,注重難易適度和趣味性,語言通俗易懂,代碼示例豐富。在多章的末尾,還給出了一些練習題并給出了解答。本書適合想要學習Python編程基礎的少兒(尤其是10歲以上的孩子)及想要教孩子學習編程的家長閱讀,也適合少兒編程培訓班的老師用作少兒編程培訓的教材。
總結(jié)
以上是生活随笔為你收集整理的记事本贪吃蛇游戏代码_如何用Python10分钟绘制贪吃蛇小游戏?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 拒收别人的回复了?有没有回的如有会的请赐
- 下一篇: 三百行python代码的项目_使用300