贪吃蛇

初始版本

初始版本,只存在基本数据结构——双向队列。

游戏思路

贪吃蛇通过不断得吃食物来增长自身,如果贪吃蛇碰到边界或者自身则游戏失败。

食物是绿色矩形来模拟,坐标为随机数生成,定义一个蛇长变量,判断蛇头坐标和食物坐标是否接近,如果蛇头接近食物,蛇长增加一个单位。

蛇结构体通过双向队列实现蛇的移动和增长。用pygame相应库函数读取键盘事件,每次事件发生都对应蛇头的相应方向,例如按键盘下键贪吃蛇向下走。蛇的移动是通过在队头添加一个新的坐标,然后删掉队尾元素实现的。队列的长度始终为蛇长变量的值。

得分变量为蛇长变量减去一个单位,初始化的时候蛇长就为1个单位长度,故而需要减1。

完整代码

import pygame
import random pygame.init() # 以RGB的形式定义颜色
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213) # 设置窗体大小
dis_width = 800
dis_height = 600
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('贪吃蛇 KevenDuan1.0') # 创建clock对象
clock = pygame.time.Clock() # 蛇的宽度
snake_block = 15
# 蛇的速度
snake_speed = 15 # 从系统库里获取字体
font_style = pygame.font.SysFont("bahnschrift", 25)
score_font = pygame.font.SysFont("comicsansms", 35) def Your_score(score):
value = score_font.render("Score: " + str(score), True, yellow)
# 在主surface里添加字体surface
dis.blit(value, [0, 0]) def our_snake(snake_block, snake_list):
for x in snake_list:
pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block]) def message(msg, color):
mesg = font_style.render(msg, True, color)
dis.blit(mesg, [dis_width // 2 - 180, dis_height // 2]) def gameLoop():
game_over = False
game_close = False x1 = dis_width / 2
y1 = dis_height / 2 x1_change = 0
y1_change = 0 # 存放蛇的身体
snake_List = []
# 蛇的长度
Length_of_snake = 1 # 食物坐标随机生成
foodx = round(random.randrange(snake_block, dis_width - snake_block, snake_block))
foody = round(random.randrange(snake_block, dis_height - snake_block, snake_block))
print(foodx, foody) while not game_over:
while game_close == True:
dis.fill(blue)
message("Game over, press p again or q quit!", red)
Your_score(Length_of_snake - 1)
# 修改得分
pygame.display.update() for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
game_over = True
game_close = False
if event.key == pygame.K_p:
gameLoop() # 获取事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
x1_change = -snake_block
y1_change = 0
elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
x1_change = snake_block
y1_change = 0
elif event.key == pygame.K_UP or event.key == pygame.K_w:
y1_change = -snake_block
x1_change = 0
elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
y1_change = snake_block
x1_change = 0 if x1 >= dis_width or x1 < 0 or y1 >= dis_height or y1 < 0:
# 判断为游戏失败
game_close = True x1 += x1_change
y1 += y1_change dis.fill(blue)
pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
snake_Head = []
snake_Head.append(x1)
snake_Head.append(y1)
snake_List.append(snake_Head)
# 贪吃蛇的移动
if len(snake_List) > Length_of_snake:
del snake_List[0] # 判断是否咬到自身
for x in snake_List[:-1]:
if x == snake_Head:
game_close = True # 画蛇出来
our_snake(snake_block, snake_List)
Your_score(Length_of_snake - 1) # 更新画面
pygame.display.update() # 判断蛇是否迟到食物
if foodx - 10 <= x1 <= foodx + 10 and foody - 10 <= y1 <= foody + 10:
foodx = round(random.randrange(snake_block, dis_width - snake_block, snake_block))
foody = round(random.randrange(snake_block, dis_height - snake_block, snake_block))
# print(foodx, foody)
Length_of_snake += 1 # 调节帧率来控制蛇的速度
clock.tick(snake_speed) pygame.quit()
quit() gameLoop()

代码讲解

使用的pygamerandom两个库。Pygame是一种流行的Python游戏开发库,它提供了许多功能,使开发人员可以轻松创建2D游戏。它具有良好的跨平台支持,可以在多个操作系统上运行。random库是用来获取随机数的,后面使用其获取食物的随机坐标。

import pygame
import random

初始化一些后期用到的参数,以及初始化pygame,创建clock时钟对象。

# 初始化pygame
pygame.init()
# 以RGB的形式定义颜色
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213) # 设置窗体大小
dis_width = 800
dis_height = 600
dis = pygame.display.set_mode((dis_width, dis_height))
# 设置窗体的名称
pygame.display.set_caption('贪吃蛇 KevenDuan1.0') # 创建clock对象
clock = pygame.time.Clock() # 蛇的宽度
snake_block = 15
# 蛇的速度
snake_speed = 15 # 从系统库里获取字体
font_style = pygame.font.SysFont("bahnschrift", 25)
score_font = pygame.font.SysFont("comicsansms", 35)

定义得分函数,实际上就是在画面中添加字体。

def Your_score(score):
value = score_font.render("Score: " + str(score), True, yellow)
# 在主surface里添加字体surface
dis.blit(value, [0, 0])

定义蛇体函数,实际上就是遍历蛇身队列,依次在画面中画出矩形。

def our_snake(snake_block, snake_list):
for x in snake_list:
pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])

定义文本函数,实际上就是在画面中显示文字。

def message(msg, color):
mesg = font_style.render(msg, True, color)
dis.blit(mesg, [dis_width // 2 - 180, dis_height // 2])

两个循环结构一个判断游戏是否结束一个判断游戏是否需要退出。

    while not game_over:
while game_close == True:
dis.fill(blue)
message("Game over, press p again or q quit!", red)
Your_score(Length_of_snake - 1)
# 修改得分
pygame.display.update() for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
game_over = True
game_close = False
if event.key == pygame.K_p:
gameLoop()

获取键盘事件改变蛇头方向

# 获取事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
x1_change = -snake_block
y1_change = 0
elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
x1_change = snake_block
y1_change = 0
elif event.key == pygame.K_UP or event.key == pygame.K_w:
y1_change = -snake_block
x1_change = 0
elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
y1_change = snake_block
x1_change = 0

蛇的移动是通过在队头添加一个新的坐标,然后删掉队尾元素实现的。队列的长度始终为蛇长变量的值。

		x1 += x1_change
y1 += y1_change dis.fill(blue)
pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
snake_Head = []
snake_Head.append(x1)
snake_Head.append(y1)
snake_List.append(snake_Head)
# 贪吃蛇的移动
if len(snake_List) > Length_of_snake:
del snake_List[0] # 判断是否咬到自身
for x in snake_List[:-1]:
if x == snake_Head:
game_close = True # 画蛇出来
our_snake(snake_block, snake_List)
Your_score(Length_of_snake - 1) # 更新画面
pygame.display.update()

判断蛇头是否吃到食物,设置一定的范围,防止出现永远吃不到的bug

# 判断蛇是否吃到食物
if foodx - 10 <= x1 <= foodx + 10 and foody - 10 <= y1 <= foody + 10:
foodx = round(random.randrange(snake_block, dis_width - snake_block, snake_block))
foody = round(random.randrange(snake_block, dis_height - snake_block, snake_block))
# print(foodx, foody)
Length_of_snake += 1

增加菜单功能

通过查阅资料,发现pygame_menu提供了比较完善的游戏菜单功能。我通过pip下载后,查阅了官方样例代码,这个菜单确实是比较精美的,正是我所需要给游戏添加的东西。

import pygame
import pygame_menu pygame.init() surface = pygame.display.set_mode((600, 400)) def set_difficulty(value, difficulty):
# Do the job here !
print(1)
pass def start_the_game():
# Do the job here !
pass menu = pygame_menu.Menu('Welcome', 600, 400,
theme=pygame_menu.themes.THEME_BLUE) menu.add.text_input('Name :', default='kevenduan')
menu.add.selector('Difficulty :', [('Hard', 1), ('Easy', 2)], onchange=set_difficulty)
menu.add.button('Play', start_the_game)
menu.add.button('Quit', pygame_menu.events.EXIT)
menu.mainloop(surface)

最终版本



新功能

最终版本添加了游戏界面菜单,有查询得分记录的功能,以及可以选择两个难度。

查询分数通过列表记录后,通过排序来显示得分前5的分数。

难度的控制是由蛇的速度来控制,由于咬到自身就游戏失败有点坑,在这里删除了。

完整代码

import pygame
import random
import pygame_menu score = [0, 0, 0, 0, 0]
pygame.init()
# 以RGB的形式定义颜色
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213) # 设置窗体大小
dis_width = 800
dis_height = 600
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('Snakes KevenDuan 1.0') # 创建clock对象
clock = pygame.time.Clock() # 蛇的宽度
snake_block = 15
# 蛇的速度
snake_speed = 15 # 从系统库里获取字体
font_style = pygame.font.SysFont("bahnschrift", 25)
score_font = pygame.font.SysFont("comicsansms", 35) def Your_score(score):
value = score_font.render("Score: " + str(score), True, yellow)
# 在主surface里添加字体surface
dis.blit(value, [0, 0]) def our_snake(snake_block, snake_list):
for x in snake_list:
pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block]) def message(msg, color):
mesg = font_style.render(msg, True, color)
dis.blit(mesg, [dis_width // 2 - 150, dis_height // 2]) def gameLoop():
game_over = False
game_close = False x1 = dis_width / 2
y1 = dis_height / 2 x1_change = 0
y1_change = 0 # 存放蛇的身体
snake_List = []
# 蛇的长度
Length_of_snake = 1 # 食物坐标随机生成
foodx = round(random.randrange(snake_block, dis_width - snake_block, snake_block))
foody = round(random.randrange(snake_block, dis_height - snake_block, snake_block))
print(foodx, foody) while not game_over:
while game_close == True:
dis.fill(blue)
score.append(Length_of_snake - 1)
message(f"Game Over! your score is {Length_of_snake - 1}", red)
Your_score(Length_of_snake - 1)
# 修改得分
pygame.display.update()
pygame.time.wait(2000)
# 显示出菜单
menu.mainloop(dis) # 获取事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
x1_change = -snake_block
y1_change = 0
elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
x1_change = snake_block
y1_change = 0
elif event.key == pygame.K_UP or event.key == pygame.K_w:
y1_change = -snake_block
x1_change = 0
elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
y1_change = snake_block
x1_change = 0 if x1 >= dis_width or x1 < 0 or y1 >= dis_height or y1 < 0:
# 判断为游戏失败
game_close = True x1 += x1_change
y1 += y1_change dis.fill(blue)
pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
snake_Head = []
snake_Head.append(x1)
snake_Head.append(y1)
snake_List.append(snake_Head)
# 贪吃蛇的移动
if len(snake_List) > Length_of_snake:
del snake_List[0] # 判断是否咬到自身
# for x in snake_List[:-1]:
# if x == snake_Head:
# game_close = True # 画蛇出来
our_snake(snake_block, snake_List)
Your_score(Length_of_snake - 1) # 更新画面
pygame.display.update() # 判断蛇是否吃到食物
if foodx - 10 <= x1 <= foodx + 10 and foody - 10 <= y1 <= foody + 10:
foodx = round(random.randrange(snake_block, dis_width - snake_block, snake_block))
foody = round(random.randrange(snake_block, dis_height - snake_block, snake_block))
# print(foodx, foody)
Length_of_snake += 1 # 调节帧率来控制蛇的速度
clock.tick(snake_speed) pygame.quit()
quit() def set_difficulty(value, difficulty):
# Do the job here !
global snake_speed
if snake_speed == 15: snake_speed = 30
else: snake_speed = 15 def start_the_game():
# Do the job here !
gameLoop() def rank():
# flag = True
while True:
dis.fill(blue)
score.sort()
print(score)
mesg1 = font_style.render(f"Your highest score is {score[-1]}", True, yellow)
dis.blit(mesg1, [dis_width // 2 - 150, dis_height // 2 - 30])
mesg2 = font_style.render(f"Ranking of scores:{score[-1:-6:-1]}", True, yellow)
dis.blit(mesg2, [dis_width // 2 - 190, dis_height // 2 + 10]) pygame.display.update()
pygame.time.wait(3000)
menu.mainloop(dis)
# menu.add.button('Quit', pygame_menu.events.EXIT)
# for event in pygame.event.get():
# if event.type == pygame.QUIT:
# flag = True menu = pygame_menu.Menu('Welcome to my game', 800, 600,
theme=pygame_menu.themes.THEME_BLUE) menu.add.text_input('Author :', default='KevenDuan')
menu.add.selector('Difficulty :', [('Easy', 1), ('Hard', 2)], onchange=set_difficulty)
menu.add.button('Yours socres', rank)
menu.add.button('Play', start_the_game)
menu.add.button('Quit', pygame_menu.events.EXIT)
menu.mainloop(dis)

Python实现贪吃蛇大作战的更多相关文章

  1. Unity3D游戏贪吃蛇大作战源码休闲益智手机小游戏完整项目

    <贪吃蛇大作战>一款休闲竞技游戏,不仅比拼手速,更考验玩家的策略. 视频演示: http://player.youku.com/player.php/sid/XMzc5ODA2Njg1Ng ...

  2. 贪吃蛇大作战canvas实现(手机触屏操作)--地图逻辑

    //html部分 <!DOCTYPE html><html><head lang="en"> <meta charset="UT ...

  3. [Untiy]贪吃蛇大作战(五)——游戏主界面

    接着上一节: 4.AI蛇的设计 这里AI蛇大部分代码都可以参照主角的代码,我这里的实现其实还可以进行改进.基本原理就是蛇创建之后给蛇一个随机方向的单位向量,AI蛇的蛇头添加一个比蛇头大两三倍大小的碰撞 ...

  4. [Untiy]贪吃蛇大作战(四)——游戏主界面

    游戏主界面: 由于这个场景比较复杂,需要分几个部分实现: 1.游戏背景 首先我们的游戏场景上包括了一个大的背景图片,之外再包围一个红色的区域.中间的区域才是可活动的区域,周围通过碰撞检测盒来检测是否有 ...

  5. [Untiy]贪吃蛇大作战(三)——商店界面

    游戏商店界面: 实际的效果图如下: 要实现这个滑动,首先我们需要,一个内容显示区域,一个内容滚动区域,如下图: 其中ItemContent挂载的组件如下: 红框标注的地方是右方的滑动块. 然后Item ...

  6. [Untiy]贪吃蛇大作战(二)——规则界面

    游戏规则界面: 从界面上可以看出,一共有三个按钮,两个切换按钮和一个退出按钮. 一共三张规则图片Sprite,我们通过设置其是否为Active来控制显示,其控制脚本代码如下: using System ...

  7. [Untiy]贪吃蛇大作战(一)——开始界面

    前言: 刚学unity没多久吧(大概1个月多点),这是我自己做的除官网之外的第一个游戏demo,中间存在很多不足的地方,但是还是希望可以给需要的人提供一些思路和帮助,有问题的小伙伴可以找我一起探讨一起 ...

  8. 【python】10分钟教你用python打造贪吃蛇超详细教程

    10分钟教你用python打造贪吃蛇超详细教程 在家闲着没妹子约, 刚好最近又学了一下python,听说pygame挺好玩的.今天就在家研究一下, 弄了个贪吃蛇出来.希望大家喜欢. 先看程序效果: 0 ...

  9. 多线程的Python 教程--“贪吃蛇”

    本指南的里代码可以在这里下载:  threadworms.py ,或者从  GitHub.代码需要  Python 3 或 Python 2 ,同时也需要安装  Pygame . 点击查看大版本图片 ...

  10. 如何用python制作贪吃蛇以及AI版贪吃蛇

    用python制作普通贪吃蛇 哈喽,大家不知道是上午好还是中午好还是下午好还是晚上好! 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很 ...

随机推荐

  1. 《SQL与数据库基础》13. 视图

    目录 视图 简介 语法 检查选项 视图更新 视图作用 本文以 MySQL 为例 视图 简介 视图(View)是一种虚拟存在的表.视图中的数据并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的 ...

  2. 如何通过API接口获取淘宝的店铺所有商品详情

    在电子商务领域中,淘宝是亚洲最大的在线交易平台之一,拥有海量的商品资源和消费者.如果你是一名开发者,想要在自己的网站或者APP中嵌入淘宝商品资源,那么你就需要通过淘宝开放平台提供的API接口来获取这些 ...

  3. SQL Server实例间同步登录用户

    SQL Server实例间同步登录用户 问题痛点:由于AlwaysOn和数据库镜像无法同步数据库外实例对象,例如 登录用户.作业.链接服务器等,导致主库切换之后,应用连接不上数据库或者作业不存在导致每 ...

  4. HTML一键打包APK工具最新版1.9.2更新(附下载地址)

    HMTL网址打包APK,可以把本地HTML项目, Egret游戏,网页游戏,或者网站打包为一个安卓应用APK文件,无需编写任何代码,也无需配置安卓开发环境,支持在最新的安卓设备上安装运行. 打包软件会 ...

  5. 【RocketMQ】【源码】延迟消息实现原理

    RocketMQ设定了延迟级别可以让消息延迟消费,延迟消息会使用SCHEDULE_TOPIC_XXXX这个主题,每个延迟等级对应一个消息队列,并且与普通消息一样,会保存每个消息队列的消费进度(dela ...

  6. 记一次 .NET 某餐饮小程序 内存暴涨分析

    一:背景 1. 讲故事 前些天有位朋友找到我,说他的程序内存异常高,用 vs诊断工具 加载时间又太久,让我帮忙看一下到底咋回事,截图如下: 确实,如果dump文件超过 10G 之后,市面上那些可视化工 ...

  7. tcpdump后台不间断抓包

    版本1的抓包命令 这两天排查一个小问题,需要在服务器上使用tcpdump24小时不间断抓包,这里简单记录下. 先看下tcpdump的语法: tcpdump [ -AbdDefhHIJKlLnNOpqS ...

  8. 算法打卡|Day5 哈希表part01

    哈希表 part01 今日任务 ● 哈希表理论基础 ● 242.有效的字母异位词 ● 349. 两个数组的交集 ● 202. 快乐数 ● 1. 两数之和 目录 哈希表 part01 链表理论基础 Pr ...

  9. oracle的根容器下新建pdb容器及本地用户

    在Oracle12C根容器下,新建pdb,要求根据种子pdb建目的pdb:db_test,配置监听:在目的pdb下建本地用户 首先根据种子pdb新建目的pdb 1.管理员身份登录 C:\WINDOWS ...

  10. Go语言常用标准库——fmt

    文章目录 fmt 向外输出 Print Fprint Sprint Errorf 格式化占位符 通用占位符 布尔型 整型 浮点数与复数 字符串和[]byte 指针 宽度标识符 其他falg 获取输入 ...