【童年经典小游戏】使用Python实现经典贪吃蛇游戏

devtools/2024/12/26 22:50:54/

文章目录

  • 使用Python实现经典贪吃蛇游戏
  • 简介
  • 实现思路与准备
  • 代码实现
    • 完整代码
  • 代码关键点解析
    • 初始化与游戏窗口
    • 贪吃蛇的表示与移动
    • 食物的生成
    • 碰撞检测与游戏结束
  • 运行代码
  • 中文不显示问题解决
  • 拓展与优化建议
  • 总结

使用Python实现经典贪吃蛇游戏

贪吃蛇(Snake)作为一个经典的小游戏,从早期的手机游戏到网页小游戏,一直深受玩家的喜爱。本文将详细介绍如何使用Python来实现一个简化版的贪吃蛇游戏,包括所需库的选择、游戏逻辑的设计、关键代码的剖析,以及如何对代码进行拓展和优化。

简介

贪吃蛇的游戏规则相对简单:玩家通过控制蛇的移动方向,让蛇吃掉场景中的食物,每吃到一个食物,蛇身会增长一节,同时得分增加。当蛇撞到墙壁或自身时,游戏结束。虽然逻辑简单,但是实现起来需要兼顾用户交互、动画刷新和碰撞检测等多个层面的问题。

实现思路与准备

游戏框架与库选择

实现贪吃蛇有多种途径,这里我们将使用Python的Pygame库来完成,它是一个基于SDL的简单易用的游戏开发框架。Pygame的优势在于:

  • 易于安装与使用
  • 提供处理图形、输入事件、声音等的API
  • 社区资源丰富

游戏基本逻辑

  1. 初始化游戏场景:定义窗口大小、背景颜色、刷新率等基本参数。
  2. 表示贪吃蛇:可以使用列表来表示蛇的身体,每个元素代表一个“块”的坐标(如网格坐标)。蛇头位于列表末尾,列表头部为蛇尾。
  3. 控制方向:通过键盘事件获取上下左右方向键的输入,更改蛇移动的方向。
  4. 移动与增长:每帧更新蛇头位置。如果吃到食物,不移除蛇尾(长度增加),否则移除蛇尾,保持长度。
  5. 食物生成:在随机位置生成食物,确保不与蛇身重叠。
  6. 碰撞检测:检测蛇头是否碰到边界或自身身体块,如是则游戏结束。
  7. 得分与显示:在窗口中显示当前得分、游戏状态等信息。

代码实现

完整代码

下面是一个简单版本的贪吃蛇代码示例。请确保本机已安装pygame库,可通过pip install pygame命令安装。

python">import pygame
import random
import sys# 初始化Pygame
pygame.init()# 定义颜色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (200, 0, 0)
GREEN = (0, 200, 0)# 游戏窗口尺寸与标题
WIDTH, HEIGHT = 600, 400
BLOCK_SIZE = 20  # 蛇与食物的大小
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("贪吃蛇游戏")clock = pygame.time.Clock()# 字体设置
font = pygame.font.SysFont(None, 30)def draw_text(msg, color, x, y):text = font.render(msg, True, color)screen.blit(text, [x, y])def create_food(snake_list):while True:x = random.randint(0, (WIDTH // BLOCK_SIZE) - 1) * BLOCK_SIZEy = random.randint(0, (HEIGHT // BLOCK_SIZE) - 1) * BLOCK_SIZEif [x, y] not in snake_list:return [x, y]def game_loop():# 初始参数game_over = Falsegame_close = False# 初始蛇位置与移动方向x = WIDTH // 2y = HEIGHT // 2x_change = 0y_change = 0snake_list = []snake_length = 1food = create_food(snake_list)score = 0while not game_over:while game_close:screen.fill(BLACK)draw_text("游戏结束,按 Q 退出 或 C 重来", RED, WIDTH//4, HEIGHT//3)draw_text(f"得分: {score}", WHITE, WIDTH//4, HEIGHT//3 + 40)pygame.display.update()for event in pygame.event.get():if event.type == pygame.KEYDOWN:if event.key == pygame.K_q:game_over = Truegame_close = Falseif event.key == pygame.K_c:return  # 重新开始# 方向控制for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()elif event.type == pygame.KEYDOWN:if event.key == pygame.K_LEFT and x_change == 0:x_change = -BLOCK_SIZEy_change = 0elif event.key == pygame.K_RIGHT and x_change == 0:x_change = BLOCK_SIZEy_change = 0elif event.key == pygame.K_UP and y_change == 0:y_change = -BLOCK_SIZEx_change = 0elif event.key == pygame.K_DOWN and y_change == 0:y_change = BLOCK_SIZEx_change = 0# 更新蛇头位置x += x_changey += y_change# 边界检测if x < 0 or x >= WIDTH or y < 0 or y >= HEIGHT:game_close = Truescreen.fill(BLACK)# 绘制食物pygame.draw.rect(screen, GREEN, [food[0], food[1], BLOCK_SIZE, BLOCK_SIZE])# 更新蛇身体列表snake_head = [x, y]snake_list.append(snake_head)if len(snake_list) > snake_length:del snake_list[0]# 蛇头碰到身体检测for segment in snake_list[:-1]:if segment == snake_head:game_close = True# 绘制蛇for segment in snake_list:pygame.draw.rect(screen, WHITE, [segment[0], segment[1], BLOCK_SIZE, BLOCK_SIZE])draw_text(f"得分: {score}", WHITE, 10, 10)pygame.display.update()# 判断是否吃到食物if x == food[0] and y == food[1]:food = create_food(snake_list)snake_length += 1score += 10clock.tick(10)  # 控制游戏帧率def main():while True:game_loop()if __name__ == "__main__":main()

代码关键点解析

初始化与游戏窗口

python">pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("贪吃蛇游戏")
  • pygame.init()初始化Pygame。
  • set_mode创建游戏窗口,set_caption为窗口标题。
  • clock = pygame.time.Clock()用于控制游戏的刷新帧率。

贪吃蛇的表示与移动

python">snake_list = []
snake_length = 1
  • snake_list列表用于存储蛇每个节的坐标,如[ [x1, y1], [x2, y2], … ],末尾为蛇头。
  • 每次移动时将新的头部坐标加入snake_list末尾,如果没有吃到食物,则移除首元素(蛇尾),达到移动效果。

食物的生成

python">def create_food(snake_list):while True:x = random.randint(0, (WIDTH // BLOCK_SIZE) - 1) * BLOCK_SIZEy = random.randint(0, (HEIGHT // BLOCK_SIZE) - 1) * BLOCK_SIZEif [x, y] not in snake_list:return [x, y]
  • 随机生成网格点作为食物位置,保证不与蛇身重叠。
  • 每次吃到食物后重新调用此函数获得新位置。

碰撞检测与游戏结束

python">if x < 0 or x >= WIDTH or y < 0 or y >= HEIGHT:game_close = True
  • 检测蛇头坐标是否超出游戏区域,如是则表示撞墙,游戏结束。
python">for segment in snake_list[:-1]:if segment == snake_head:game_close = True
  • 检查蛇头是否与身体其它部分重叠,若是则游戏结束。

运行代码

首先在桌面创建一个文本文件,将代码复制进去,然后重命名为.py文件

之后我们打开终端(win+r)输入cmd
然后右键文件属性,找到路径
在cmd中输入 cd 文件路径,就可以进入到相应的路径中去,之后输入

python">Python 文件名

在这里插入图片描述

上方向键:向上移动
下方向键:向下移动
左方向键:向左移动
右方向键:向右移动
游戏目标是让蛇吃掉出现的绿色方块(食物)。每当蛇吃到食物:
蛇身长度会增加一格。
得分会增加10分。
需要注意的要点:
切勿让蛇头碰到游戏窗口的边界,否则游戏结束。
不要让蛇头碰到自己身体的其他部分,否则游戏结束。
游戏结束时,屏幕上会显示相应提示,可按 C 键重新开始,或按 Q 键退出游戏

中文不显示问题解决

下面的链接作者会教你如何下载字体
https://gitcode.com/open-source-toolkit/c55ef/overview?utm_source=tools_gitcode&index=top&type=card&&null
在这里插入图片描述

python"># -*- coding: utf-8 -*-
import pygame
import random
import sys# 初始化Pygame
pygame.init()# 定义颜色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (200, 0, 0)
GREEN = (0, 200, 0)# 游戏窗口尺寸与标题
WIDTH, HEIGHT = 600, 400
BLOCK_SIZE = 20  # 蛇与食物的大小
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("贪吃蛇游戏")clock = pygame.time.Clock()# 使用支持中文的字体(需准备支持中文的字体文件,如simhei.ttf放在同目录下)
font = pygame.font.Font("simhei.ttf", 30)def draw_text(msg, color, x, y):text = font.render(msg, True, color)screen.blit(text, [x, y])def create_food(snake_list):while True:x = random.randint(0, (WIDTH // BLOCK_SIZE) - 1) * BLOCK_SIZEy = random.randint(0, (HEIGHT // BLOCK_SIZE) - 1) * BLOCK_SIZEif [x, y] not in snake_list:return [x, y]def game_loop():# 初始参数game_over = Falsegame_close = False# 初始蛇位置与移动方向x = WIDTH // 2y = HEIGHT // 2x_change = 0y_change = 0snake_list = []snake_length = 1food = create_food(snake_list)score = 0while not game_over:while game_close:screen.fill(BLACK)draw_text("游戏结束,按 Q 退出 或 C 重来", RED, WIDTH//4, HEIGHT//3)draw_text(f"得分: {score}", WHITE, WIDTH//4, HEIGHT//3 + 40)pygame.display.update()for event in pygame.event.get():if event.type == pygame.KEYDOWN:if event.key == pygame.K_q:game_over = Truegame_close = Falseelif event.key == pygame.K_c:return  # 重新开始elif event.type == pygame.QUIT:pygame.quit()sys.exit()# 方向控制for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()elif event.type == pygame.KEYDOWN:# 避免180度掉头:当向左移动时不允许直接向右,向上时不允许直接向下,反之亦然if event.key == pygame.K_LEFT and x_change == 0:x_change = -BLOCK_SIZEy_change = 0elif event.key == pygame.K_RIGHT and x_change == 0:x_change = BLOCK_SIZEy_change = 0elif event.key == pygame.K_UP and y_change == 0:y_change = -BLOCK_SIZEx_change = 0elif event.key == pygame.K_DOWN and y_change == 0:y_change = BLOCK_SIZEx_change = 0# 如果蛇还未开始移动,则不更新位置(防止游戏开始后立即结束)if x_change == 0 and y_change == 0:# 等待用户进行第一次方向输入pygame.display.update()clock.tick(10)continue# 更新蛇头位置x += x_changey += y_change# 边界检测if x < 0 or x >= WIDTH or y < 0 or y >= HEIGHT:game_close = Truescreen.fill(BLACK)# 绘制食物pygame.draw.rect(screen, GREEN, [food[0], food[1], BLOCK_SIZE, BLOCK_SIZE])# 更新蛇身体列表snake_head = [x, y]snake_list.append(snake_head)if len(snake_list) > snake_length:del snake_list[0]# 蛇头碰到身体检测for segment in snake_list[:-1]:if segment == snake_head:game_close = True# 绘制蛇for segment in snake_list:pygame.draw.rect(screen, WHITE, [segment[0], segment[1], BLOCK_SIZE, BLOCK_SIZE])draw_text(f"得分: {score}", WHITE, 10, 10)pygame.display.update()# 判断是否吃到食物if x == food[0] and y == food[1]:food = create_food(snake_list)snake_length += 1score += 10clock.tick(10)  # 控制游戏帧率def main():while True:game_loop()if __name__ == "__main__":main()

拓展与优化建议

添加音效:在吃食物或游戏结束时播放音效。
难度调节:增加游戏关卡或根据得分提升蛇的移动速度。
UI美化:换成更精美的图片作为蛇身和食物贴图。
排行榜功能:记录每次游戏的分数,并在游戏结束时显示历史最高分。

总结

通过本篇博客的学习,我们了解了如何借助Python与Pygame实现一个简单的贪吃蛇游戏。从基础的游戏循环、蛇与食物的数据结构设计,到碰撞检测与绘制画面,都有了一个清晰的实现范例。未来,您可以在这个基础上添加更多特性,打造一款更丰富、更有趣的游戏体验,当然这仅仅是一个小案例,若想要完整的实现,可以看看建议,或者结合其他游戏开发工具,unity,虚幻等
请添加图片描述


http://www.ppmy.cn/devtools/145647.html

相关文章

MySQL 查询优化案例分享

在日常开发中&#xff0c;SQL 查询性能直接影响到系统的响应速度和用户体验。随着数据量的增长&#xff0c;慢查询可能成为系统的瓶颈。本文将通过实际案例&#xff0c;分享几种常见的 MySQL 查询优化方法&#xff0c;帮助开发者快速定位和优化慢查询&#xff0c;提升数据库性能…

SpringBoot 整合 Avro 与 Kafka

优质博文&#xff1a;IT-BLOG-CN 【需求】&#xff1a;生产者发送数据至 kafka 序列化使用 Avro&#xff0c;消费者通过 Avro 进行反序列化&#xff0c;并将数据通过 MyBatisPlus 存入数据库。 一、环境介绍 【1】Apache Avro 1.8&#xff1b;【2】Spring Kafka 1.2&#xf…

VScode 查看linux 内核代码

0&#xff0c;安装c.c 1&#xff0c;查看linux 目录下的linux代码&#xff0c;安装remote ssh 2&#xff0c; 输入服务器IP 3 选择服务器为linux

2025考研加油!Jing也加油哦!

一恍惚&#xff0c;离自己考研初试过去都两年了&#xff01;研究生生活也过去一大半&#xff01;借此机会也总结一下研究生这一段生活——研究生生活&#xff08;上&#xff09; About I 昨天实验室聚餐&#xff0c;作为老生欢迎新生&#xff0c;啊啊啊&#xff0c;真的没想到…

Android笔试面试题AI答之Android基础(3)

文章目录 1.谈一谈 Android 的安全机制一、系统架构层面的安全设计二、核心安全机制三、其他安全机制与措施 2.Android 的四大组件是哪四大&#xff1f;3.Android 的四大组件都需要在清单文件中注册吗&#xff1f;4.介绍几个常用的Linux命令一、文件和目录管理二、用户和权限管…

STM32-笔记7-继电器定时开闭

1、复制02项目&#xff0c;重命名08-继电器定时开闭 打开项目工程 在\Drivers\BSP\该路径下&#xff0c;新建alarm文件夹&#xff0c;该文件夹下里面包含alarm.c和alarm.h文件 加载进该项目中 为什么这里使用的是 这个单词&#xff0c;而不是继电器&#xff08;relay&#…

TypeScript 流程控制语句

文章目录 前言一、if - else 与 else - if 条件判断二、switch 语句的使用及注意事项三、for 循环&#xff08;常规、for - in、for - of&#xff09;&#xff08;一&#xff09;常规 for 循环&#xff08;二&#xff09;for - in 循环&#xff08;三&#xff09;for - of 循环…

时间轮在 Netty , Kafka 中的设计与实现

本文基于 Netty 4.1.112.Final , Kafka 3.9.0 版本进行讨论 在业务开发的场景中&#xff0c;我们经常会遇到很多定时任务的需求。比如&#xff0c;生成业务报表&#xff0c;周期性对账&#xff0c;同步数据&#xff0c;订单支付超时处理等。针对业务场景中定时任务逻辑复杂&…