Day4——0基础剖解贪吃蛇部分代码

该代码实现了一个基于PythonPygame库的贪吃蛇游戏。游戏使用双端队列(deque)来存储和管理蛇的身体坐标,通过pygame模块创建游戏窗口,处理用户输入和图形绘制。游戏包含初始化蛇的位置、创建随机食物、处理蛇的移动和碰撞检测等功能。当蛇吃到食物时,速度会增加,游戏结束时显示GAMEOVER。
摘要由CSDN通过智能技术生成

源码如下

"""贪吃蛇"""

import random #该模块提供生成伪随机数 创建随机食物位置 防止食物生成在蛇身上
import sys# 这个函数可以用于退出 Python 解释器在贪吃蛇游戏中,你可以使用 sys.exit() 来结束游戏。
import time#提供时间相关的功能。在贪吃蛇游戏中使用time.time()来获取当前时间戳,用于计算两次移动之间的时间间隔
import pygame#使用pygame来创建游戏窗口、处理用户输入、绘制图形等操作。
from pygame.locals import *#模块提供了一些常用的常量和变量,用于方便地访问和使用pygame模块的功能。
# 这些常量和变量涵盖了游戏开发中常见的输入事件、键盘按键、鼠标事件、窗口事件等
from collections import deque#入collections模块中的deque类
#deque类可以在贪吃蛇游戏中用于存储蛇身的坐标
#通过使用deque作为蛇身的数据结构,可以方便地实现以下操作:
#在蛇尾添加新的蛇身坐标,即蛇身的延长;
#在蛇头删除旧的蛇身坐标,即蛇身的移动;
#高效地访问蛇身的所有坐标。

SCREEN_WIDTH = 600      # 屏幕宽度
SCREEN_HEIGHT = 480     # 屏幕高度
SIZE = 20               # 小方格大小
LINE_WIDTH = 1          # 网格线宽度

# 游戏区域的坐标范围
SCOPE_X = (0, SCREEN_WIDTH // SIZE - 1)
#-1是因为计算机索引范围是从0开始 计算出贪吃蛇在水平方向上可以占据的方块数量
SCOPE_Y = (2, SCREEN_HEIGHT // SIZE - 1)

# 食物的分值及颜色
FOOD_STYLE_LIST = [(10, (255, 100, 100)), (20, (100, 255, 100)), (30, (100, 100, 255))]
#FOOD_STYLE_LIST是一个包含食物分值及颜色的列表。每个元素是一个元组,元组的第一个值是食物的分值,
# 第二个值是食物的颜色。例如,(10, (255, 100, 100)) 表示一个分值为 10 的食物,颜色为红色
#(20, (100, 255, 100)) 表示一个分值为 20 的食物,其颜色为亮绿色
LIGHT = (100, 100, 100)
DARK = (200, 200, 200)      # 蛇的颜色
BLACK = (0, 0, 0)           # 网格线颜色
RED = (200, 30, 30)         # 红色,GAME OVER 的字体颜色
BGCOLOR = (40, 40, 60)      # 背景色


def print_text(screen, font, x, y, text, fcolor=(255, 255, 255)):
    # 这是 Pygame 的函数,用于将文本渲染为图像。它接受文本字符串、一个布尔值参数用于启用或禁用抗锯齿功能
    imgText = font.render(text, True, fcolor)

    # ,以及一个颜色参数 fcolor 用于指定文本的颜色。调用该函数会返回一个文本图像对象 imgText。
    screen.blit(imgText, (x, y))


# 初始化蛇
def init_snake():
    snake = deque()
    snake.append((2, SCOPE_Y[0]))
    snake.append((1, SCOPE_Y[0]))
    snake.append((0, SCOPE_Y[0]))
    return snake


def create_food(snake):
    food_x = random.randint(SCOPE_X[0], SCOPE_X[1])
    food_y = random.randint(SCOPE_Y[0], SCOPE_Y[1])
    while (food_x, food_y) in snake:
        # 如果食物出现在蛇身上,则重来
        food_x = random.randint(SCOPE_X[0], SCOPE_X[1])
        food_y = random.randint(SCOPE_Y[0], SCOPE_Y[1])
    return food_x, food_y


def get_food_style():
    return FOOD_STYLE_LIST[random.randint(0, 2)]


def main():
    pygame.init()
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    pygame.display.set_caption('贪吃蛇')

    font1 = pygame.font.SysFont('SimHei', 24)  # 得分的字体
    font2 = pygame.font.Font(None, 72)  # GAME OVER 的字体
    fwidth, fheight = font2.size('GAME OVER')

    # 如果蛇正在向右移动,那么快速点击向下向左,由于程序刷新没那么快,向下事件会被向左覆盖掉,导致蛇后退,直接GAME OVER
    # b 变量就是用于防止这种情况的发生
    b = True

    # 蛇
    snake = init_snake()
    # 食物
    food = create_food(snake)
    food_style = get_food_style()
    # 方向
    pos = (1, 0)

    game_over = True
    start = False       # 是否开始,当start = True,game_over = True 时,才显示 GAME OVER
    score = 0           # 得分
    orispeed = 0.5      # 原始速度
    speed = orispeed
    last_move_time = None
    pause = False       # 暂停

    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                sys.exit()
            elif event.type == KEYDOWN:
                if event.key == K_RETURN:
                    if game_over:
                        start = True
                        game_over = False
                        b = True
                        snake = init_snake()
                        food = create_food(snake)
                        food_style = get_food_style()
                        pos = (1, 0)
                        # 得分
                        score = 0
                        last_move_time = time.time()
                elif event.key == K_SPACE:
                    if not game_over:
                        pause = not pause
                elif event.key in (K_w, K_UP):
                    # 这个判断是为了防止蛇向上移时按了向下键,导致直接 GAME OVER
                    if b and not pos[1]:
                        pos = (0, -1)
                        b = False
                elif event.key in (K_s, K_DOWN):
                    if b and not pos[1]:
                        pos = (0, 1)
                        b = False
                elif event.key in (K_a, K_LEFT):
                    if b and not pos[0]:
                        pos = (-1, 0)
                        b = False
                elif event.key in (K_d, K_RIGHT):
                    if b and not pos[0]:
                        pos = (1, 0)
                        b = False

        # 填充背景色
        screen.fill(BGCOLOR)
        # 画网格线 竖线
        for x in range(SIZE, SCREEN_WIDTH, SIZE):
            pygame.draw.line(screen, BLACK, (x, SCOPE_Y[0] * SIZE), (x, SCREEN_HEIGHT), LINE_WIDTH)
        # 画网格线 横线
        for y in range(SCOPE_Y[0] * SIZE, SCREEN_HEIGHT, SIZE):
            pygame.draw.line(screen, BLACK, (0, y), (SCREEN_WIDTH, y), LINE_WIDTH)

        if not game_over:
            curTime = time.time()
            if curTime - last_move_time > speed:
                if not pause:
                    b = True
                    last_move_time = curTime
                    next_s = (snake[0][0] + pos[0], snake[0][1] + pos[1])
                    if next_s == food:
                        # 吃到了食物
                        snake.appendleft(next_s)
                        score += food_style[0]
                        speed = orispeed - 0.03 * (score // 100)
                        food = create_food(snake)
                        food_style = get_food_style()
                    else:
                        if SCOPE_X[0] <= next_s[0] <= SCOPE_X[1] and SCOPE_Y[0] <= next_s[1] <= SCOPE_Y[1] \
                                and next_s not in snake:
                            snake.appendleft(next_s)
                            snake.pop()
                        else:
                            game_over = True

        # 画食物
        if not game_over:
            # 避免 GAME OVER 的时候把 GAME OVER 的字给遮住了
            pygame.draw.rect(screen, food_style[1], (food[0] * SIZE, food[1] * SIZE, SIZE, SIZE), 0)

        # 画蛇
        for s in snake:
            pygame.draw.rect(screen, DARK, (s[0] * SIZE + LINE_WIDTH, s[1] * SIZE + LINE_WIDTH,
                                            SIZE - LINE_WIDTH * 2, SIZE - LINE_WIDTH * 2), 0)

        print_text(screen, font1, 30, 7, f'速度: {score//100}')
        print_text(screen, font1, 450, 7, f'得分: {score}')

        if game_over:
            if start:
                print_text(screen, font2, (SCREEN_WIDTH - fwidth) // 2, (SCREEN_HEIGHT - fheight) // 2, 'GAME OVER', RED)

        pygame.display.update()


if __name__ == '__main__':
    main()

1.双端队列数据结构

代码46-54行

# 初始化蛇
def init_snake():
    snake = deque()
    snake.append((2, SCOPE_Y[0]))
    snake.append((1, SCOPE_Y[0]))
    snake.append((0, SCOPE_Y[0]))
    return snake
  1. deque():这是一个双端队列数据结构,通过 import collections 导入使用。双端队列可以在两端进行高效的插入和删除操作。在这段代码中,snake 被初始化为一个双端队列。

  2. append():这是 deque 对象的内置方法,用于向队列的右侧添加元素。在这段代码中,使用 snake.append() 将元组 (2, SCOPE_Y[0])(1, SCOPE_Y[0]) 和 (0, SCOPE_Y[0]) 依次添加到 snake 队列的右侧。

  3. SCOPE_Y:这是一个列表或其他可迭代对象,用于存储 Y 轴的范围。这段代码没有给出 SCOPE_Y 的具体定义,但可以假设它包含了 Y 轴的一些值。

这段代码的语法是 Python 语言的语法。在 Python 中,函数定义使用 def 关键字,后跟函数名称和一对圆括号,可能包含参数列表。函数体通常使用缩进来表示代码块,函数体中的代码会在函数被调用时执行。在这段代码中,init_snake() 是一个无参数的函数,返回一个 deque 对象。

这段代码的作用是初始化蛇的初始位置。通过在 snake 队列中添加三个元组,表示蛇身的初始位置。该蛇的初始位置位于 X 坐标为 2、1 和 0,Y 坐标为 SCOPE_Y[0] 的位置。最后,该函数返回初始化后的 snake 队列对象。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值