Python实战练习_贪吃蛇 (pygame的初次使用)
正如标题所写的那样,我将一步步的完成本次实战练习——贪吃蛇。废话不多说,感兴趣的伙伴可以一同挑战一下。
首先说明本次实战中我的配备:
开发环境:python 3.7;
开发工具:pycharm2019.2.2;
开发模块:pygame;
首先在本次开发中,我们要借用一下pygame模块,那么问题来了,什么是pygame模块?有什么用?
pygame 是包含图像、声音建立在SDL基础上,允许实时电子游戏研发而无需被低级语言(如机器语言和汇编语言)束缚。
基于这样一个设想,所有需要的游戏功能和理念都(主要是图像方面)都完全简化为游戏逻辑本身,所有的资源结构都可以由高级语言提供,如Python。
我个人理解 pygame是一个简化2d游戏开发的开发模块。
本次开发的第一步便是装载pygame,具体方法如下
1.通过在python文件中 打开命令提示 输入对应代码
2.pycharm软件 可以通过设置内,添加新模块
确保安装完成可以在命令提示符中打开python 输入 import pygame检测 如下所示
有需要的话,可以通过留言,我在下一期博客中专门做一个pygame安装教程。
接下来便是我们的开发之旅:
首先展示一下我们的效果图,由一个个大小为20*20的方块儿组成的贪吃蛇游戏
1.调用python开发环境,包括pygame、sys、random。
# python 运行时的环境
import pygame, sys, random
2.调用pygame相关常量、还有配置颜色。
# 这个模块包含所有pygame所使用的常量
from pygame.locals import *
# 定义颜色变量
# 目标方块儿红颜色
redColor = pygame.Color(, , )
# 背景颜色为黑色
blackColor = pygame.Color(, , )
# 蛇颜色为白色
whiteColor = pygame.Color(, , )
3.定义游戏结束的函数 主要包含两部分操作,第一部分为pygame结束,第二部分为sys结束。
# 定义游戏结束
def gameOver():
pygame.quit()
sys.exit()
4.有了前面的铺垫,我们可以正式开始设计我们的游戏,我将游戏内容存放到main函数中。
4.1初始化pygame,设定变量来控制蛇的速度,然后制作一个界面,界面的大小为640*480,界面标题为贪吃蛇。
其中界面大小是必须设定的,贪吃蛇游戏的规则之一便是不能触及边界,但界面的标题是可以不写的,界面标题默认为python文件名
特别注意pygame.display.set_mode()函数中需要插入为两项序列而不是整数型 所以参数应为(640, 480)
具体代码如下
def main():
# 初始化pygame
pygame.init()
# 定义一个变量 控制速度
fpsClock = pygame.time.Clock()
# 创建一个窗口界面,界面大小为640*480
playSurface = pygame.display.set_mode((, ))
# 界面标题为“贪吃蛇” 可不写,默认为python文件名
pygame.display.set_caption('贪吃蛇')
4.2设定目标方块
目标方块是由计算机随机生成的,但在那之前需要我们手动设定一个初值,同时设定一个target_flag来判断目标方块是否被贪吃蛇 “吃” 掉
# 初始化目标方块的位置
targetPosition = [, ]
# 目标方块标记 判断贪吃蛇是否吃掉目标方块 1为没吃掉 0为吃掉
targetFlag =
4.3设定贪吃蛇的相关属性
初始化蛇需要注意什么?首先蛇的位置,其次蛇的长度,最后便是蛇的方向。那么一步步来实现
我们可以将蛇看做两部分组成组成,蛇头和蛇身。蛇身只要不断跟随蛇头便可,蛇头需要用来判断贪吃蛇的前进方向、是否结束游戏、是否 “吃” 掉目标方块儿等等
我们设定蛇头以(100, 100)为基准,蛇为水平方向放置,并且向右前进,所以蛇身的第一部分 应等于蛇头的’“Y”值,而“X”应当减去一个方块儿的位置,也就是减少20,贪吃蛇第一块应当是(80, 100)
设定存在方向的变量direction,初始方向向右,也需要设定改变方向的变量changedirection,令changedirection == direction
所写代码如下
# 初始化贪吃蛇的位置 (,)为基准
# 初始化贪吃蛇长度 列表中有几个元素 就有几个身体
snake_head = [, ]
snake_body = [[, ], [, ]] # 初始化方向 默认为右
direction = 'right'
# 定义一个认为控制的方向的变量
changedirection = direction
4.4需要贪吃蛇动起来
特别说明 pygame的所有事件全都在一个实时循环中
由于操作比较简单,鼠标操作的便只有一个,点击右上角的叉叉关闭游戏,但键盘上的操作相对比较多 包括↑↓←→,控制蛇的移动,esc退出游戏
所以首先要判断发生的事件类型是点击QUIT ,又或者是KEYDOWN
QUIT不必说,游戏结束之前上面也有描述 pygame.quit() 与sys.exit()
KEYDOWN 就需要判断是上下左右的哪一个,发生按键要使得蛇的移动方向发生改变,所以changedirection 需要发生变动,更改为按键方向。
# pygame 所有事件全部放到一个实时循环中
while True:
# 从队列中获取事件
for event in pygame.event.get(): if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_RIGHT:
changedirection = 'right'
if event.key == K_LEFT:
changedirection = 'left'
if event.key == K_UP:
changedirection = 'up'
if event.key == K_DOWN:
changedirection = 'down'
if event.key == K_ESCAPE:
pygame.event.post(pygame.event.Event(QUIT))
蛇的移动方向由direction决定,按键改变的是changedirection,所以我们需要将changedirection的值赋予direction
众所周知,贪吃蛇是不可以走回头路的,也就是说当贪吃蛇向右移动,按左键是没哟效果的
所以在将changedirection的值赋予direction 之前 还需要判断两个值是否相反
# 确定方向
if changedirection == 'left' and not direction == 'right':
direction = changedirection
if changedirection == 'right' and not direction == 'left':
direction = changedirection
if changedirection == 'up' and not direction == 'down':
direction = changedirection
if changedirection == 'down' and not direction == 'up':
direction = changedirection
4.5贪吃蛇转弯
就像上文提到的那样,蛇身是跟着蛇头运动,所以转弯实际上是改变蛇头的位置。
将蛇身与蛇头分开来写相对来说这时候比较占优势,只要改变蛇头snake_head的位置信息就可以。
并不是说蛇头和蛇身必须分开写,也可以放在一起,我们只需要多写一步 提取蛇的第一个方块信息就可以了
那么问题来了,怎么改变蛇头位置信息才能达到转弯的效果?
我们以蛇在向右移动,这时按↓键为例
蛇头这时候应当向下移动一个方块的位置,也就是说这时候蛇头的“X”不发生改变,“Y”值增加一个方块的数值,也就是20
同理可得蛇头向上等操作的方法,注意snake_head是一个数组 ,snake_head[0]即为“X” snake_head[1]即为“Y”
代码如下
# 根据方向移动蛇头
if direction == 'right':
snake_head[] +=
if direction == 'left':
snake_head[] -=
if direction == 'up':
snake_head[] -=
if direction == 'down':
snake_head[] +=
4.5贪吃蛇吃方块
贪吃蛇游戏的目的便是控制贪吃蛇“吃”掉方块儿,那么怎样来实现呢?
首先蛇的嘴巴长在蛇头上,所以蛇吃掉方块需要用到蛇头的位置信息。
其次目标方块儿存放在指定位置,所以当蛇头的位置信息等于目标方块儿的位置信息即可
位置信息包含x与y,所以当蛇头x=目标方块儿x,并且蛇头y=目标方块儿y时,我们便认定贪吃蛇吃了方块
之前设定判断目标方块的状态变量 targetflag便起到作用,1表示没吃,0表示吃了,所以targetflag从1变成了0
# 如果贪吃蛇位置和目标方块位置重合
if snake_head[] == targetPosition[] and
snake_head[] == targetPosition[]: targetFlag = else:
snake_body.pop()
4.6重新生成新的目标方块
当判断目标方块儿被吃了,也就是说targetflag=0时,系统需要重新生成一个新的目标方块。
目标方块的设定相对来说比较简单,只需要生成一个新的位置信息并将targetflag=1即可。
目标方块将会出现在一个随机的位置,所以我们在这里需要引入一个随机数,这也是为什么刚开始开发游戏时,需要import random
由于一个方块的大小为20*20,游戏界面为640*480,所以x的取值范围只有(20/20, 640/20)即为(1, 32)
同理可得y的取值范围应当是(1,24) 所以随机生成的目标方块儿位置信息应当为(x*20, y*20)
输入的位置信息应当为整数类型,所以还需要加强转,代码如下
if targetFlag == :
x = random.randrange(, )
y = random.randrange(, )
targetPosition = [int(x * ), int(y * )]
targetFlag =
5.界面生成
写到这里,游戏的规则基本完成,接下来我们需要“画”出我们的界面
首先给自己的游戏界面填充为黑色,借用playSurface.fill()函数,将黑色的参数传入
之后就是画我们的贪吃蛇,用for循环画每一部分的身子,利用pygame中draw所带的Rect函数来绘画方块 rect函数需要传四个参数
第一个为surface,需要制定一个surface编辑区域
第二个为color,即绘画的颜色,这个很好理解
第三个为rect,rect为绘画矩形,需要提供矩形的位置,长度,宽度
第四个为width,这并不代表宽度,而是特指线条的粗细, width=0实心,width=1空心 ,一般可以不传入,默认为0
然后便是画目标方块,原理如上所示,但不需要用到for循环,毕竟就一个目标方块儿
最后开启实时更新界面
# 填充背景颜色
playSurface.fill(blackColor) for position in snake_body:
# rect函数内
# 第一个参数surface 指定一个surface编辑区
# 第二个参数color 指定颜色
# 第三个参数rect 返回一个矩形包含位置信息(x,y),(width,height)
# 第四个参数width 表示线条的粗细 width= 实心 width= 空心
# 画蛇
pygame.draw.rect(playSurface, whiteColor, Rect(position[], position[], , ))
# 画目标方块儿
pygame.draw.rect(playSurface, redColor, Rect(targetPosition[], targetPosition[], , )) # 更新显示到屏幕
pygame.display.flip()
6.游戏结束条件
当贪吃蛇撞击到边界时便会触发游戏结束,也就是蛇头的位置超过了预定的640*480的界面,这时候游戏结束
# 判断游戏结束
if snake_head[] > or snake_head[] < :
gameOver()
if snake_head[] > or snake_head[] < :
gameOver()
7.调控难度
调控难度主要是更改贪吃蛇的速度,之前有设定贪吃蛇速度的变量,这时候我们只要加以修改即可,个人比较手残,开三挡即可,有兴趣的小伙伴可以尝试下更高的难度
# 控制游戏速度
fpsClock.tick()
8.开启游戏,启动main函数
# 启动入口 main函数
if __name__ == '__main__':
main()
至此就开发完成了一个简单的像素贪吃蛇,下面便是游戏最终效果
由于种种原因,最后有些地方没来得及改进,所以也算给诸位留下一些难题。
过段时间我会重新更新更加完善、更加丰富的贪吃蛇项目
改进方案:
1.可以加入分数体系,在每次吃到目标方块儿后分数加一,最终在结束后呈现给玩家
2.贪吃蛇游戏结束条件:蛇头碰到自己身体,游戏结束未实现
3.界面过于简单,可以制作一个简单的游戏开始界面,或者在游戏结束后创建一个排名榜,重来一次等
4.部分代码跨度较大 显得冗长,建议精简重新构建框架
最后显示源代码,以供各位参考
# python 运行时的环境
import pygame, sys, random # 这个模块包含所有pygame所使用的常量
from pygame.locals import * # 定义颜色变量 # 目标方块儿红颜色
redColor = pygame.Color(, , )
# 背景颜色为黑色
blackColor = pygame.Color(, , )
# 蛇颜色为白色
whiteColor = pygame.Color(, , ) # 定义游戏结束
def gameOver():
pygame.quit()
sys.exit() # 定义main函数 定义入口函数
def main():
# 初始化pygame
pygame.init()
# 定义一个变量 控制速度
fpsClock = pygame.time.Clock()
# 创建一个窗口界面
playSurface = pygame.display.set_mode((, ))
pygame.display.set_caption('贪吃蛇') # 初始化目标方块的位置
targetPosition = [, ]
# 目标方块标记 判断贪吃蛇是否吃掉目标方块 1为没吃掉 0为吃掉
targetFlag = # 初始化贪吃蛇的位置 (,)为基准
# 初始化贪吃蛇长度 列表中有几个元素 就有几个身体
snake_head = [, ]
snake_body = [[, ], [, ]] # 初始化方向 默认为右
direction = 'right'
# 定义一个认为控制的方向的变量
changedirection = direction # pygame 所有事件全部放到一个实时循环中
while True:
# 从队列中获取事件
for event in pygame.event.get(): if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_RIGHT:
changedirection = 'right'
if event.key == K_LEFT:
changedirection = 'left'
if event.key == K_UP:
changedirection = 'up'
if event.key == K_DOWN:
changedirection = 'down'
if event.key == K_ESCAPE:
pygame.event.post(pygame.event.Event(QUIT))
# 确定方向
if changedirection == 'left' and not direction == 'right':
direction = changedirection
if changedirection == 'right' and not direction == 'left':
direction = changedirection
if changedirection == 'up' and not direction == 'down':
direction = changedirection
if changedirection == 'down' and not direction == 'up':
direction = changedirection # 根据方向移动蛇头
if direction == 'right':
snake_head[] +=
if direction == 'left':
snake_head[] -=
if direction == 'up':
snake_head[] -=
if direction == 'down':
snake_head[] += # 增加蛇的长度
snake_body.insert(, list(snake_head)) # 如果贪吃蛇位置和目标方块位置重合
if snake_head[] == targetPosition[] and snake_head[] == targetPosition[]:
targetFlag = else:
snake_body.pop() if targetFlag == :
x = random.randrange(, )
y = random.randrange(, )
targetPosition = [int(x * ), int(y * )]
targetFlag = # 填充背景颜色
playSurface.fill(blackColor) for position in snake_body:
# rect函数内
# 第一个参数surface 指定一个surface编辑区
# 第二个参数color 指定颜色
# 第三个参数rect 返回一个矩形包含位置信息(x,y),(width,height)
# 第四个参数width 表示线条的粗细 width= 实心 width= 空心
# 画蛇
pygame.draw.rect(playSurface, whiteColor, Rect(position[], position[], , ))
# 画目标方块儿
pygame.draw.rect(playSurface, redColor, Rect(targetPosition[], targetPosition[], , )) # 更新显示到屏幕
pygame.display.flip() # 判断游戏结束
if snake_head[] > or snake_head[] < :
gameOver()
if snake_head[] > or snake_head[] < :
gameOver()
# 控制游戏速度
fpsClock.tick() # 启动入口 main函数
if __name__ == '__main__':
main()
Python实战练习_贪吃蛇 (pygame的初次使用)的更多相关文章
- Python:游戏:贪吃蛇原理及代码实现
一.游戏介绍 贪吃蛇是个非常简单的游戏,适合练手.先来看一下我的游戏截图: 玩法介绍:回车键:开始游戏空格键:暂停 / 继续↑↓←→方向键 或 WSAD 键:控制移动方向. 食物分红.绿.蓝三种,分别 ...
- 原生JS实战:经典贪吃蛇(开局10倍速度,来看看你最高能得多少分!)
本文是苏福的原创文章,转载请注明出处:苏福CNblog:http://www.cnblogs.com/susufufu/p/5875523.html 该程序是本人的个人作品,写的不好,未经本人允许,请 ...
- [原创]html5游戏_贪吃蛇
代码随便写写,尚有许多不足,PC与手机端皆可运行 手机端滑屏操作,PC端方向键操作 疑问: 生成食物,与判断是否可以移动方面 有两种实现方式, 1.使用js内存,数组循环判断 2.使用dom的quer ...
- python版本的简单贪吃蛇
先看看效果,白色的条是蛇(简单勿怪,有研究的同学请告知做的美观点),做了一个笑脸是糖果,背景弄了一个图, 代码也是从其他人那边弄来的,改了一部分直接可以在window上直接运行 代码如下: #codi ...
- python小游戏之贪吃蛇
本程序需要安装pygame,请自行百度安装...... 废话不多说,直接上代码 import pygame,sys,time,random from pygame.locals import * # ...
- 如何用python制作贪吃蛇以及AI版贪吃蛇
用python制作普通贪吃蛇 哈喽,大家不知道是上午好还是中午好还是下午好还是晚上好! 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很 ...
- [C语言]贪吃蛇_结构数组实现
一.设计思路 蛇身本质上就是个结构数组,数组里存储了坐标x.y的值,再通过一个循环把它打印出来,蛇的移动则是不断地刷新重新打印.所以撞墙.咬到自己只是数组x.y值的简单比较. 二.用上的知识点 结构数 ...
- 用python+pygame写贪吃蛇小游戏
因为python语法简单好上手,前两天在想能不能用python写个小游戏出来,就上网搜了一下发现了pygame这个写2D游戏的库.了解了两天再参考了一些资料就开始写贪吃蛇这个小游戏. 毕竟最开始的练手 ...
- 程序游戏推荐(C语言贪吃蛇,python天天酷跑(需要安装pygame),js是狠人就坚持30s)
下面是下载位置,我把他们上传到我的文件下了. C语言贪吃蛇:https://files.cnblogs.com/files/ITXiaoAng/%E8%B4%AA%E5%90%83%E8%9B%87. ...
随机推荐
- unity shader 纹理&透明效果
1.纹理映射基础 (1)纹理映射通过(u,v)坐标实现.注意:这句话时博主当时面试一家外企被问到的问题. (2)添加纹理属性:——MainTex("Main Tex",2D)=&q ...
- 域渗透-LSA Protection
简介: 微软在 2014 年 3 月 12 日添加了 LSA 保护策略,用来防止对进程 lsass.exe 的代码注入,这样一来就无法使用 mimikatz 对 lsass.exe 进行注入,相关操作 ...
- 信道估计系列之LS
在无线通信系统中,系统的性能主要受到无线信道的制约.基站和接收机之间的传播路径复杂多变,从简单的视距传输到受障碍物反射.折射.散射影响的传播.在无线传输环境中,接收信号会存在多径时延,时间选择性衰落和 ...
- Delphi - StringReplace用法
StringReplace用法 在开发过程中,有时候我们需要对字符串进行替换操作,屏蔽或者和谐某些字符,可使用Delphi自带的函数StringReplace函数. 通过代码进行说明: //函数原型 ...
- js 快速排序算法
Array.prototype.quickSort = function() { var len = this.length; if(len < 2) return this; var left ...
- tabBar的内部控件
大体来说tabBar的内部其实除了UITabBarButton还有两个UIImageView 1.两个UIImageView是我们访问不到的,_UITabBarBackgroundView继承自UII ...
- 微服务时代之网关相关技术选型及部署(nacos+gateway)
1.场景描述 因要用到微服务,关于注册中心这块,与同事在技术原型上做了讨论,初步定的方案是使用:阿里巴巴的nacos+springcloud gateway,下面表格是同事整理的注册中心对比,以前用的 ...
- 【故障公告】再次出现数据库 CPU 居高不下的问题以及找到问题的线索
非常非常抱歉,今天上午的故障又一次给大家带来麻烦了,再次恳请大家的谅解. 在昨天升级阿里云 RDS SQL Server 实例的配置后(详见昨天的博文),万万没有想到,今天上午更高配置的阿里云 RDS ...
- Codeforces Round #486 (Div. 3)988D. Points and Powers of Two
传送门:http://codeforces.com/contest/988/problem/D 题意: 在一堆数字中,找出尽量多的数字,使得这些数字的差都是2的指数次. 思路: 可以知道最多有三个,差 ...
- 牛客OI测试赛 C 序列 思维
链接:https://www.nowcoder.com/acm/contest/181/C来源:牛客网 题目描述 小a有n个数,他想把他们划分为连续的权值相等的k段,但他不知道这是否可行. 每个数都必 ...