首页 > 编程语言 >贪吃蛇小游戏Python Pygame实现

贪吃蛇小游戏Python Pygame实现

时间:2024-06-11 17:37:04浏览次数:26  
标签:Python 小游戏 grid 食物 贪吃蛇 GREEN WHITE SIDE 255

运行结果

 

游戏规则

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.2
    up += 1

s -= 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] = None
    snake.append((x, y))
    grid[x][y] = True
    s = speed

for 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 += 1
    if c <= 100:
        grid[i][j] = (random.choice(RCOL))
        return
    for 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 += 1
    if c <= 100:
        grid[i][j] = (random.choice(RCOL))
        return
    for i in range(SIDE):
        for j in range(SIDE):
            if not grid[i][j]:
                grid[i][j] = (random.choice(RCOL))
                return


def 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, True
    create_food()
    F = 1/FPS
    game_t = 0
    s = speed
    up = 0
    while 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.2
            up += 1

        s -= 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] = None
            snake.append((x, y))
            grid[x][y] = True
            s = speed


        for 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, 感谢各位大佬及时指出!

标签:Python,小游戏,grid,食物,贪吃蛇,GREEN,WHITE,SIDE,255
From: https://www.cnblogs.com/xanderChou/p/18242363

相关文章

  • Python 字符串
    Python字符串Python中的字符串是一种常见且重要的数据类型,用于存储文本信息。字符串是不可变的,即一旦创建,就不能更改其内容。但我们可以创建新的字符串作为修改的结果。以下是关于Python字符串的一些基本操作和功能的介绍。数据类型转字符串在Python中,你可以使用str()......
  • 爬取京东商品图片的Python实现方法
    引言在数据驱动的商业环境中,网络爬虫技术已成为获取信息的重要手段。京东作为中国领先的电商平台,拥有海量的商品信息和图片资源。本文将详细介绍如何使用Python编写爬虫程序,爬取京东商品的图片,并提供完整的代码实现过程。爬虫基础在开始编写爬虫之前,需要了解一些基本的网......
  • Python 调整PDF页面尺寸大小
    在处理PDF文件时,我们可能会遇到这样的情况:原始PDF文档不符合我们的阅读习惯,或者需要适配不同显示设备等。这时,我们就需要及时调整PDF文档中的页面尺寸,以满足不同应用场景的需求。利用Python语言的高效性和灵活性,再结合Spire.PDFforPython库的强大功能,我们可以通过Python代码轻......
  • python怎么保留小数
    保留两位小数,并做四舍五入处理方法一:使用字符串格式化a = 12.345print("%.2f" % a)# 12.35方法二:使用round内置函数a = 12.345a1 = round(a, 2)print(a1)# 12.35方法三:使用decimal模块from decimal import Decimala = 12.345Decimal(a).......
  • python怎么画曲线图
    如何使用python画曲线图?下面是基本步骤:前提首先,为了实际使用Matplotlib,我们需要安装它。安装如果你安装了更高版本的Python,你应该能够打开cmd.exe或终端,然后执行:pip install matplotlib注意:如果上面的较短命令不工作,你可能需要执行C:/Python34/Scripts/pipinsta......
  • 基于Vue+Node.js的高校学业预警系统+10551(免费领源码)可做计算机毕业设计JAVA、PHP、爬
    NodeJS高校学业预警系统摘 要随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,教育行业当然也不能排除在外。高校学业预警系统是以实际运用为开发背景,运用软件工程开发方法,采用Node.JS技术构建的一个管理系统。......
  • 使用python处理excel数据
    使用python处理excel数据python处理excel数据时间差计算平均量计算excel处理后数据python处理excel数据excel数据有一列是开始时间,一列为结束时间,计算时间差,时间差>1h,将数据平均为1h。时间差>1h,总量也将平均到每个小时,如第三行数据,时间差为4h,数据为5.2,所以每小时......
  • python-找第一个只出现一次的字符
    [题目描述]给定一个只包含小写字母的字符串,请你找到第一个仅出现一次的字符。如果没有,输出no。输入:一个字符串,长度小于1100。输出:输出第一个仅出现一次的字符,若没有则输出no。样例输入1abcabd样例输出1c来源/分类(难度系数:一星) 完整代码如下:a=list(input())b=[......
  • python数据分析
    frompyechartsimportoptionsasoptsfrompyecharts.chartsimportMap#假设你有一个包含省份和抖音大v人数的字典data={  "广东":100,  "江苏":80,  "山东":70,  "浙江":60,  "河南":50,  "河北":40,  &qu......
  • Python项目打包二进制文件并发布
    复制项目生成二进制文件(交叉编译???)重命名二进制文件生成pyi文件(编译器智能提示需要删除原始py文件(复制后的)项目打包上传(分版本分平台???)流程、代码待完善二进制文件生成pipinstallcpython#setup.pydeffind_pyx_files(directory):pyx_files=[]forroot,_......