教你一步步利用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使用新浪微博API发送微博的例子
Apr 10 Python
详谈python http长连接客户端
Jun 12 Python
python笔记:mysql、redis操作方法
Jun 28 Python
python 文件转成16进制数组的实例
Jul 09 Python
python实现将一维列表转换为多维列表(numpy+reshape)
Nov 29 Python
如何通过Django使用本地css/js文件
Jan 20 Python
python在不同条件下的输入与输出
Feb 13 Python
python 插入日期数据到Oracle实例
Mar 02 Python
简单了解pytest测试框架setup和tearDown
Apr 14 Python
python实现爱奇艺登陆密码RSA加密的方法示例详解
May 27 Python
Python 利用flask搭建一个共享服务器的步骤
Dec 05 Python
Pandas实现批量拆分与合并Excel的示例代码
May 30 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
ZF等常用php框架中存在的问题
2008/01/10 PHP
php+AJAX传送中文会导致乱码的问题的解决方法
2008/09/08 PHP
linux命令之调试工具strace的深入分析
2013/06/03 PHP
php使用smtp发送支持附件的邮件示例
2014/04/13 PHP
[原创]php常用字符串输出方法分析(echo,print,printf及sprintf)
2016/07/09 PHP
PHP实现Markdown文章上传到七牛图床的实例内容
2020/02/11 PHP
定时器(setTimeout/setInterval)调用带参函数失效解决方法
2013/03/26 Javascript
jquery 根据name名获取元素的value值
2015/02/27 Javascript
javascript遇到html5的一些表单属性
2015/07/05 Javascript
jQuery获取访问者IP地址的方法(基于新浪API与QQ查询接口)
2016/05/25 Javascript
js模拟微博发布消息
2017/02/23 Javascript
运用jQuery写的验证表单(实例讲解)
2017/07/06 jQuery
vue-cli如何引入bootstrap工具的方法
2017/10/19 Javascript
Vue CLI3 如何支持less的方法示例
2018/08/29 Javascript
JS/jQuery实现获取时间的方法及常用类完整示例
2019/03/07 jQuery
Jquery实现获取子元素的方法分析
2019/08/24 jQuery
vue使用map代替Aarry数组循环遍历的方法
2020/04/30 Javascript
vue3.0 项目搭建和使用流程
2021/03/04 Vue.js
[01:28:56]2014 DOTA2华西杯精英邀请赛 5 24 CIS VS DK
2014/05/26 DOTA
pymssql ntext字段调用问题解决方法
2008/12/17 Python
Python编程中对文件和存储器的读写示例
2016/01/25 Python
python操作excel的方法(xlsxwriter包的使用)
2018/06/11 Python
pycharm修改界面主题颜色的方法
2019/01/17 Python
python调用摄像头拍摄数据集
2019/06/01 Python
python3实现斐波那契数列(4种方法)
2019/07/15 Python
Python 函数用法简单示例【定义、参数、返回值、函数嵌套】
2019/09/20 Python
python 比较2张图片的相似度的方法示例
2019/12/18 Python
Python基于requests实现模拟上传文件
2020/04/21 Python
浅析PyCharm 的初始设置(知道)
2020/10/12 Python
Melissa鞋英国官方网站:Nonnon
2019/05/01 全球购物
竞职演讲稿范文
2014/01/11 职场文书
财务部绩效考核方案
2014/05/04 职场文书
基层党员群众路线教育实践活动个人对照检查材料思想汇报
2014/10/05 职场文书
大学升旗仪式主持词
2015/07/04 职场文书
Vue Mint UI mt-swipe的使用方式
2022/06/05 Vue.js
MySQL数据库之存储过程 procedure
2022/06/16 MySQL