贪吃蛇小游戏Python Pygame实现

news/2024/10/5 10:20:00

运行结果

 

游戏规则

1. ↑ ↓ ← → 来控制蛇的移动方向

2. 蛇吃到自己身体的任意一部分游戏结束, 自动退出窗口

3. 蛇的速度会随游戏时间增长越来越快, 与吃食物的多少 (分数) 无关

4. 蛇可以穿过边界到达另一边

5. 场上食物同时只会存在一个, 颜色随机, 但每个颜色的所得分数不同, 生存概率也不同

 

实现思路

此段介绍代码逻辑, 比较简单, 可以直接跳过, 最后有全部代码

 

1. 棋盘实现

棋盘采用最简单的方法来实现, 即一个grid[][]二元列表来表示棋盘, 下标表示棋盘的位置

例如: grid[5][4]表示第5行第4列的一格

  1) None表示该一格为空, 即蛇可以安全通过

  2) 颜色例如(0, 0, 0)为该一格有食物

  3) True表示该一格是蛇的身体

 

SIZE = 30
SIDE = HEIGHT // SIZE
grid = [[None for _ in range(SIDE)] for _ in range(SIDE)]

 

 

2. 蛇的实现

用双端队列表示蛇, 这样尾部和头部的更新时间复杂度都为O(1).

蛇初始长度为3, 方向向右

1). 蛇的动态实现

  根据蛇的前进速度, 每前进一格, 若没有吃到食物, 则删除尾部一格, 添加头部一格, 并更新棋盘的值; 若吃到食物, 则头部添加一格, 尾部不会删除, 即实现了蛇的长度增加一格

2). 蛇的方向改变

  在按上下左右来改变蛇的方向时, 为了防止蛇反向移动吃掉自己, 需要获取蛇此时的移动方向

  例如: 蛇此时往右移动, 那么按"左"时蛇的移动方向不会发生改变, 否则会立即吃到自己结束游戏

  若成功改变移动方向, 则根据DIR变量来改变移动方向

snake = collections.deque()  # 蛇的实现
DIR = ((-1, 0), (1, 0), (0, -1), (0, 1))  # 上下左右
dir = DIR[3]  # 初始方向右
speed = 0.12# 蛇初始有三格
snake.append((0, 0))
snake.append((0, 1))
snake.append((0, 2))
grid[0][0], grid[0][1], grid[0][2] = True, True, True
.
.
.
# 蛇的速度随时间非线性增长
if game_t >= 10 * up:speed /= 1.2up += 1s -= F
if s <= 0:  # 移动一次x, y = snake[-1][0] + dir[0], snake[-1][1] + dir[1]  # 下一步的坐标x, y = x % SIDE, y % SIDE  # 过墙穿到另一边if grid[x][y] == True:  # 吃到自己, 游戏结束
        pygame.quit()exit()elif grid[x][y]:  # 吃到食物, 加分, 重新生成食物score += SCORE[grid[x][y]]create_food()  # 重新生成else:  # 无事发生, 前进一格xp, yp = snake.popleft()grid[xp][yp] = Nonesnake.append((x, y))grid[x][y] = Trues = speedfor e in pygame.event.get():if e.type == QUIT:pygame.quit()exit()if e.type == KEYDOWN:if e.key == K_UP and dir != DIR[1]:dir = DIR[0]elif e.key == K_DOWN and dir != DIR[0]:dir = DIR[1]elif e.key == K_LEFT and dir != DIR[3]:dir = DIR[2]elif e.key == K_RIGHT and dir != DIR[2]:dir = DIR[3]

 

3. 食物生成

食物采用随机生成在棋盘任意位置的方式, 但不能直接生成在蛇的身上.

这里为了避免食物一直生成在蛇身上, 然后导致程序卡在一个循环里, 我们设置最大循环次数为100, 若100次循环后还没找到位置生成食物, 就会遍历棋盘直接寻找空位, 没有空位则不生成食物 (你的蛇铺满了整个棋盘, 好耶)

  食物得分: 绿色:2分, 蓝色: 3分, 白色: 1分

  食物生成概率: 绿色25%, 蓝色 12.5%, 白色62.5%

SCORE = {GREEN: 2, LIGHTBLUE: 3, WHITE: 1}
RCOL = (GREEN, GREEN, LIGHTBLUE, WHITE, WHITE, WHITE, WHITE, WHITE)
score = 0  # 得分# 生成食物
def create_food():i, j = random.randint(0, SIDE-1), random.randint(0, SIDE-1)c = 0  # 重置次数while grid[i][j] and c <= 100:i, j = random.randint(0, SIDE-1), random.randint(0, SIDE-1)c += 1if c <= 100:grid[i][j] = (random.choice(RCOL))returnfor i in range(SIDE):for j in range(SIDE):if not grid[i][j]:grid[i][j] = (random.choice(RCOL))return.
.
.
create_food()

 

全部代码:

# 游戏规则: ↑ ↓ ← →控制蛇的移动方向
# 可以穿过边界
# 蛇的速度每10s增长一次, 不随分数增长import pygame, random, collections
from pygame.locals import *pygame.init()
WIDTH, HEIGHT = 750, 600
sur = pygame.display.set_mode((WIDTH, HEIGHT))
FPS = 200
fpsClock = pygame.time.Clock()# 颜色变量
WHITE =  (255, 255, 255)
RED  =   (255, 0, 0)
GREEN =  (0, 255, 0)
BLUE  =  (0, 0, 255)
BLACK =  (0, 0, 0)
YELLOW = (255, 255, 0)
SILVER = (192, 192, 192)
GRAY =   (169, 169, 169)
PURPLE = (127, 0, 255)
PINK =   (255, 51, 153)
ORANGE = (255, 128, 0)
BROWN =  (102, 51, 0)
LIGHTBLUE = (137, 207, 240)
WOOD = (222, 184, 135)# 游戏变量
SIZE = 30
SIDE = HEIGHT // SIZE
snake = collections.deque()
grid = [[None for _ in range(SIDE)] for _ in range(SIDE)]
DIR = ((-1, 0), (1, 0), (0, -1), (0, 1))  # 上下左右
dir = DIR[3]  # 初始方向右
SCORE = {GREEN: 2, LIGHTBLUE: 3, WHITE: 1}
RCOL = (GREEN, GREEN, LIGHTBLUE, WHITE, WHITE, WHITE, WHITE, WHITE)
score = 0  # 得分
speed = 0.12# 写入文本
def write(x, y, text, color, size):font = pygame.font.SysFont('SimHei', size)Text = font.render(text, True, color)sur.blit(Text, (x, y))# 生成食物
def create_food():i, j = random.randint(0, SIDE-1), random.randint(0, SIDE-1)c = 0  # 重置次数while grid[i][j] and c <= 100:i, j = random.randint(0, SIDE-1), random.randint(0, SIDE-1)c += 1if c <= 100:grid[i][j] = (random.choice(RCOL))returnfor i in range(SIDE):for j in range(SIDE):if not grid[i][j]:grid[i][j] = (random.choice(RCOL))returndef main():global speed, dir, score# 蛇初始有三格
    snake.append((0, 0))snake.append((0, 1))snake.append((0, 2))grid[0][0], grid[0][1], grid[0][2] = True, True, Truecreate_food()F = 1/FPSgame_t = 0s = speedup = 0while True:sur.fill(BLACK)sur.fill(GRAY, (WIDTH-150, 0, 200, HEIGHT))game_t += F# 右侧信息栏write(620, 80, '时间:'+str(int(game_t)), BLACK, 25)write(620, 20, '分数:'+str(score), BLACK, 25)write(620, 140, '速度:'+str(int(1/speed)), BLACK, 25)# 画蛇和食物for i in range(SIDE):for j in range(SIDE):if grid[i][j] == True:pygame.draw.rect(sur, PINK, (j*SIZE, i*SIZE, SIZE, SIZE))elif grid[i][j]:pygame.draw.rect(sur, grid[i][j], (j*SIZE, i*SIZE, SIZE, SIZE))# 画棋盘的线for i in range(0, WIDTH-149, SIZE):pygame.draw.line(sur, BLUE, (i, 0), (i, HEIGHT), 1)for j in range(0, HEIGHT+1, SIZE):pygame.draw.line(sur, BLUE, (0, j), (WIDTH-150, j), 1)# 蛇的速度随时间非线性增长if game_t >= 10*up:speed /= 1.2up += 1s -= Fif s <= 0:  # 移动一次x, y = snake[-1][0]+dir[0], snake[-1][1]+dir[1]  # 下一步的坐标x, y = x % SIDE, y % SIDE  # 过墙穿到另一边if grid[x][y] == True:  # 吃到自己, 游戏结束
                pygame.quit()exit()elif grid[x][y]:  # 吃到食物, 加分, 重新生成食物score += SCORE[grid[x][y]]create_food()  # 重新生成else:  # 无事发生, 前进一格xp, yp = snake.popleft()grid[xp][yp] = Nonesnake.append((x, y))grid[x][y] = Trues = speedfor e in pygame.event.get():if e.type == QUIT:pygame.quit()exit()if e.type == KEYDOWN:if e.key == K_UP and dir != DIR[1]:dir = DIR[0]elif e.key == K_DOWN and dir != DIR[0]:dir = DIR[1]elif e.key == K_LEFT and dir != DIR[3]:dir = DIR[2]elif e.key == K_RIGHT and dir != DIR[2]:dir = DIR[3]pygame.display.update()fpsClock.tick(FPS)main()

 

最后

请勿用于商业用途, 若有问题或bug, 感谢各位大佬及时指出!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hjln.cn/news/44150.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

在线RSA公私钥PKCS格式互转工具

在线公私钥PKCS格式转换,支持公钥PKCS1与PKCS8格式之间相互转换,私钥PKCS1与PKCS8格式之间相互转换;PKCS1定义RSA公开密钥算法加密和签名机制,PKCS8描述私有密钥信息格式,该信息包括公开密钥算法的私有密钥以及可选的属性集等。在线RSA公私钥PKCS格式互转工具

【0基础学爬虫】爬虫基础之自动化工具 DrissionPage 的使用

概述 前三期文章中已经介绍到了 Selenium 与 Playwright 、Pyppeteer 的使用方法,它们的功能都非常强大。而本期要讲的 DrissionPage 更为独特,强大,而且使用更为方便,目前检测少,强烈推荐!!! 这里推荐观看十一姐 B 站 DrissionPage 系列视频,很详细:合集爬虫自动化 …

dynamics 365 online仪表板提示:超出最大记录限制。请减少记录数量

1、Dynamics 365 online的仪表板确实有数量限制,当记录条数超过5万的时候,就会提示:超出最大记录限制。请减少记录数量 https://learn.microsoft.com/zh-cn/power-apps/maker/model-driven-apps/create-edit-system-chart https://learn.microsoft.com/zh-cn/power-apps/mak…

python gamma分布飞机作业前中后

数据: 目标做雨滴谱gamma分布,作业中、作业后1h、作业后2h 代码如下:#!usr/bin/env python # -*- coding:utf-8 -*- """ @author: Suyue @file: raincontent.py @time: 2024/05/23 @desc: """ import numpy as np import pandas as pd import…

国产2米高分遥感数据超分辨率(到0.5米)

​国产2米数据,包括高分一号PMS,高分六号PMS等等,应该是使用最为广泛的光学遥感数据了,主要是因为这几种数据幅宽大,组网访问频次也高,因此在全国各个自然资源、交通、水利等单位是应用最为广泛的数据源。但是这个数据有一个很大的缺陷,就是2米分辨率用来看一般的地物基…

Python 调整PDF页面尺寸大小

在处理PDF文件时,我们可能会遇到这样的情况:原始PDF文档不符合我们的阅读习惯,或者需要适配不同显示设备等。这时,我们就需要及时调整PDF文档中的页面尺寸,以满足不同应用场景的需求。 利用Python语言的高效性和灵活性,再结合Spire.PDF for Python 库的强大功能,我们可以…

redis集群报错

数据不一致, 通过./redis-cli --cluster check 10.12.120.19:7001 -a 123456 解决了.无聊我就学英语

腾讯云CVM主机在原分区(主分区)上增加磁盘空间

#现有环境: vdb 1000G- vdb1 500G - 剩余500G需要加在vdb1上# 1、安装- yum install -y cloud-utils-growpart- 一般系统都自带# 2、执行以下命令,使用 growpart 工具扩容分区- growpart /dev/vdb 1 # 1 表示是第一个分区:vdb1- 返回结果如下 图-1所示,则表示…