Python贪吃蛇实战:从零运行到打包exe全流程
2026/9/13 19:03:57 网站建设 项目流程

如果只允许用一个词来形容运行这个游戏源码后的感受,我会选“爽”。它不是 3A 大作,也没有任何美术资源,就是一段几百行的 Python 代码,但你会在里面体会到完整的游戏闭环:键盘控制、碰撞检测、食物生成、分数累积、游戏结束。更重要的是,这个项目能把“学 Python”变成“玩 Python”,从源码阅读到功能扩展,每一步都有即时反馈。

这篇文章会把整个流程走一遍:环境准备、源码结构、运行测试、自动批量验证、打包 exe 可执行文件,以及如何顺手接一个本地排行榜 API。不管你是刚装好 Python 的纯新手,还是想拿小项目练手的老手,都可以按这篇内容完整复现。先给结论:这个贪吃蛇项目几乎不挑硬件,纯 CPU 就能跑,依赖只有一个 pygame,Windows、macOS、Linux 都能运行,非常适合作 Python 入门后的第一个实战项目。

1. 核心能力速览

能力项说明
项目类型Python 游戏实战练手项目
核心玩法贪吃蛇:方向控制、吃食物、加速增长、碰撞结束
运行环境Python 3.8 及以上
第三方依赖仅 pygame(可选的 Flask 用于排行榜 API)
显存/GPU 需求不需要独立显卡,纯 CPU 即可
支持平台Windows / macOS / Linux
启动方式命令行运行 Python 脚本
是否支持打包支持,通过 PyInstaller 打包为 exe
是否支持 API可通过 Flask 扩展本地排行榜接口
是否支持批量任务支持,通过无界面自动游玩脚本批量统计分数
适合人群Python 初学者、想巩固基础语法与面向对象编程的开发者

从功能上来看,这个项目并不复杂,但它覆盖的知识点很全面:变量、列表、字典、函数、循环、条件判断、随机数、事件监听、类与对象。对刚学完 Python 基础语法的人来说,它是一个把语法转成真实产出的最佳跳板。

2. 为什么游戏化练手比刷教程更有效

2.1 即时反馈降低放弃概率

刷语法题时,你往往要等很久才能看到“我能用它做什么”的正反馈。游戏项目的反馈是即时的:按下方向键,蛇就动;吃到食物,分数就加;撞到墙,游戏就结束。这种反馈链能提升代码修改动力。

2.2 小代码量覆盖完整流程

一个贪吃蛇的主逻辑可以压缩到 150 行以内,但它已经把软件开发的完整流程走了一遍:状态初始化、输入处理、逻辑更新、碰撞检测、渲染输出。这种“小而全”的结构非常适合作为第一个独立完成的程序。

2.3 修改门槛低,扩展方向多

游戏的核心玩法清晰,边界明确,很适合做二次开发。你可以加暂停、加障碍、加计分板,或者把控制方式改成 AI 自动游玩。每加一个功能,都是在练“如何拆解需求、如何改代码、如何调 bug”。

2.4 适合拿去演示和分享

游戏类的项目能直接跑出可见结果,截图、录屏、发给朋友都方便。这种“可以给别人看”的属性,对编程学习初期的成就感培养很有帮助。

3. 环境准备:Python 安装与编辑器配置

3.1 检查 Python 是否已经安装

先打开终端或命令行工具,执行:

python --version

如果输出类似Python 3.10.11,说明已经装好。如果提示“python 不是内部或外部命令”,说明 Python 还没安装,或者没有加入环境变量。

Windows 用户也可以试一下:

py --version

3.2 安装 Python

推荐去 Python 官网下载安装包,安装时务必勾选“Add Python to PATH”这个选项,否则后续命令行里找不到 Python。

安装完成后,重新打开命令行,确认版本信息能正常输出,再继续下一步。

3.3 安装 pygame

命令:

pip install pygame

如果你使用的是国内镜像,可以加快下载速度:

pip install pygame -i https://pypi.tuna.tsinghua.edu.cn/simple

3.4 选择编辑器

推荐 VS Code 或 PyCharm。

VS Code 安装 Python 扩展后,可以直接在编辑器里运行脚本,也能看到更清晰的错误提示。本文的所有命令都基于命令行,用任何编辑器都能复现。

3.5 准备项目目录

建议单独建一个文件夹,比如snake_game,后续所有代码和打包文件都放在里面,方便管理。

mkdir snake_game cd snake_game

4. 游戏源码结构与完整代码

4.1 项目文件结构

snake_game/ ├── snake.py # 主游戏脚本 ├── auto_test.py # 无界面自动游玩测试脚本 ├── server.py # 本地排行榜 API(可选) └── dist/ # 打包输出目录

4.2 完整可运行代码

下面这段代码是 pygame 版贪吃蛇的核心实现。直接保存为snake.py

import random import sys import pygame # 初始化 pygame pygame.init() # 窗口与网格参数 WIDTH, HEIGHT = 600, 600 CELL = 20 FPS = 10 # 颜色 BLACK = (0, 0, 0) GREEN = (0, 200, 0) RED = (200, 0, 0) WHITE = (255, 255, 255) # 窗口与时钟 screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("贪吃蛇:Python 实战练手") clock = pygame.time.Clock() font = pygame.font.Font(None, 36) def generate_food(snake): """生成食物,避免出现在蛇身上""" while True: food = [ random.randint(0, (WIDTH - CELL) // CELL) * CELL, random.randint(0, (HEIGHT - CELL) // CELL) * CELL, ] if food not in snake: return food def draw_snake(snake): for block in snake: pygame.draw.rect(screen, GREEN, (block[0], block[1], CELL, CELL)) def draw_food(food): pygame.draw.rect(screen, RED, (food[0], food[1], CELL, CELL)) def show_score(score): text = font.render(f"Score: {score}", True, WHITE) screen.blit(text, (10, 10)) def main(): snake = [[100, 100], [80, 100], [60, 100]] direction = "right" food = generate_food(snake) score = 0 running = True while running: # 事件监听 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_UP and direction != "down": direction = "up" elif event.key == pygame.K_DOWN and direction != "up": direction = "down" elif event.key == pygame.K_LEFT and direction != "right": direction = "left" elif event.key == pygame.K_RIGHT and direction != "left": direction = "right" # 移动蛇头 head = snake[0].copy() if direction == "up": head[1] -= CELL elif direction == "down": head[1] += CELL elif direction == "left": head[0] -= CELL elif direction == "right": head[0] += CELL # 碰撞检测:撞墙或撞自己 if head[0] < 0 or head[0] >= WIDTH or head[1] < 0 or head[1] >= HEIGHT: running = False if head in snake: running = False snake.insert(0, head) # 吃到食物 if head[0] == food[0] and head[1] == food[1]: score += 1 food = generate_food(snake) else: snake.pop() # 渲染 screen.fill(BLACK) draw_snake(snake) draw_food(food) show_score(score) pygame.display.flip() clock.tick(FPS) pygame.quit() print(f"游戏结束,最终得分:{score}") if __name__ == "__main__": main()

4.3 代码关键点拆解

4.3.1 蛇的表示方式

蛇用二维列表表示,每一项是一个[x, y]坐标。蛇头是snake[0],蛇尾是snake[-1]。这种设计让“移动”变得很简单:插入新蛇头,如果没有吃到食物就移除蛇尾。

4.3.2 方向控制逻辑

为了防止玩家在同一帧内按两个方向导致蛇反向移动,代码里加了方向互斥判断:

if event.key == pygame.K_UP and direction != "down": direction = "up"

这样蛇不能直接穿过自己身体往回走。

4.3.3 食物生成

sleep 函数generate_foodwhile True循环确保食物不会生成在蛇身上。对新手来说,这种写法值得记下来:当需要随机生成一个满足特定条件的数值时,轮询检查是简单且可靠的方案。

4.3.4 碰撞检测

撞墙检测判断的是蛇头坐标是否超出窗口边界。撞自己检测判断的是蛇头是否出现在蛇身列表里。这里有个细节:因为蛇头刚被插入snake,所以判断顺序是先检测,后插入。如果先插入再检测,蛇头永远会算作撞到自己,导致游戏无法开始。

5. 运行游戏与功能测试

5.1 启动游戏

在项目目录下执行:

python snake.py

正常情况下会弹出一个黑色窗口,左上角显示分数,一条绿色蛇在画面中移动。

5.2 测试用例清单

测试项操作预期结果
窗口启动执行脚本窗口正常打开,蛇开始移动
方向控制按上下左右方向键蛇按对应方向移动,不能直接反向
吃食物控制蛇靠近红色方块食物消失,分数 +1,蛇身变长
撞墙结束让蛇头碰触窗口边缘游戏退出,命令行输出最终分数
撞自己结束让蛇头碰触自身身体游戏退出,命令行输出最终分数
窗口关闭点击窗口关闭按钮程序正常退出

5.3 判定成功的标准

以上测试项全部通过,说明项目可以稳定运行。重点观察两点:方向控制是否流畅、分数是否在吃到食物后正确递增。如果出现闪退、卡顿、按键无响应,需要按第九章排查。

5.4 第一次修改建议

FPS从 10 改成 15,然后重新运行,感受游戏速度变化:

FPS = 15

这一步能直观理解“帧率”对游戏手感的影响,也是第一次改代码的最佳体验。

6. 自动游玩与批量统计测试

手动玩只能测试单局体验。要做稳定性验证,可以写一个无界面自动游玩脚本,让蛇自己朝食物走,批量跑几十局,统计平均得分和最大分数。这是练习“批量任务 + 日志统计”的好机会。

6.1 无界面自动游玩脚本

将下面的代码保存为auto_test.py

import random class SnakeGame: """无界面的贪吃蛇逻辑模拟器""" def __init__(self, width=30, height=30): self.width = width self.height = height self.snake = [[15, 15], [14, 15], [13, 15]] self.direction = "right" self.score = 0 self.food = self._generate_food() def _generate_food(self): while True: food = [ random.randint(0, self.width - 1), random.randint(0, self.height - 1), ] if food not in self.snake: return food def _step(self): head = self.snake[0].copy() if self.direction == "up": head[1] -= 1 elif self.direction == "down": head[1] += 1 elif self.direction == "left": head[0] -= 1 elif self.direction == "right": head[0] += 1 # 撞墙或撞自己 if head[0] < 0 or head[0] >= self.width or head[1] < 0 or head[1] >= self.height: return False if head in self.snake: return False self.snake.insert(0, head) if head[0] == self.food[0] and head[1] == self.food[1]: self.score += 1 self.food = self._generate_food() else: self.snake.pop() return True def auto_play(self, max_steps=1000): """自动朝食物方向移动""" for _ in range(max_steps): head = self.snake[0] dx = self.food[0] - head[0] dy = self.food[1] - head[1] if abs(dx) > abs(dy): self.direction = "right" if dx > 0 else "left" else: self.direction = "down" if dy > 0 else "up" if not self._step(): break return self.score def run_batch(n=50): """批量运行 n 局,返回统计结果""" scores = [] for i in range(n): game = SnakeGame() score = game.auto_play() scores.append(score) print(f"第 {i + 1} 局结束,得分:{score}") if scores: avg_score = sum(scores) / len(scores) print(f"\n共运行 {n} 局") print(f"平均得分:{avg_score:.2f}") print(f"最高得分:{max(scores)}") print(f"最低得分:{min(scores)}") return scores if __name__ == "__main__": run_batch(50)

运行方式:

python auto_test.py

6.2 批量测试的价值

这个脚本不依赖 pygame,在命令行就能跑。它把游戏核心逻辑从界面渲染中分离出来,方便做自动化验证。你还能把它进一步改造成:

  • 统计不同参数下的平均得分。
  • 测试不同初始方向策略的胜率。
  • 用日志文件记录每一局的轨迹,方便复盘。

这种“把逻辑从界面中抽出来”的思路,在后续做算法设计和自动化测试时非常重要。

7. 打包为 exe 可执行文件

7.1 安装 PyInstaller

pip install pyinstaller

7.2 基本打包命令

pyinstaller -F -w snake.py

参数解释:

  • -F:打包为单个可执行文件。
  • -w:运行时不显示命令行窗口。

打包完成后,可执行文件在dist/snake.exe(Windows)或dist/snake(macOS/Linux)。

7.3 保存分数日志的打包方式

注意:-w会隐藏控制台窗口,导致print()输出的分数不可见。如果希望始终保留运行日志,可以去掉-w

pyinstaller -F snake.py

这样游戏结束后,命令行窗口里仍然能显示最终得分。

7.4 打包后文件过大

如果发现 exe 体积偏大,这是 PyInstaller 打包 pygame 的正常现象,不必担心。pygame 本身包含多项媒体支持,打包后体积通常在几十 MB 级别。想减小体积,可以尝试压缩可执行文件或用 UPX 压缩,但对这个小项目来说,体积不是关键问题。

7.5 杀毒软件误报

Windows 下使用 PyInstaller 打包的 exe 偶发杀毒软件误报。建议在测试环境先运行几款杀毒软件扫描确认,或者把打包结果分发给自己信任的人再使用,不要直接对外传播不明来源的 exe。

8. 接口 API 与 Web 扩展思路

贪吃蛇本身不依赖网络。但如果你想把它改造成一个可以展示给朋友的小项目,可以给游戏加一个本地排行榜 API。这里用 Flask 实现一个最简单的服务。

8.1 安装 Flask

pip install flask

8.2 排行榜接口实现

保存为server.py

from flask import Flask, jsonify, request app = Flask(__name__) # 内存排行榜 scores = [] @app.route("/api/score", methods=["POST"]) def add_score(): data = request.get_json(force=True) player = data.get("player", "anonymous") score = data.get("score", 0) scores.append({"player": player, "score": score}) scores.sort(key=lambda x: x["score"], reverse=True) return jsonify({"ok": True, "count": len(scores)}) @app.route("/api/scores", methods=["GET"]) def list_scores(): return jsonify(scores[:10]) if __name__ == "__main__": app.run(host="127.0.0.1", port=5000)

启动服务:

python server.py

8.3 调用接口测试

新增分数:

curl -X POST http://127.0.0.1:5000/api/score \ -H "Content-Type: application/json" \ -d "{\"player\": \"admin\", \"score\": 25}"

查询排行榜:

curl http://127.0.0.1:5000/api/scores

用 Python 的requests调用也一样:

import requests response = requests.post( "http://127.0.0.1:5000/api/score", json={"player": "test_user", "score": 18}, timeout=5, ) print(response.json())

8.4 接口扩展提醒

当前接口数据保存在内存里,服务重启后数据会丢失。如果要持久化,可以把数据写入 JSON 文件或 SQLite。这个扩展思路适合练习 Web API 基础,但注意只适合本地测试环境,不要直接暴露到公网,否则需要加认证和访问限制。

9. 常见问题与排查方法

问题现象可能原因排查方式解决方案
提示python不是内部或外部命令Python 未安装或未加入 PATH执行python --versionpy --version重新安装 Python 并勾选 Add Python to PATH
提示No module named 'pygame'依赖未安装执行pip show pygame执行pip install pygame
运行后窗口闪退代码报错但窗口提前关闭使用命令行运行python snake.py查看报错按报错信息修复代码或依赖
方向键控制反向坐标方向理解错误检查方向改变时的坐标加减逻辑y 轴向下增大时,up 应减小 y 值
蛇一开局就结束蛇头初始位置和方向冲突打印初始蛇列表检查确保初始蛇身坐标沿移动方向排列
打包后 exe 无法运行被杀毒软件拦截或模块缺失查看杀毒隔离记录,或命令行运行 exe添加信任或重新打包
Flask 接口无法访问服务未启动或端口占用执行python server.py检查终端输出切换端口或关闭占用程序
自动游玩脚本得分一直为 0自动方向策略陷入死循环打印每步方向与位置增加随机避障逻辑或调整方向策略

10. 最佳实践与学习建议

10.1 第一次先跑通,不要急着加功能

先把原版代码运行起来,确认每一行代码的作用,再开始修改。新手最忌讳一边运行一边大改,出了问题无法判断是哪一步引入的。

10.2 用 Git 保存每次修改

给项目初始化 Git 仓库,每完成一个功能提交一次。这样能清楚地看到每次改动的影响范围,也能随时回退到可运行版本。

10.3 把界面和逻辑分离

在自动游玩脚本里,我特意把游戏逻辑写成独立类。这个设计不仅是自动化测试的基础,也是后续扩展的核心。建议你在个人项目里尽量把“业务逻辑”和“展示层”分开。

10.4 合理管理素材和源码目录

如果后续加入音效、图片、字体等资源,建议统一放到assets目录,并把所有资源路径用相对路径管理:

snake_game/ ├── assets/ │ ├── sounds/ │ └── images/ ├── src/ │ ├── game.py │ └── auto_test.py └── README.md

10.5 批量任务一定要加日志

自动游玩脚本输出了每一局的分数,并在最后汇总统计。真正处理批量任务时,哪怕只是批量测试,也要保留每一轮的结果,否则后期很难定位问题。

10.6 接口服务要控制访问范围

排行榜 API 只监听127.0.0.1,意味着只能本机访问。想给朋友展示时,可以改成0.0.0.0,但必须考虑认证和网络安全风险。对外暴露接口前,建议先确认不会泄露敏感信息。

10.7 发布和分发前做好效果复核

如果想把这个项目发布到博客或开源平台,记得检查源码里是否有临时路径、本机用户名、自定义配置等隐私信息。打包的 exe 也需要测试不同 Windows 版本下的兼容性。

11. 总结与下一步

这个贪吃蛇项目最值得尝试的点,是它把 Python 基础语法变成了一个能玩、能改、能分享的完整作品。从运行原版、修改参数、自动测试、打包 exe 到接一个简单 API,整个过程能覆盖大部分 Python 初学者应该掌握的核心技能。

第一次动手建议先完成三条线:

  • 运行原版游戏,把每个函数的作用读一遍,尤其是方向控制和碰撞检测。
  • 写一个自动游玩脚本,跑 50 局批量统计分数,验证逻辑稳定性。
  • 把游戏打包成 exe,发给身边朋友试玩,收集反馈。

最容易踩的坑有三个:一是方向控制里忘记做反向限制,二是碰撞检测的顺序写错,三是刚装好 pygame 就急着写复杂功能但没先跑通最小版本。这三个问题在本文对应章节都给出了排查思路,遇到时可以直接对照解决。

后续扩展方向可以继续做:给游戏加障碍物和关卡系统、尝试用 AI 算法让蛇自动寻路、把排行榜数据接入 SQLite 持久化、给游戏增加音效和背景音乐。每一步都是在不同维度上提升你的 Python 工程能力。建议先把这篇内容里四个脚本完整跑通一遍,再挑选一个方向深入改。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询