Skip to content

PyGame-贪吃蛇

难度:⭐⭐⭐

1. 题目描述

题目描述

使用 Pygame 库实现贪吃蛇

2. 关键点

  • pygame 的使用;运行 pip install pygame 进行安装
  • 向量的理解与使用

3. 代码实现

点击显示代码
python
import sys
import random
import pygame
from pygame.math import Vector2


class Fruit:
    """水果类"""
    def __init__(self):
        self.randomize()

    def draw(self):
        """绘制水果"""
        rect = pygame.Rect(
            self.pos.x * cell_size,
            self.pos.y * cell_size,
            cell_size,
            cell_size
        )
        pygame.draw.rect(screen, fruit_color, rect)

    def randomize(self):
        """随机位置"""
        self.x = random.randint(0, cell_number - 1)
        self.y = random.randint(0, cell_number - 1)
        self.pos = Vector2(self.x, self.y)


class Snake:
    """贪吃蛇"""
    def __init__(self):
        # 初始🐍
        self.body = [Vector2(5, 10), Vector2(4, 10), Vector2(3, 10)]
        self.direction = Vector2(1, 0)

    def draw(self):
        """绘制贪吃蛇"""
        for block in self.body:
            x_pos = int(block.x * cell_size)
            y_pos = int(block.y * cell_size)
            rect = pygame.Rect(x_pos, y_pos, cell_size, cell_size)
            pygame.draw.rect(screen, snake_color, rect)

    def move(self):
        """移动"""
        self.eat()
        self.body.pop()

    def eat(self):
        """吃到水果"""
        self.body.insert(0, self.body[0] + self.direction)


class Main:
    def __init__(self):
        self.snake = Snake()
        self.fruit = Fruit()

    def update(self):
        self.snake.move()
        self.check_eat()
        self.check_fail()

    def draw_elements(self):
        """进行绘制"""
        self.fruit.draw()
        self.snake.draw()

    def check_eat(self):
        """判断是否吃到了水果"""
        if self.fruit.pos == self.snake.body[0]:
            self.fruit.randomize()
            self.snake.eat()

    def check_fail(self):
        """失败检测
        1. 蛇头撞墙失败
        2. 蛇头吃到自己失败
        """
        if not 0 <= self.snake.body[0].x < cell_number \
                or not 0 <= self.snake.body[0].y < cell_number:
            print('撞墙了')
            self.game_over()

        for block in self.snake.body[1:]:
            if block == self.snake.body[0]:
                print('吃到自己了')
                self.game_over()

    @staticmethod
    def game_over():
        pygame.quit()
        sys.exit()


screen_color = (175, 215, 70)   # 屏幕背景颜色
fruit_color = (126, 166, 114)   # 水果颜色
snake_color = (183, 111, 122)   # 蛇体颜色
cell_size = 20      # 蛇体宽度
cell_number = 20    # 控制屏幕大小

pygame.init()
pygame.display.set_caption('贪吃蛇')
screen = pygame.display.set_mode(
        (cell_number * cell_size, cell_number * cell_size))
clock = pygame.time.Clock()

SCREEN_UPDATE = pygame.USEREVENT
pygame.time.set_timer(SCREEN_UPDATE, 200)

main = Main()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            main.game_over()
        if event.type == SCREEN_UPDATE:
            main.update()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                if main.snake.direction.y != 1:
                    main.snake.direction = Vector2(0, -1)
            if event.key == pygame.K_RIGHT:
                if main.snake.direction.x != -1:
                    main.snake.direction = Vector2(1, 0)
            if event.key == pygame.K_DOWN:
                if main.snake.direction.y != -1:
                    main.snake.direction = Vector2(0, 1)
            if event.key == pygame.K_LEFT:
                if main.snake.direction.x != 1:
                    main.snake.direction = Vector2(-1, 0)

    screen.fill(screen_color)
    main.draw_elements()
    pygame.display.update()
    clock.tick(60)

4. 运行示例

5. 进阶思考

  1. 为水果和贪吃蛇添加材质