教你一步步利用python实现贪吃蛇游戏


Posted in Python onJune 27, 2019

0 引言

前几天,星球有人提到贪吃蛇,一下子就勾起了我的兴趣,毕竟在那个Nokia称霸的年代,这款游戏可是经典中的经典啊!而用Python(蛇)玩Snake(贪吃蛇),那再合适不过了???

先通过下面这个效果图来感受下吧!

教你一步步利用python实现贪吃蛇游戏

1 环境

操作系统:Windows

Python版本:3.7.3

2 需求分析

我们先来回顾下贪吃蛇中的游戏元素及游戏规则。

首先呢,需要有贪吃蛇、有食物;需要能控制贪吃蛇来上下移动获取食物;贪吃蛇在吃取食物后,自身长度增加,同时食物消失并随机生成新的食物;如果贪吃蛇触碰到四周墙壁或是触碰到自己身体时,则游戏结束。

游戏规则就是这么简单,接下来我们借助一个第三方库pygame来实现它。

Pygame是一个利用SDL库的游戏库, 是一组用来开发游戏软件的 Python 程序模块。

SDL(Simple DirectMedia Layer)是一个跨平台库,支持访问计算机多媒体硬件(声音、视频、输入等),SDL非常强大,但美中不足的是它是基于 C 语言的。

PyGame是 SDL 库的 Python 包装器(wrapper),Pygame 在SDL库的基础上提供了各种接口,从而使用用户能够使用python语言创建各种各样的游戏或多媒体程序。

它的安装方法很简单,如下:

pip install pygame

想要了解更多pygame功能的朋友也可以查阅官方的文档。

3 代码实现

首先导入我们要用到的模块,除了第三方库pygame外,我们还会用到一些Python内置的模块如sys、random、time等,一并导入即可。

import pygame, sys, random, time
# 从pygame模块导入常用的函数和常量
from pygame.locals import *

3.1 一些全局参数的初始化

接下来,我们需要声明一些全局参数。如初始化pygame、定义游戏窗口的大小、窗口的标题、定义全局的颜色变量等信息。

# 初始化Pygame库
pygame.init()
# 初始化一个游戏界面窗口
DISPLAY = pygame.display.set_mode((640, 480))
# 设置游戏窗口的标题
pygame.display.set_caption('人人都是Pythonista - Snake')
# 定义一个变量来控制游戏速度
FPSCLOCK = pygame.time.Clock()
# 初始化游戏界面内使用的字体
BASICFONT = pygame.font.SysFont("SIMYOU.TTF", 80)

# 定义颜色变量
BLACK = pygame.Color(0, 0, 0)
WHITE = pygame.Color(255, 255, 255)
RED = pygame.Color(255, 0, 0)
GREY = pygame.Color(150, 150, 150)

3.2 初始化贪吃蛇及食物

游戏中需要有贪吃蛇及食物,我们给定一个初始值。我们将整个界面看成许多20*20的小方块,每个小方块代表一个标准小格子,贪吃蛇的长度就可以用几个标准小格子表示。我们将贪吃蛇身体用列表的形式存储,方便之后的删减。
'''初始化贪吃蛇及食物'''

# 贪吃蛇的的初始位置
snake_Head = [100,100]
# 初始化贪吃蛇的长度 (注:这里以20*20为一个标准小格子)
snake_Body = [[80,100],[60,100],[40,100]]
# 指定蛇初始前进的方向,向右
direction = "right"

# 给定第一枚食物的位置
food_Position = [300,300]
# 食物标记:0代表食物已被吃掉;1代表未被吃掉。
food_flag = 1

3.3 实现贪吃蛇的上下左右移动

我们需要控制贪吃蛇的上下左右的移动,这里通过监听键盘输入来实现。利用键盘中的上下左右键或WASD键来控制贪吃蛇的运动。

# 检测按键等Pygame事件
for event in pygame.event.get():
  if event.type == QUIT:
    # 接收到退出事件后,退出程序
    pygame.quit()
    sys.exit()
    
  # 判断键盘事件,用 方向键 或 wsad 来表示上下左右
  elif event.type == KEYDOWN:
    if (event.key == K_UP or event.key == K_w) and direction != DOWN:
      direction = UP
    if (event.key == K_DOWN or event.key == K_s) and direction != UP:
      direction = DOWN
    if (event.key == K_LEFT or event.key == K_a) and direction != RIGHT:
      direction = LEFT
    if (event.key == K_RIGHT or event.key == K_d) and direction != LEFT:
      direction = RIGHT

接下来就是将蛇前进方向按照键盘的输入进行转弯操作,并将蛇的头部当前的位置加入到蛇身的列表中。

# 根据键盘的输入,改变蛇的头部,进行转弯操作
if direction == LEFT:
  snake_Head[0] -= 20
if direction == RIGHT:
  snake_Head[0] += 20
if direction == UP:
  snake_Head[1] -= 20
if direction == DOWN:
  snake_Head[1] += 20

# 将蛇的头部当前的位置加入到蛇身的列表中
snake_Body.insert(0, list(snake_Head))

3.4 判断是否吃到食物

如果蛇头与食物的位置重合,则判定吃到食物,将食物数量清零;而没吃到食物的话,蛇身就会跟着蛇头运动,蛇身的最后一节将被踢出列表。

# 判断是否吃掉食物
if snake_Head[0]==food_Position[0] and snake_Head[1]==food_Position[1]:
  food_flag = 0
else:
  snake_Body.pop()

3.5 重新生成食物

当游戏界面中的食物数量为0时,需要重新生成食物。利用random函数来生成随机位置

# 生成新的食物
if food_flag == 0:
  # 随机生成x, y
  x = random.randrange(1,32)
  y = random.randrange(1,24)
  food_Position = [int(x*20),int(y*20)]
  food_flag = 1

3.6 绘制贪吃蛇、食物、分数等信息

定义贪吃蛇的绘制函数

# 绘制贪吃蛇
def drawSnake(snake_Body):
  for i in snake_Body:
    pygame.draw.rect(DISPLAY, WHITE, Rect(i[0], i[1], 20, 20))

定义食物的绘制函数
# 绘制食物的位置
def drawFood(food_Position):
  pygame.draw.rect(DISPLAY, RED, Rect(food_Position[0], food_Position[1], 20, 20))

定义分数的绘制函数
# 打印出当前得分
def drawScore(score):
  # 设置分数的显示颜色
  score_Surf = BASICFONT.render('%s' %(score), True, GREY)
  # 设置分数的位置
  score_Rect = score_Surf.get_rect()
  score_Rect.midtop = (320, 240)
  # 绑定以上设置到句柄
  DISPLAY.blit(score_Surf, score_Rect)

这些都定义好之后,我们需要在游戏主逻辑中调用它们,并刷新Pygame的显示层,贪吃蛇与食物的每一次移动,都会进行刷新显示层的操作来显示。最后我们可以设定一个速度值来合理控制游戏执行的速度。

DISPLAY.fill(BLACK)
# 画出贪吃蛇
drawSnake(snake_Body)
# 画出食物的位置
drawFood(food_Position)
# 打印出玩家的分数
drawScore(len(snake_Body) - 3)
# 刷新Pygame的显示层,贪吃蛇与食物的每一次移动,都会进行刷新显示层的操作来显示。
pygame.display.flip()
# 控制游戏速度
FPSCLOCK.tick(7)

3.7 定义游戏结束的画面并判断游戏是否结束

定义函数,用于展示游戏结束的画面并退出程序

# 游戏结束并退出
def GameOver():
  # 设置GameOver的显示颜色
  GameOver_Surf = BASICFONT.render('Game Over!', True, GREY)
  # 设置GameOver的位置
  GameOver_Rect = GameOver_Surf.get_rect()
  GameOver_Rect.midtop = (320, 10)
  # 绑定以上设置到句柄
  DISPLAY.blit(GameOver_Surf, GameOver_Rect)

  pygame.display.flip()
  # 等待3秒
  time.sleep(3)
  # 退出游戏
  pygame.quit()
  # 退出程序
  sys.exit()

在游戏主逻辑中加入判断,游戏是否结束

'''游戏结束的判断'''
# 贪吃蛇触碰到边界
if snake_Head[0]<0 or snake_Head[0]>620:
  GameOver()
if snake_Head[1]<0 or snake_Head[1]>460:
  GameOver()
# 贪吃蛇触碰到自己
for i in snake_Body[1:]:
  if snake_Head[0]==i[0] and snake_Head[1]==i[1]:
    GameOver()

4 后记

本文利用Pygame模块实现了最简单的贪吃蛇版本。当然还有很多需要优化的地方,比如随机生成食物时如何避免出现在贪吃蛇的自身上、通过贪吃蛇的长度来自动控制游戏速度等等。更高级一点的有如何通过AI自动玩贪吃蛇、贪吃蛇的双人对战等,期待大家利用Python可以把贪吃蛇玩出一个新的高度!???

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
浅谈Python中数据解析
May 05 Python
使用python实现接口的方法
Jul 07 Python
如何在python中使用selenium的示例
Dec 26 Python
3个用于数据科学的顶级Python库
Sep 29 Python
python下PyGame的下载与安装过程及遇到问题
Aug 04 Python
Python将主机名转换为IP地址的方法
Aug 14 Python
pygame库实现移动底座弹球小游戏
Apr 14 Python
python 视频逐帧保存为图片的完整实例
Dec 10 Python
Python实现钉钉订阅消息功能
Jan 14 Python
django 扩展user用户字段inlines方式
Mar 30 Python
Python3通过chmod修改目录或文件权限的方法示例
Jun 08 Python
python 逆向爬虫正确调用 JAR 加密逻辑
Jan 12 Python
Python中遍历列表的方法总结
Jun 27 #Python
Python 把序列转换为元组的函数tuple方法
Jun 27 #Python
Python使用numpy模块实现矩阵和列表的连接操作方法
Jun 26 #Python
Python 实现交换矩阵的行示例
Jun 26 #Python
对numpy下的轴交换transpose和swapaxes的示例解读
Jun 26 #Python
Python用Try语句捕获异常的实例方法
Jun 26 #Python
python调用自定义函数的实例操作
Jun 26 #Python
You might like
PHP实现利用MySQL保存session的方法
2014/08/23 PHP
老生常谈PHP 文件写入和读取(必看篇)
2017/05/22 PHP
Laravel框架集成UEditor编辑器的方法图文与实例详解
2019/04/17 PHP
jQuery的强大选择器小结
2009/12/27 Javascript
jquery 的 $(&quot;#id&quot;).html() 无内容的解决方法
2010/06/07 Javascript
javascript 进阶篇1 正则表达式,cookie管理,userData
2012/03/14 Javascript
js获取内联样式的方法
2015/01/27 Javascript
深入浅出 jQuery中的事件机制
2016/08/23 Javascript
微信小程序 wx.request(OBJECT)发起请求详解
2016/10/13 Javascript
jquery+Jscex打造游戏力度条
2020/09/12 Javascript
JavaScript实现使用Canvas绘制图形的基本教程
2016/10/27 Javascript
jQuery-mobile事件监听与用法详解
2016/11/23 Javascript
jQuery读取XML文件的方法示例
2017/02/03 Javascript
JavaScript中transform实现数字翻页效果
2017/03/08 Javascript
layui 点击重置按钮, select 并没有被重置的解决方法
2019/09/03 Javascript
vue实现文件上传读取及下载功能
2020/11/17 Javascript
node.js中 redis 的安装和基本操作示例
2020/02/10 Javascript
javascript设计模式 ? 命令模式原理与用法实例分析
2020/04/20 Javascript
vue中父子组件传值,解决钩子函数mounted只运行一次的操作
2020/07/27 Javascript
Python实现简单遗传算法(SGA)
2018/01/29 Python
对python中的高效迭代器函数详解
2018/10/18 Python
Python 中 function(#) (X)格式 和 (#)在Python3.*中的注意事项
2018/11/30 Python
Python+AutoIt实现界面工具开发过程详解
2019/08/07 Python
基于PyQT实现区分左键双击和单击
2020/05/19 Python
python3.8.1+selenium实现登录滑块验证功能
2020/05/22 Python
python opencv肤色检测的实现示例
2020/12/21 Python
shallow copy和deep copy的区别
2016/05/09 面试题
介绍一下你对SOA的认识
2016/04/24 面试题
会计专业大学生职业生涯规划书
2014/02/11 职场文书
社区巾帼文明岗事迹材料
2014/06/03 职场文书
“四风”查摆问题自我剖析材料
2014/09/27 职场文书
辩护词范文大全
2015/05/21 职场文书
python如何正确使用yield
2021/05/21 Python
PHP中多字节字符串操作实例详解
2021/08/23 PHP
php png失真的原因及解决办法
2021/10/24 PHP
Python实现提取PDF简历信息并存入Excel
2022/04/02 Python