python程序22:写一个经典游戏-贪吃蛇

想必贪吃蛇这个游戏大家都玩过,那么贪吃蛇怎么在python代码里实现呢?

今天需要引入

PyQt5是一个基于Qt框架的Python GUI编程工具包,它提供了一系列的Python模块,使得开发者可以使用Python语言来开发跨平台的桌面应用程序。PyQt5是Qt官方推荐的Python绑定工具之一,它支持最新的Qt 5框架,并且提供了良好的文档和示例代码。

PyQt5包含了大量的类和函数,可以用于创建各种GUI组件,如窗口、标签、按钮、列表框、文本框等等。它还提供了一些高级组件,如图形场景、绘图区域、多媒体播放器等等。此外,PyQt5还支持与Qt Designer集成,使得开发者可以使用可视化的方式设计和布局界面。

根据需求需要引用如下的类和函数:
from PyQt5.QtWidgets import QApplication, QMainWindow, QDesktopWidget, QLabel, QPushButton, QGraphicsScene, QGraphicsView
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter

简单介绍这些类和函数:

  • QApplication:Qt应用程序类,用于管理应用程序的生命周期和事件循环。
  • QMainWindow:Qt主窗口类,提供了一个带有菜单栏、工具栏、状态栏等基本界面组件的窗口。
  • QDesktopWidget:Qt桌面窗口类,提供了一些方法来获取桌面的大小和屏幕分辨率等信息。
  • QLabel:Qt标签类,用于显示文本或图像等内容。
  • QPushButton:Qt按钮类,用于创建可点击的按钮。
  • QGraphicsScene:Qt图形场景类,提供了一个二维图形场景,可以在其中添加、移动、缩放和旋转图形项。
  • QGraphicsView:Qt图形视图类,提供了一个二维图形视图,可以在其中显示QGraphicsScene中的图形项。
  • QPainter:Qt绘图类,提供了一些方法来绘制各种图形、文本和图像等内容。

源代码如下所示(详细注释已列出):

import sys
import random
import pygame
from PyQt5.QtWidgets import QApplication, QMainWindow, QDesktopWidget, QLabel, QPushButton, QGraphicsScene, QGraphicsView
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter

# 游戏窗口大小
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600

# 贪吃蛇方块大小
BLOCK_SIZE = 20

# 游戏区域大小
GAME_AREA_WIDTH = WINDOW_WIDTH - BLOCK_SIZE * 2
GAME_AREA_HEIGHT = WINDOW_HEIGHT - BLOCK_SIZE * 6

# 贪吃蛇初始位置
SNAKE_INIT_X = GAME_AREA_WIDTH // 2
SNAKE_INIT_Y = GAME_AREA_HEIGHT // 2

# 贪吃蛇初始移动方向
SNAKE_INIT_DIRECTION = 'right'

# 食物颜色
FOOD_COLOR = (255, 0, 0)

# 贪吃蛇颜色
SNAKE_COLOR = (0, 255, 0)

# 分数颜色
SCORE_COLOR = (255, 255, 255)

class SnakeGame:
    def __init__(self):
        # 初始化Pygame库
        pygame.init()

        # 创建游戏窗口
        self.window = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
        pygame.display.set_caption('Snake Game')

        # 创建游戏区域表面
        self.game_area_surface = pygame.Surface((GAME_AREA_WIDTH, GAME_AREA_HEIGHT))

        # 创建游戏区域矩形
        self.game_area_rect = pygame.Rect(BLOCK_SIZE, BLOCK_SIZE, GAME_AREA_WIDTH, GAME_AREA_HEIGHT)

        # 创建贪吃蛇表面
        self.snake_surface = pygame.Surface((BLOCK_SIZE, BLOCK_SIZE))

        # 创建食物表面
        self.food_surface = pygame.Surface((BLOCK_SIZE, BLOCK_SIZE))
        self.food_surface.fill(FOOD_COLOR)

        # 创建贪吃蛇初始位置和移动方向
        self.snake = [(SNAKE_INIT_X, SNAKE_INIT_Y)]
        self.direction = SNAKE_INIT_DIRECTION

        # 创建食物位置
        self.food_pos = self.get_random_pos()

        # 创建分数
        self.score = 0

    def start(self):
        # 创建游戏时钟
        clock = pygame.time.Clock()

        # 游戏循环
        while True:
            # 处理事件
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_UP and self.direction != 'down':
                        self.direction = 'up'
                    elif event.key == pygame.K_DOWN and self.direction != 'up':
                        self.direction = 'down'
                    elif event.key == pygame.K_LEFT and self.direction != 'right':
                        self.direction = 'left'
                    elif event.key == pygame.K_RIGHT and self.direction != 'left':
                        self.direction = 'right'

            # 移动贪吃蛇
            head_x, head_y = self.snake[0]
            if self.direction == 'up':
                head_y -= BLOCK_SIZE
            elif self.direction == 'down':
                head_y += BLOCK_SIZE
            elif self.direction == 'left':
                head_x -= BLOCK_SIZE
            elif self.direction == 'right':
                head_x += BLOCK_SIZE

            # 判断是否吃到食物
            if head_x == self.food_pos[0] and head_y == self.food_pos[1]:
                self.snake.insert(0, (head_x, head_y))
                self.food_pos = self.get_random_pos()
                self.score += 10

            else:
                # 删除贪吃蛇尾部方块
                self.snake.pop()

                # 判断是否撞墙或自撞
                if not (BLOCK_SIZE <= head_x < GAME_AREA_WIDTH and BLOCK_SIZE <= head_y < GAME_AREA_HEIGHT) or (head_x, head_y) in self.snake:
                    self.game_over()

                else:
                    # 添加贪吃蛇头部方块
                    self.snake.insert(0, (head_x, head_y))

            # 绘制游戏区域和贪吃蛇
            self.game_area_surface.fill((0, 0, 0))
            for pos in self.snake:
                pygame.draw.rect(self.game_area_surface, SNAKE_COLOR, (pos[0]-BLOCK_SIZE, pos[1]-BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))
            self.game_area_surface.blit(self.food_surface, (self.food_pos[0]-BLOCK_SIZE, self.food_pos[1]-BLOCK_SIZE))

            # 绘制分数
            font = pygame.font.SysFont(None, 36)
            score_text = font.render(f'Score: {self.score}', True, SCORE_COLOR)
            score_rect = score_text.get_rect()
            score_rect.centerx = WINDOW_WIDTH // 2
            score_rect.top = BLOCK_SIZE // 2
            self.game_area_surface.blit(score_text, score_rect)

            # 将游戏区域表面绘制到游戏窗口中央位置
            window_centerx = WINDOW_WIDTH // 2
            window_centery = WINDOW_HEIGHT // 2
            game_area_centerx = BLOCK_SIZE + GAME_AREA_WIDTH // 2
            game_area_centery = BLOCK_SIZE + GAME_AREA_HEIGHT // 2
            x_offset = window_centerx - game_area_centerx
            y_offset = window_centery - game_area_centery
            self.window.fill((0, 0, 0))
            self.window.blit(self.game_area_surface, (x_offset, y_offset))

            # 刷新屏幕并控制帧率
            pygame.display.update()
            clock.tick(10)

    def get_random_pos(self):
        x = random.randint(BLOCK_SIZE, GAME_AREA_WIDTH - BLOCK_SIZE)
        y = random.randint(BLOCK_SIZE, GAME_AREA_HEIGHT - BLOCK_SIZE)
        return (x // BLOCK_SIZE * BLOCK_SIZE, y // BLOCK_SIZE * BLOCK_SIZE)

    def game_over(self):
        print('Game over!')
        pygame.quit()
        sys.exit()

class SnakeWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        # 设置窗口标题和大小
        self.setWindowTitle('Snake Game')
        self.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)

        # 设置窗口居中显示
        screen_rect = QDesktopWidget().availableGeometry(self)
        window_rect = self.frameGeometry()
        window_rect.moveCenter(screen_rect.center())
        self.move(window_rect.topLeft())

        # 创建游戏场景和视图
        scene = QGraphicsScene()
        view = QGraphicsView(scene)
        view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        view.setRenderHint(QPainter.Antialiasing)
        view.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
        view.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)

        # 创建游戏标签和按钮
        label = QLabel('Snake Game', view)
        label.setAlignment(Qt.AlignCenter)
        label.setGeometry(0, 50, WINDOW_WIDTH, 100)

        button_start = QPushButton('Start', view)
        button_start.setGeometry(150, 200, 100, 50)
        button_start.clicked.connect(self.start_game)

        button_exit = QPushButton('Exit', view)
        button_exit.setGeometry(550, 200, 100, 50)
        button_exit.clicked.connect(self.close)

        # 将视图设置为主窗口的中心部件
        self.setCentralWidget(view)

    def start_game(self):
        # 创建SnakeGame对象并开始游戏循环
        game = SnakeGame()
        game.start()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = SnakeWindow()
    window.show()
    sys.exit(app.exec_())




我们运行测试一下:

这里食物在窗口内随机生成,当蛇吃入食物以后自己的身长会增加一格,随之分数会增加。当蛇自己碰撞到自己身体或者撞到窗口边缘则会游戏结束。感兴趣的同学在pycharm里尝试一下吧,有不理解的欢迎在评论区留言讨论。

发表回复