基于Python實(shí)現(xiàn)貪吃蛇小游戲(附源碼)
前言
這幾年人工智能技術(shù)大發(fā)展,Python因此幾乎成了第一位的語言。實(shí)際上,多年來,它不僅在軟件工程師中得到廣泛使用,也是各行業(yè)通用的專家語言,就是說,不管孩子以后做什么,都可能用得著。準(zhǔn)備針對我自己上小學(xué)的孩子,每周抽出些時(shí)間,通過學(xué)習(xí)他們感興趣的小游戲,逐步把python知識點(diǎn)帶進(jìn)游戲的制作過程中,用到哪些知識簡單的解紹一下哪些,以學(xué),以用為主。
本次我們將編寫一個(gè)貪吃蛇的游戲。通過鍵盤上、下、左、右控制小蛇上、下、左、右移動,吃到食物后長度加1;蛇頭碰到自身或窗口邊緣,游戲失敗。我們首先構(gòu)造小蛇,實(shí)現(xiàn)小蛇向4個(gè)方向移動;然后實(shí)現(xiàn)游戲失敗的判斷、吃食物增加長度、得分功能;每段游戲,增加一個(gè)功能,另存一下,容易讓孩子理解學(xué)習(xí),同時(shí)也可以讓其在每個(gè)階段增加他想增加的功能,一舉多得。最后學(xué)習(xí)函數(shù)的定義與使用,并通過進(jìn)行時(shí)間控制變更游戲難度。
主要設(shè)計(jì)
1、蛇的表示
游戲開發(fā)本身就會用到很多面向?qū)ο蟮母拍?,而蛇的身體又是一個(gè)天然的“鏈表”結(jié)構(gòu),太適合用來練習(xí)數(shù)據(jù)結(jié)構(gòu)了。
蛇怎么表示?我們可以將整個(gè)游戲區(qū)域劃分成一個(gè)個(gè)的小格子,由一組連在一起的小格子組成“蛇”,蛇頭用個(gè)蛇頭(圓帶兩個(gè)眼睛)表示,蛇身用個(gè)圓表示。我們可以用坐標(biāo)來表示每一個(gè)小方格,X 軸和 Y 軸的范圍都是可以設(shè)定好的。用一個(gè)列表來存放“蛇身”的坐標(biāo),那么一條“蛇”就出來了。
2、蛇怎么移動?
第一反應(yīng)就是像蚯蚓爬行一樣,每一個(gè)小方塊向前移動一格,但這樣實(shí)現(xiàn)起來很麻煩。想象一下我們玩過的貪吃蛇,每次“蛇”的移動感覺上是整體往前移動了一格,排除掉腦子中“蛇”的“動作”,細(xì)想移動前和移動后“蛇”的位置變化,其實(shí)除了頭尾,其他部分根本就沒有變。那就簡單了,將下一格的坐標(biāo)添加到列表開頭,并移除列表的最后一個(gè)元素,就相當(dāng)于蛇向前移動了一格。(由于蛇頭與蛇身是不同的圖片,還需要把第二張也即原先的蛇并沒有照片換成蛇身照片,要不跑幾步就成一串蛇頭了,你可以試試,把蛇身換蛇頭的那行代碼注釋掉就可看到了。)
3、玩家控制小蛇移動功能的實(shí)現(xiàn)
玩家控制小蛇移動,在update()函數(shù)中實(shí)現(xiàn)用戶按上、下、左、右方向鍵,設(shè)定direction變量取不同的值,即可實(shí)現(xiàn)玩家鍵盤控制小蛇向4個(gè)方向移動。即通過一個(gè)公共變量direction來實(shí)現(xiàn),當(dāng)鍵盤按不同的上下左右鍵時(shí)修改公共變量direction就達(dá)到了玩家控制小蛇方向的問題。
4、如何判定游戲結(jié)束?
“蛇”移動超出了游戲區(qū)的范圍或者碰到了自己就算輸了,軸坐標(biāo)的范圍是事先定好的,超出范圍很容易判斷。那么如何判斷碰到自己呢?如果腦子里想的是“蛇”動的畫面,那真的比較難了,但是放到代碼中,我們的“蛇”是一個(gè)列表,那么只要判斷下一格的坐標(biāo)是否已經(jīng)包含在“蛇”的列表中豈不就可以了?
理清了這些問題,我們就可以開始編碼了。
應(yīng)用知識點(diǎn)
1、python知識點(diǎn)
1.1 列表
游戲開發(fā)本身就會用到很多面向?qū)ο蟮母拍?,而蛇的身體又是一個(gè)天然的“鏈表”結(jié)構(gòu),太適合用來練習(xí)數(shù)據(jù)結(jié)構(gòu)了。
列表,數(shù)據(jù)類型list,list是python內(nèi)置的一種高級數(shù)據(jù)類型。list是一種有序的集合,基于鏈表實(shí)現(xiàn) 在python中應(yīng)用很廣泛,可以隨時(shí)添加和刪除其中的元素。在此游戲中用于表是蛇身,由蛇頭,蛇身組成,吃個(gè)食物,蛇身增加一段,即應(yīng)用列表添加一個(gè)蛇身圖片。蛇身的移動,用到了列表的添加與刪除功能。len()可以獲得列表長度。用索引來訪問list中每一個(gè)位置的元素,記得索引是從0開始的,也可以用負(fù)數(shù),表示從-1表示列表最后一個(gè)。
append()在列表未尾增加一個(gè)元素
如:Snake.append(snakebody) # 把蛇身加入列表中
del 刪除最后一個(gè)元素
del Snake[len(Snake)-1] # 刪除舊蛇尾
也可用 del Snake[-1]
在指定位置增加元素用insert()
如:Snake.insert(0, newSnakeHead) # 把新蛇頭加到列表的最前面
1.2 time 時(shí)間模塊
屬于Python的時(shí)間模塊?;旧?,這會增加執(zhí)行延遲,并且只會暫停當(dāng)前線程,而不會暫停整個(gè)程序。
Python的time模塊中提供了Python time.sleep()函數(shù)。在使用此Python函數(shù)之前,您需要使用以下命令導(dǎo)入此模塊:import time
導(dǎo)入此模塊后,即可使用time.sleep()函數(shù)。語法如下:
句法:睡眠(秒),如您所見,它需要一個(gè)參數(shù),即秒。在執(zhí)行過程中,這基本上會引起這么多秒的延遲,此游戲中應(yīng)用到sleep(0.2),讓游戲更新時(shí)暫緩0.2秒,通過此參數(shù)可以調(diào)試蛇的移動速度。
1.3 random模塊
random() 方法返回隨機(jī)生成的一個(gè)實(shí)數(shù),它在[0,1)范圍內(nèi)
import random random.random() #randint函數(shù),返回指定范圍的一個(gè)隨機(jī)整數(shù),包含上下限 random.randint(0,99)#返回0~99之間的整數(shù)
2、pygamezero知識點(diǎn)
Pygame Zero這個(gè)神器,它對PyGame做了很多封裝,避免寫很多枯燥的框架代碼,讓初學(xué)者可以更專注于游戲核心邏輯,容易上手。
2.1 游戲角色Acto
游戲角色Actor pgzero中所有以圖片顯示的元素都是Actor類來定義,如snakebody = Actor(‘snake2’) # 導(dǎo)入蛇身方塊圖片。也可以理解為Actor是用來代表一個(gè)你繪制到屏幕的圖形。
通過把字符串 ‘snake2’ 作為參數(shù)傳遞給 Actor 類,Pygame Zero自動加載了外星人精靈,并且圖片具有位置和大小屬性。snake2是指images文件夾下snake2.png圖片。也可以apple = Actor(‘apple’,(200,300)) # 設(shè)置圖片apple的位置。連圖片帶位置一起指定。
一個(gè)免費(fèi)的png圖片下載網(wǎng)站:https://kenney.nl/assets/page:3?q=2d
2.2 輸出中文字體
顯示中文 準(zhǔn)備:在.py同級目錄下新建fonts文件夾,并放入支持中文的字體文件simhei.ttf
if isclose: # 顯示游戲失敗信息 screen.draw.text(“游戲失敗!”, (120, HEIGHT/2-100), fontsize=100, fontname=‘simhei', color=‘yellow')
2.3鍵盤控制
from pgzero.keyboard import keys, Keyboard
可以查詢下原碼,通過keys.w,keyboard.left等進(jìn)行控制
功能截圖
代碼實(shí)現(xiàn)
1、蛇的表示
import pgzrun # 導(dǎo)入游戲庫 TILE_SIZE = 30 # 小蛇方塊的大小,20×20 WIDTH = 20*TILE_SIZE # 設(shè)置窗口的寬度為800 HEIGHT = 20*TILE_SIZE # 設(shè)置窗口的高度為600 snkaeHead = Actor('snake1') # 導(dǎo)入蛇頭方塊圖片 snkaeHead.x = WIDTH/2 # 蛇頭方塊圖片的x坐標(biāo) snkaeHead.y = HEIGHT/2 # 蛇頭方塊圖片的y坐標(biāo) Snake = [] # 存儲蛇的列表 Snake.append(snkaeHead) # 把蛇頭加入列表中 for i in range(4): # 再為蛇添加4段蛇身 print(i) snakebody = Actor('snake2') # 導(dǎo)入蛇身方塊圖片 snakebody.x = Snake[i].x - TILE_SIZE # 蛇身方塊圖片的x坐標(biāo) snakebody.y = Snake[i].y # 蛇身方塊圖片的y坐標(biāo) Snake.append(snakebody) # 把蛇身加入列表中 def draw(): # 繪制模塊,每幀重復(fù)執(zhí)行 screen.clear() # 每幀清除屏幕,便于重新繪制 for snkaebody in Snake: # 繪制蛇 snkaebody.draw() pgzrun.go() # 開始執(zhí)行游戲
2、蛇的前進(jìn)移動
蛇一直向右移動,直至完全走出屏幕
direction = 'right' def update(): # 更新模塊,每幀重復(fù)操作 newSnakeHead = Actor('snake1') # 創(chuàng)建新蛇頭的圖片 # 根據(jù)direction變量設(shè)定新蛇頭的坐標(biāo) # 如小蛇向下移動,就在舊蛇頭的下邊 if direction == 'right': # 小蛇向右移動 newSnakeHead.x = Snake[0].x + TILE_SIZE newSnakeHead.y = Snake[0].y if direction == 'left': # 小蛇向左移動 newSnakeHead.x = Snake[0].x - TILE_SIZE newSnakeHead.y = Snake[0].y if direction == 'up': # 小蛇向上移動 newSnakeHead.x = Snake[0].x newSnakeHead.y = Snake[0].y - TILE_SIZE if direction == 'down': # 小蛇向下移動 newSnakeHead.x = Snake[0].x newSnakeHead.y = Snake[0].y + TILE_SIZE Snake.insert(0, newSnakeHead) # 把新蛇頭加到列表的最前面 Snake[1].image='snake2' del Snake[len(Snake)-1] # 刪除舊蛇尾
3、控制移動方向
def update(): # 更新模塊,每幀重復(fù)操作 global direction,isclose if keyboard.left: # 如果按下鍵盤向左方向鍵 direction = 'left' # 小蛇要向左移 if keyboard.right: # 如果按下鍵盤向右方向鍵 direction = 'right' # 小蛇要向右移 if keyboard.up: # 如果按下鍵盤向上方向鍵 direction = 'up' # 小蛇要向上移 if keyboard.down: # 如果按下鍵盤向下方向鍵 direction = 'down' # 小蛇要向下移
4、游戲失敗
# 當(dāng)小蛇(新蛇頭)超出邊框時(shí),游戲失敗 if newSnakeHead.y < 0 or newSnakeHead.y > HEIGHT or newSnakeHead.x < 0 or newSnakeHead.x > WIDTH: isclose = True def draw(): # 繪制模塊,每幀重復(fù)執(zhí)行 screen.clear() # 每幀清除屏幕,便于重新繪制 for snkaebody in Snake: # 繪制蛇 snkaebody.draw() # 顯示中文 準(zhǔn)備:在.py同級目錄下新建fonts文件夾,并放入支持中文的字體文件simhei.ttf if isclose: # 顯示游戲失敗信息 screen.draw.text("游戲失??!", (120, HEIGHT/2-100), fontsize=100, fontname='simhei', color='yellow')
5、食物的隨機(jī)出現(xiàn)
當(dāng)小蛇頭碰到食物時(shí),不處理,也就是長度+1;青蛙重新在隨機(jī)位置出現(xiàn);
if newSnakeHead.x == food.x and newSnakeHead.y == food.y: food.x = random.randint(5, 20) * TILE_SIZE food.y = random.randint(5, 20) * TILE_SIZE score = score + 1 # 得分加1
6、游戲得分
設(shè)置公共變量score,當(dāng)小蛇吃到食物時(shí),score值加1,更新時(shí)屏幕顯示出得分,用如下語句。
screen.draw.text("得分:"+str(score), (100, 20), fontsize=50, fontname='simhei', color='white')
源碼
由于網(wǎng)友建意,把源碼增加在此,為方便大家查詢,特修改添之
# _*_ coding: UTF-8 _*_ # 開發(fā)團(tuán)隊(duì): 信息化未來 # 開發(fā)人員: Administrator # 開發(fā)時(shí)間:2022/9/4 18:02 # 文件名稱: 貪吃蛇.py # 開發(fā)工具: PyCharm import pgzrun # 導(dǎo)入游戲庫 from pgzero.actor import Actor from pgzero.keyboard import Keyboard from pgzero.screen import Screen keyboard: Keyboard # 類型標(biāo)注 screen: Screen # 類型標(biāo)注 import time import random # 導(dǎo)入隨機(jī)庫 TILE_SIZE = 30 # 小蛇方塊的大小,20×20 WIDTH = 20*TILE_SIZE # 設(shè)置窗口的寬度為800 HEIGHT = 20*TILE_SIZE # 設(shè)置窗口的高度為600 snkaeHead = Actor('snake1') # 導(dǎo)入蛇頭方塊圖片 snkaeHead.x = WIDTH/2 # 蛇頭方塊圖片的x坐標(biāo) snkaeHead.y = HEIGHT/2 # 蛇頭方塊圖片的y坐標(biāo) food = Actor('food') # 導(dǎo)入食物方塊圖片 food.x = random.randint(10, 20)*TILE_SIZE # 食物方塊圖片的x坐標(biāo) food.y = random.randint(10, 20)*TILE_SIZE # 食物方塊圖片的y坐標(biāo) score = 0 # 游戲得分 direction = 'right' isclose = False Snake = [] # 存儲蛇的列表 Snake.append(snkaeHead) # 把蛇頭加入列表中 for i in range(4): # 再為蛇添加4段蛇身 print(i) snakebody = Actor('snake2') # 導(dǎo)入蛇身方塊圖片 snakebody.x = Snake[i].x - TILE_SIZE # 蛇身方塊圖片的x坐標(biāo) snakebody.y = Snake[i].y # 蛇身方塊圖片的y坐標(biāo) Snake.append(snakebody) # 把蛇身加入列表中 def draw(): # 繪制模塊,每幀重復(fù)執(zhí)行 screen.clear() # 每幀清除屏幕,便于重新繪制 for snkaebody in Snake: # 繪制蛇 snkaebody.draw() food.draw() # 顯示中文 準(zhǔn)備:在.py同級目錄下新建fonts文件夾,并放入支持中文的字體文件.ttf if isclose: # 顯示游戲失敗信息 screen.draw.text("游戲失??!", (120, HEIGHT/2-100), fontsize=100, fontname='simhei', color='yellow') # fontname='宋體', screen.draw.text("得分:"+str(score), (100, 20), fontsize=50, fontname='simhei', color='white') def update(): # 更新模塊,每幀重復(fù)操作 global direction,isclose,food,score if keyboard.left: # 如果按下鍵盤向左方向鍵 direction = 'left' # 小蛇要向左移 if keyboard.right: # 如果按下鍵盤向右方向鍵 direction = 'right' # 小蛇要向右移 if keyboard.up: # 如果按下鍵盤向上方向鍵 direction = 'up' # 小蛇要向上移 if keyboard.down: # 如果按下鍵盤向下方向鍵 direction = 'down' # 小蛇要向下移 newSnakeHead = Actor('snake1') # 創(chuàng)建新蛇頭的圖片 # 根據(jù)direction變量設(shè)定新蛇頭的坐標(biāo) # 如小蛇向下移動,就在舊蛇頭的下邊 if direction == 'right': # 小蛇向右移動 newSnakeHead.x = Snake[0].x + TILE_SIZE newSnakeHead.y = Snake[0].y if direction == 'left': # 小蛇向左移動 newSnakeHead.x = Snake[0].x - TILE_SIZE newSnakeHead.y = Snake[0].y if direction == 'up': # 小蛇向上移動 newSnakeHead.x = Snake[0].x newSnakeHead.y = Snake[0].y - TILE_SIZE if direction == 'down': # 小蛇向下移動 newSnakeHead.x = Snake[0].x newSnakeHead.y = Snake[0].y + TILE_SIZE # 當(dāng)小蛇(新蛇頭)超出邊框時(shí),游戲失敗 if newSnakeHead.y < 0 or newSnakeHead.y > HEIGHT or newSnakeHead.x < 0 or newSnakeHead.x > WIDTH: isclose = True # 當(dāng)小蛇蛇頭碰到自身時(shí),游戲失敗 for snakebody in Snake: # 對所有蛇身循環(huán),判斷是否和蛇頭坐標(biāo)一致 if newSnakeHead.x == snakebody.x and newSnakeHead.y == snakebody.y: isLoose = True break # 當(dāng)小蛇頭碰到食物時(shí),不處理,也就是長度+1;青蛙重新在隨機(jī)位置出現(xiàn); if newSnakeHead.x == food.x and newSnakeHead.y == food.y: food.x = random.randint(5, 20) * TILE_SIZE food.y = random.randint(5, 20) * TILE_SIZE score = score + 1 # 得分加1 else: # 否則,刪除掉舊蛇尾,也就是蛇的長度保持不變 del Snake[len(Snake) - 1] Snake.insert(0, newSnakeHead) # 把新蛇頭加到列表的最前面 Snake[1].image='snake2' # del Snake[len(Snake)-1] # 刪除舊蛇尾 time.sleep(0.2) # 暫停0.2s pgzrun.go() # 開始執(zhí)行游戲
總結(jié)
這次我們主要制作了貪吃蛇游戲,了解了time模塊的sleep函數(shù)、clock模塊的schedule等功能,學(xué)習(xí)了列表的插入函數(shù)、break與continue語句、函數(shù)的定義與調(diào)用等知識點(diǎn)。讀者可以嘗試在本章代碼的基礎(chǔ)上繼續(xù)改進(jìn):1.實(shí)現(xiàn)得分越來越高,游戲速度越來越快的效果;2.實(shí)現(xiàn)蛇頭、蛇身不同顏色的顯示效果;
以上就是基于Python實(shí)現(xiàn)貪吃蛇小游戲(附源碼)的詳細(xì)內(nèi)容,更多關(guān)于Python貪吃蛇游戲的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python數(shù)據(jù)容器dict(字典)的實(shí)現(xiàn)
本文主要介紹了Python數(shù)據(jù)容器dict(字典)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02python圖片剪裁代碼(圖片按四個(gè)點(diǎn)坐標(biāo)剪裁)
這篇文章主要介紹了python圖片剪裁代碼(圖片按四個(gè)點(diǎn)坐標(biāo)剪裁),具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03python 迭代器和iter()函數(shù)詳解及實(shí)例
這篇文章主要介紹了python 迭代器和iter()函數(shù)詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-03-03Python實(shí)現(xiàn)正則表達(dá)式匹配任意的郵箱方法
今天小編就為大家分享一篇Python實(shí)現(xiàn)正則表達(dá)式匹配任意的郵箱方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-12-12python項(xiàng)目127.0.0.1:5000訪問失敗問題解決
Windows環(huán)境下啟動python項(xiàng)目,接口訪問失敗,本文給大家分享python項(xiàng)目127.0.0.1:5000訪問失敗問題解決方法,感興趣的朋友跟隨小編一起看看吧2023-09-09OpenCV中resize函數(shù)插值算法的實(shí)現(xiàn)過程(五種)
最新版OpenCV2.4.7中,cv::resize函數(shù)有五種插值算法:最近鄰、雙線性、雙三次、基于像素區(qū)域關(guān)系、蘭索斯插值。感興趣的可以了解一下2021-06-06python中如何利用matplotlib畫多個(gè)并列的柱狀圖
python是一個(gè)很有趣的語言,可以在命令行窗口運(yùn)行,下面這篇文章主要給大家介紹了關(guān)于python中如何利用matplotlib畫多個(gè)并列的柱狀圖的相關(guān)資料,需要的朋友可以參考下2022-01-01