教你一步步利用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使用matplotlib实现绘制自定义图形功能示例
Jan 18 Python
手把手教你用python抢票回家过年(代码简单)
Jan 21 Python
python判断计算机是否有网络连接的实例
Dec 15 Python
详解用pyecharts Geo实现动态数据热力图城市找不到问题解决
Jun 26 Python
wxPython之wx.DC绘制形状
Nov 19 Python
python opencv 图像边框(填充)添加及图像混合的实现方法(末尾实现类似幻灯片渐变的效果)
Mar 09 Python
python中pathlib模块的基本用法与总结
Aug 17 Python
python Matplotlib数据可视化(1):简单入门
Sep 30 Python
Python 实现3种回归模型(Linear Regression,Lasso,Ridge)的示例
Oct 15 Python
使用python-cv2实现视频的分解与合成的示例代码
Oct 26 Python
python 读取串口数据的示例
Nov 09 Python
用python基于appium模块开发一个自动收取能量的小助手
Sep 25 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
一个高ai的分页函数和一个url函数
2006/10/09 PHP
深入解析yii权限分级式访问控制的实现(非RBAC法)
2013/06/13 PHP
PHP框架性能测试报告
2016/05/08 PHP
PHP赋值的内部是如何跑的详解
2019/01/13 PHP
PHP使用Http Post请求发送Json对象数据代码解析
2020/07/16 PHP
用javascript操作xml
2006/11/04 Javascript
JavaScript DOM 学习第三章 内容表格
2010/02/19 Javascript
JQuery Dialog的内存泄露问题解决方法
2010/06/18 Javascript
浅谈tudou土豆网首页图片延迟加载的效果
2010/06/23 Javascript
javascript面向对象包装类Class封装类库剖析
2013/01/24 Javascript
json中换行符的处理方法示例介绍
2014/06/10 Javascript
jQuery中的height innerHeight outerHeight区别示例介绍
2014/06/15 Javascript
基于JavaScript操作DOM常用的API小结
2015/12/01 Javascript
如何利用AngularJS打造一款简单Web应用
2015/12/05 Javascript
Jquery和angularjs获取check框选中的值的方法汇总
2016/01/17 Javascript
AngularJS基础 ng-init 指令简单示例
2016/08/02 Javascript
HTML Table 空白单元格补全的简单实现
2016/10/13 Javascript
详谈$.data()的用法和作用
2017/02/13 Javascript
angularjs实现下拉列表的选中事件示例
2017/03/03 Javascript
Vue.js实现网格列表布局转换方法
2017/08/25 Javascript
简述JS控制台的使用
2018/07/15 Javascript
node.js环境搭建图文详解
2018/09/19 Javascript
JavaScript实现tab栏切换效果
2020/03/16 Javascript
[01:03:56]Mineski vs TNC 2018国际邀请赛淘汰赛BO1 8.21
2018/08/22 DOTA
使用Python中的cookielib模拟登录网站
2015/04/09 Python
Java及python正则表达式详解
2017/12/27 Python
python rsa实现数据加密和解密、签名加密和验签功能
2019/09/18 Python
python使用pip安装模块出现ReadTimeoutError: HTTPSConnectionPool的解决方法
2019/10/04 Python
Python 网络编程之TCP客户端/服务端功能示例【基于socket套接字】
2019/10/12 Python
Python json解析库jsonpath原理及使用示例
2020/11/25 Python
通用自荐信范文
2014/03/14 职场文书
贷款委托书怎么写
2014/08/02 职场文书
2014年中秋寄语
2014/08/11 职场文书
2014学习十八届四中全会精神思想汇报范文
2014/10/23 职场文书
Win11 Build 22000.51版本文件资源管理器“命令栏”和上下文菜单有什么新变化?
2021/11/21 数码科技
Python IO文件管理的具体使用
2022/03/20 Python