Python版貪吃蛇保姆級(jí)教程(附完整代碼有詳細(xì)注釋)
Python版貪吃蛇(最后附上完整代碼并有詳細(xì)注釋):從零開(kāi)始用Pygame實(shí)現(xiàn)經(jīng)典游戲
一、前言:童年經(jīng)典游戲重生
貪吃蛇作為一款經(jīng)典游戲,承載著無(wú)數(shù)人的童年回憶。今天我們將用Python+pygame從零開(kāi)始實(shí)現(xiàn)這個(gè)經(jīng)典游戲!通過(guò)本教程,你不僅能掌握游戲開(kāi)發(fā)的基本流程,還能學(xué)習(xí)到實(shí)用的編程技巧。先來(lái)看看最終效果:
二、開(kāi)發(fā)準(zhǔn)備
環(huán)境要求
Python 3.9
Pygame==2.6.1庫(kù)(
pip install pygame==
2.6.1)
三、核心代碼解析
3.1 游戲初始化
# 初始化Pygame引擎 pygame.init() # 創(chuàng)建游戲窗口 screen = pygame.display.set_mode((800, 600)) pygame.display.set_caption("貪吃蛇大作戰(zhàn)")
3.2 游戲常量配置
WINDOW_WIDTH = 800 # 窗口寬度 WINDOW_HEIGHT = 600 # 窗口高度 CELL_SIZE = 20 # 蛇身和食物的單位尺寸 COLORS = { # 顏色字典 "BLACK": (0,0,0), "WHITE": (255,255,255), "RED": (255,0,0), # ...其他顏色 }
3.3 蛇的移動(dòng)控制
# 方向向量控制:通過(guò)元組存儲(chǔ)方向 current_dir = (1, 0) # 初始向右 # 鍵盤事件處理(防止180度轉(zhuǎn)向) if event.key == pygame.K_UP: new_dir = (0, -1) # 判斷新方向是否合法(非相反方向) if (current_dir[0] + new_dir[0] != 0) or ...: current_dir = new_dir
四、關(guān)鍵技術(shù)實(shí)現(xiàn)
4.1 蛇身繪制技巧
# 漸變顏色區(qū)分頭身 for i, (x, y) in enumerate(snake): color = COLORS["SNAKE_HEAD"] if i==0 else COLORS["SNAKE_BODY"] # 圓角矩形提升美觀度 pygame.draw.rect(screen, color, (x,y,CELL_SIZE-1,CELL_SIZE-1), border_radius=4)
4.2 智能食物生成
def generate_food(): while True: # 隨機(jī)生成坐標(biāo) x = random.randint(0, (WIDTH-CELL_SIZE)//CELL_SIZE) * CELL_SIZE y = ... # 確保不在蛇身上 if (x,y) not in snake: return (x,y)
4.3 碰撞檢測(cè)系統(tǒng)
# 邊界檢測(cè) new_head[0] < 0 or new_head[0] >= WIDTH... # 自碰檢測(cè) new_head in snake # 食物碰撞檢測(cè) new_head == food_pos
五、特色功能實(shí)現(xiàn)
5.1 速度切換系統(tǒng)
# 按住方向鍵加速 accelerate = any(keys[k] for k in (pygame.K_UP, ...)) # 動(dòng)態(tài)調(diào)整幀率 Clock().tick(ACCELERATE_FPS if accelerate else BASE_FPS)
5.2 高分記錄系統(tǒng)
def load_highscore(): try: with open('highscore.txt') as f: return int(f.read()) except: return 0 def save_highscore(): with open('highscore.txt', 'w') as f: f.write(str(high_score))
六、游戲邏輯流程圖
graph TD A[游戲初始化] --> B[主循環(huán)] B --> C{事件處理} C -->|按鍵| D[更新方向] C -->|退出| E[結(jié)束游戲] B --> F[移動(dòng)蛇頭] F --> G{碰撞檢測(cè)} G -->|碰墻/自身| H[游戲結(jié)束] G -->|吃到食物| I[增長(zhǎng)蛇身] G -->|正常移動(dòng)| J[更新位置] B --> K[重繪畫面]
擴(kuò)展方向
增加不同難度級(jí)別
添加多種特殊食物(加速、減速等)
實(shí)現(xiàn)多人對(duì)戰(zhàn)模式
加入背景音樂(lè)和音效
七、總結(jié)
通過(guò)本教程,我們完整實(shí)現(xiàn)了:
游戲窗口創(chuàng)建與繪制
蛇的移動(dòng)與控制邏輯
智能食物生成系統(tǒng)
完善的碰撞檢測(cè)
高分記錄功能
動(dòng)態(tài)速度調(diào)節(jié)
八、完整代碼
# -*- coding: utf-8 -*- import pygame import random import sys # 初始化pygame(必須的步驟,用于初始化所有pygame模塊) pygame.init() # === 游戲常量配置 === WINDOW_WIDTH = 800 # 游戲窗口寬度(單位:像素) WINDOW_HEIGHT = 600 # 游戲窗口高度(單位:像素) CELL_SIZE = 20 # 網(wǎng)格單元格大小(單位:像素) BASE_FPS = 5 # 基礎(chǔ)游戲幀率(控制蛇的正常移動(dòng)速度) ACCELERATE_FPS = 14 # 加速時(shí)的游戲幀率 # 顏色定義(RGB格式) COLORS = { "BLACK": (0, 0, 0), "WHITE": (255, 255, 255), "RED": (255, 0, 0), "GREEN": (0, 255, 0), "BLUE": (0, 100, 200), "GRID": (40, 40, 40), # 網(wǎng)格線顏色 "SNAKE_HEAD": (0, 255, 0), # 蛇頭顏色 "SNAKE_BODY": (0, 200, 0) # 蛇身顏色 } # === 游戲狀態(tài)初始化 === snake = [] # 用列表存儲(chǔ)蛇身體的坐標(biāo)(每個(gè)元素是一個(gè)元組) current_dir = (1, 0) # 當(dāng)前移動(dòng)方向(使用向量表示,初始向右) food_pos = (0, 0) # 食物位置坐標(biāo) is_playing = True # 游戲是否進(jìn)行中的狀態(tài) score = 0 # 當(dāng)前游戲分?jǐn)?shù) high_score = 0 # 歷史最高分記錄 # 初始化游戲窗口 screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) pygame.display.set_caption("貪吃蛇大作戰(zhàn)") # 窗口標(biāo)題 def draw_grid(): """繪制網(wǎng)格線背景,幫助玩家更好地觀察位置""" # 繪制垂直網(wǎng)格線 for x in range(0, WINDOW_WIDTH, CELL_SIZE): pygame.draw.line(screen, COLORS["GRID"], (x, 0), (x, WINDOW_HEIGHT)) # 繪制水平網(wǎng)格線 for y in range(0, WINDOW_HEIGHT, CELL_SIZE): pygame.draw.line(screen, COLORS["GRID"], (0, y), (WINDOW_WIDTH, y)) def generate_food(): """生成食物坐標(biāo),確保不在蛇身體上""" while True: # 計(jì)算網(wǎng)格坐標(biāo)(確保在窗口范圍內(nèi)) x = random.randint(0, (WINDOW_WIDTH - CELL_SIZE) // CELL_SIZE) * CELL_SIZE y = random.randint(0, (WINDOW_HEIGHT - CELL_SIZE) // CELL_SIZE) * CELL_SIZE # 檢查生成位置是否與蛇身體重疊 if (x, y) not in snake: return (x, y) def reset_game(): """重置游戲所有狀態(tài)到初始值""" global snake, current_dir, food_pos, is_playing, score snake = [(WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2)] # 蛇初始位置在窗口中心 current_dir = (1, 0) # 初始方向向右 food_pos = generate_food() # 生成第一個(gè)食物 is_playing = True # 游戲狀態(tài)設(shè)置為進(jìn)行中 score = 0 # 重置當(dāng)前分?jǐn)?shù) def show_text(content, size, color, position): """在指定位置顯示文字的工具函數(shù)""" font = pygame.font.SysFont('simhei', size) # 使用黑體字 text_surface = font.render(content, True, color) screen.blit(text_surface, position) def load_highscore(): """從文件讀取歷史最高分""" try: with open('highscore.txt', 'r') as f: return int(f.read()) except FileNotFoundError: return 0 # 文件不存在時(shí)返回0分 def save_highscore(): """保存最高分到文件""" with open('highscore.txt', 'w') as f: f.write(str(high_score)) # 初始化游戲 high_score = load_highscore() reset_game() # === 主游戲循環(huán) === while True: # 處理事件隊(duì)列(包括按鍵、窗口關(guān)閉等) for event in pygame.event.get(): if event.type == pygame.QUIT: # 點(diǎn)擊窗口關(guān)閉按鈕 pygame.quit() sys.exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_q: # Q鍵退出 pygame.quit() sys.exit() if event.key == pygame.K_r and not is_playing: # R鍵重啟游戲 reset_game() # 方向鍵控制(已解決反向問(wèn)題) if is_playing: new_dir = current_dir # 默認(rèn)保持當(dāng)前方向 if event.key == pygame.K_UP: new_dir = (0, -1) elif event.key == pygame.K_DOWN: new_dir = (0, 1) elif event.key == pygame.K_LEFT: new_dir = (-1, 0) elif event.key == pygame.K_RIGHT: new_dir = (1, 0) # 禁止直接反向(只有當(dāng)新方向不相反時(shí)更新) if (current_dir[0] + new_dir[0] != 0) or (current_dir[1] + new_dir[1] != 0): current_dir = new_dir # 獲取當(dāng)前按鍵狀態(tài)實(shí)現(xiàn)加速功能 keys = pygame.key.get_pressed() # 檢查是否有方向鍵被按?。ㄊ褂梦贿\(yùn)算優(yōu)化判斷) accelerate = any(keys[k] for k in (pygame.K_UP, pygame.K_DOWN, pygame.K_LEFT, pygame.K_RIGHT)) # 游戲進(jìn)行中的邏輯處理 if is_playing: # 計(jì)算新蛇頭位置 head_x, head_y = snake[0] dir_x, dir_y = current_dir new_head = (head_x + dir_x * CELL_SIZE, head_y + dir_y * CELL_SIZE) # 碰撞檢測(cè)(邊界和自身) if (new_head in snake or new_head[0] < 0 or new_head[0] >= WINDOW_WIDTH or new_head[1] < 0 or new_head[1] >= WINDOW_HEIGHT): is_playing = False # 更新最高分記錄 if score > high_score: high_score = score save_highscore() # 更新蛇的位置 snake.insert(0, new_head) if new_head == food_pos: # 吃到食物 score += 10 food_pos = generate_food() else: # 沒(méi)吃到食物時(shí)移除尾部 snake.pop() # === 繪制游戲畫面 === screen.fill(COLORS["BLACK"]) # 填充背景色 draw_grid() # 繪制網(wǎng)格線 # 繪制蛇的身體(使用漸變顏色) for i, (x, y) in enumerate(snake): # 根據(jù)部位設(shè)置顏色(頭部更亮) color = COLORS["SNAKE_HEAD"] if i == 0 else COLORS["SNAKE_BODY"] # 繪制帶圓角的蛇身 pygame.draw.rect(screen, color, (x, y, CELL_SIZE - 1, CELL_SIZE - 1), border_radius=4) # 繪制食物(使用圓形) center = (food_pos[0] + CELL_SIZE // 2, food_pos[1] + CELL_SIZE // 2) pygame.draw.circle(screen, COLORS["RED"], center, CELL_SIZE // 2 - 2) # 顯示分?jǐn)?shù)信息 show_text(f"分?jǐn)?shù): {score} 最高分: {high_score}", 24, COLORS["WHITE"], (10, 10)) # 游戲結(jié)束顯示提示 if not is_playing: text_width = 400 # 根據(jù)文字長(zhǎng)度估算居中位置 show_text("游戲結(jié)束!按 R 重新開(kāi)始", 48, COLORS["WHITE"], (WINDOW_WIDTH // 2 - text_width // 2, WINDOW_HEIGHT // 2 - 30)) # 更新畫面并控制游戲速度 pygame.display.update() # 根據(jù)加速狀態(tài)動(dòng)態(tài)調(diào)整幀率 pygame.time.Clock().tick(ACCELERATE_FPS if accelerate else BASE_FPS)
總結(jié)
到此這篇關(guān)于Python版貪吃蛇保姆級(jí)教程的文章就介紹到這了,更多相關(guān)Python貪吃蛇保姆級(jí)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用信號(hào)如何監(jiān)控Django模型對(duì)象字段值的變化詳解
這篇文章主要給大家介紹了關(guān)于利用信號(hào)如何監(jiān)控Django模型對(duì)象字段值變化的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11

Numpy中扁平化函數(shù)ravel()和flatten()的區(qū)別詳解

python cv2讀取rtsp實(shí)時(shí)碼流按時(shí)生成連續(xù)視頻文件方式