Python课程设计:python制作俄罗斯方块小游戏

news2024/10/7 7:28:48

基于python的俄罗斯方块小游戏

目录

基于python的俄罗斯方块小游戏

1.概述

1.1 摘要

1.2 开发背景

1.3 开发环境

1.4 实现功能

2.代码描述

2.1 模块导入

2.2 初始化变量

2.3 播放音乐

2.4 创建方块类

2.5 绘制游戏地图

2.6 游戏初始化

2.7 绘制有边框矩形

2.8 绘制我的文字

2.9 游戏主体

2.10 主程序运行

3.运行效果

4.注意事项

5.附录源码


1.概述

1.1 摘要

本文介绍了一个基于Python语言开发的简单俄罗斯方块小游戏。该游戏使用了pygame库来实现图形界面和声音效果,并通过面向对象的设计方法来组织代码。游戏的主要功能包括方块的随机生成、移动、旋转、消除行以及得分计算等。游戏界面简洁直观,音效增强了游戏体验。此外,游戏还提供了音乐开关和游戏暂停的功能,以增加游戏的可玩性和用户友好性。

1.2 开发背景

俄罗斯方块是一款经典的益智游戏,自上世纪80年代推出以来一直备受欢迎。随着计算机技术的不断发展,越来越多的开发者尝试将这款游戏移植到各种平台上。Python作为一种易学易用且功能强大的编程语言,非常适合用于开发小游戏。同时,pygame库提供了丰富的图形、声音和事件处理功能,使得开发过程更加便捷。

1.3 开发环境

Windows 11系统

pycharm 2021

python 3.9

1.4 实现功能

1.方块生成与显示:游戏会根据预设的方块类型随机生成一个新的方块,并在游戏界面的顶部显示。

2.方块移动与旋转:玩家可以通过键盘控制方块的左右移动和顺时针/逆时针旋转。

3.消除行与得分:当玩家将一行方块填满时,该行会消除并给玩家加分。消除的行数越多,得分越高。

4.游戏结束条件:当方块堆积到游戏界面的顶部时,游戏结束。

5.音效与音乐:游戏中有方块下落、消除行等音效,同时提供了开启/关闭背景音乐的选项。

6.游戏暂停与恢复:玩家可以随时暂停游戏并在之后恢复,方便玩家在需要时暂时离开。

7.等级与速度:随着游戏的进行,方块的生成速度会逐渐加快,增加游戏难度。

2.代码描述

2.1 模块导入
import pygame
from pygame.locals import *
from sys import exit
import random

分析:

1.pygame: 一个用于制作游戏的Python库。

2.pygame.locals: 从pygame库中导入的常量集合。

3.sys: Python标准库中的模块,用于与Python解释器交互。

4.random: 用于生成随机数。

2.2 初始化变量
# 使用pygame.init()初始化pygame库
pygame.init()

# 常量
MAX_I = 34
MAX_J = 15
# 定义地图的最大行数和列数
SIZE = 15
# 方块的大小

COLORS = [(0, 0, 0), (255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0), (255, 255, 255)]
# 一个颜色列表,用于表示不同的方块
gameMap = [[0 for j in range(MAX_J + 3)] for i in range(MAX_I + 3)]
# 一个二维列表,代表游戏地图。初始化为全0,表示没有方块。
tetrisHeight = 0
# 记录当前塔的高度,即已放下的方块行数
tetrises = [
    [
        [1, 0, 0, 0],
        [1, 0, 0, 0],
        [1, 0, 0, 0],
        [1, 0, 0, 0]
    ],
    [
        [0, 0, 0, 0],
        [0, 1, 1, 0],
        [0, 1, 1, 0],
        [0, 0, 0, 0]
    ],
    [
        [1, 0, 0, 0],
        [1, 1, 0, 0],
        [0, 1, 0, 0],
        [0, 0, 0, 0]
    ],
    [
        [0, 1, 0, 0],
        [1, 1, 0, 0],
        [1, 0, 0, 0],
        [0, 0, 0, 0]
    ],
    [
        [0, 1, 0, 0],
        [1, 1, 1, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]
    ],
    [
        [1, 0, 0, 0],
        [1, 1, 1, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]
    ],
    [
        [0, 0, 1, 0],
        [1, 1, 1, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]
    ]
]
# 一个列表,包含7种不同的基本方块形状。每个形状都是一个二维列表,表示方块的各个部分。
# 分数
score = 0
# 等级
level = 1
# 音乐开关
isMusic = True
# 游戏暂停
isPause = False

分析:

此代码段只是游戏的初始化部分,没有包含游戏的主循环、方块的移动、旋转、消除行以及得分等逻辑。但从这段代码中,我们可以看出这是一个俄罗斯方块游戏的基础框架,接下来的代码会包含游戏的主体逻辑和界面渲染等部分。

2.3 播放音乐
def playMyMusic(src):
    if isMusic:
        sound = pygame.mixer.Sound(src)
        sound.play()

分析:

这个函数接收一个参数src,这个参数应该是音乐文件的路径。如果isMusic变量为True(意味着音乐功能是开启的),那么函数会加载音乐文件并播放它。这里使用了pygame.mixer.Sound来加载声音文件,并调用play方法来播放声音。

2.4 创建方块类

2.4.1 定义私有属性

class Tetris:
    __i = 0
    __j = 0
    __color = 0
    __nextColor = 0
    __nextType = 0

分析:

1.__i: 方块的行位置。

2.__j: 方块的列位置。

3.__color: 方块的颜色。

4.__nextColor: 下一个方块的颜色。

5.__nextType: 下一个方块的类型。

2.4.2 构造函数__init__

这个构造函数在创建Tetris类的实例时被调用。它初始化下一个方块的颜色和类型,并调用createTetris方法来创建当前的方块。

    def __init__(self):
        self.__nextColor = random.randint(0, 3) + 1  # 一共四种颜色
        self.__nextType = random.randint(0, 6)  # 一共七种类型
        self.createTetris()

2.4.3 createTetris方法

    def createTetris(self):
        # 根据类型调整一下快出现的位置
        if self.__nextType == 0:
            self.__i = 1
            self.__j = 7
        else:
            self.__i = 2
            self.__j = 6
        self.__color = self.__nextColor

        # 根据方块模板,放置整个到地图
        for i in range(4):
            for j in range(4):
                if tetrises[self.__nextType][i][j] == 1:
                    if gameMap[self.__i + i][self.__j + j] == 0:
                        gameMap[self.__i + i][self.__j + j] = self.__color
                    else:
                        print('游戏失败!')
                        exit()
                        return -1

        # 产生下一种类型和颜色
        self.__nextColor = random.randint(0, 3) + 1  # 一共四种颜色
        self.__nextType = random.randint(0, 6)  # 一共七种类型

        playMyMusic('music/get.wav')

分析:

该段代码的主要功能是创建一个新的俄罗斯方块(Tetris)并将其放置在游戏地图上。以下是代码的主要功能概述:

确定方块的初始位置:根据方块的类型(self.__nextType),代码确定了方块在游戏地图上的初始位置(self.__i 和 self.__j)。不同的方块类型可能需要不同的起始位置。

**设置方块的颜色:**将方块的颜色设置为下一个可用的颜色(self.__nextColor)。颜色是通过一个随机数生成的,确保每种颜色都有可能被选中。

**放置方块到游戏地图:**通过两个嵌套的循环,代码遍历方块的每个格子。如果方块模板中的某个格子值为1(表示该格子被填充),则检查游戏地图中对应的位置是否为空(值为0)。如果为空,则在该位置放置方块(即将该位置的值设置为方块的颜色)。如果对应位置已经被其他方块占据,则输出“游戏失败!”并退出游戏。

**生成下一种方块类型和颜色:**在成功放置当前方块后,代码生成下一种方块的类型和颜色。这是通过随机数生成器实现的,确保每次生成的方块类型和颜色都是随机的。

**播放音效:**放置方块后,播放一个音效文件(‘music/get.wav’),为玩家提供反馈。

总的来说,这段代码是俄罗斯方块游戏中生成和放置新方块的关键部分,它负责处理方块的初始位置、颜色、放置逻辑以及生成下一种方块。

    def moveDown(self):
        global gameMap

        # 判断是否可以下移
        for j in range(4):
            for i in range(3, -1, -1):
                if gameMap[self.__i + i][self.__j + j] == self.__color:
                    # 判断是否到底
                    if self.__i + i + 1 > MAX_I:
                        return 1

                    # 判断前面是否有东西
                    if gameMap[self.__i + i + 1][self.__j + j] != 0:
                        return 1

                    break

        # 下移
        for j in range(4):
            for i in range(3, -1, -1):
                if gameMap[self.__i + i][self.__j + j] == self.__color:
                    gameMap[self.__i + i][self.__j + j], gameMap[self.__i + i + 1][self.__j + j] = \
                        gameMap[self.__i + i + 1][self.__j + j], gameMap[self.__i + i][self.__j + j]

        self.__i += 1

分析:

该段代码的主要功能是处理俄罗斯方块游戏中方块的下移操作。以下是代码的主要功能概述:

**判断是否可以下移:**通过两个嵌套的循环遍历方块的每个格子,检查当前方块是否可以下移。首先,它检查方块是否已经到达地图的底部(即是否超过了最大行数MAX_I),如果是,则不能下移,函数返回1。其次,它检查方块的下方是否有其他方块占据,如果有,则不能下移,函数同样返回1。

**执行下移操作:**如果上述检查都通过,说明方块可以下移,代码将执行下移操作。通过另一个两个嵌套的循环遍历方块的每个格子,找到当前方块的每个格子,并将其与其下方的对应格子交换位置。这实际上是将整个方块向下移动了一行。

**更新方块位置:**在成功执行下移操作后,代码更新方块的__i属性值,将其增加1,以反映方块在游戏地图中的新位置。

这个函数的目的是处理方块的下移逻辑,包括检查是否可以下移、执行下移操作以及更新方块的位置。它是俄罗斯方块游戏中控制方块移动的重要部分。

    def stopTetris(self):
        global tetrisHeight

        flag = True

        for i in range(4):
            for j in range(4):
                if gameMap[self.__i + i][self.__j + j] == self.__color:
                    gameMap[self.__i + i][self.__j + j] += 10

                    # 找到第一个颜色方块
                    if flag:
                        tetrisHeight = MAX_I - self.__i if tetrisHeight < MAX_I - self.__i else tetrisHeight
                        flag = False

        self.deleteRow()

分析:

该段代码的主要功能是停止当前正在下落的俄罗斯方块,并对其进行处理。以下是代码的主要功能概述:

标记方块停止状态:首先,代码通过遍历当前方块的每个格子,将其颜色值增加10,以标记这些格子属于已经停止下落的方块。这样做通常是为了在游戏地图上区分正在下落和已经停止的方块。

确定方块高度:在标记方块的过程中,代码还查找并记录了当前方块的最高位置(即方块中最顶部的行索引)。这是通过比较当前方块最高行与全局变量tetrisHeight的值来完成的,确保tetrisHeight始终存储当前游戏地图中最高的方块高度。

删除完整行:在标记完方块并确定了其高度后,代码调用deleteRow函数来检查并删除游戏地图中的完整行。这是俄罗斯方块游戏中的一个重要机制,当玩家堆叠的方块形成完整的一行时,该行会被消除,并为玩家带来分数和可能的等级提升。

总的来说,这段代码负责在方块停止下落时对其进行处理,包括标记方块状态、确定方块高度以及触发行消除机制。这是俄罗斯方块游戏中管理方块状态和控制游戏逻辑的关键部分。

    def moveLeft(self):
        # 判断是否能够左移
        for i in range(4):
            for j in range(4):
                if gameMap[self.__i + i][self.__j + j] == self.__color:
                    if self.__j + j - 1 < 0:
                        return 1
                    if gameMap[self.__i + i][self.__j + j - 1] != 0:
                        return 1

                    break

        # 左移
        for i in range(4):
            for j in range(4):
                if gameMap[self.__i + i][self.__j + j] == self.__color:
                    gameMap[self.__i + i][self.__j + j], gameMap[self.__i + i][self.__j + j - 1] = \
                        gameMap[self.__i + i][self.__j + j - 1], gameMap[self.__i + i][self.__j + j]

        self.__j -= 1

分析:

该段代码的主要功能是处理俄罗斯方块游戏中方块的左移操作。以下是代码的主要功能概述:

判断是否可以左移:代码首先通过两个嵌套的循环遍历方块的每个格子,检查当前方块是否可以向左移动。它首先检查方块的左侧是否有足够的空间(即是否超出了地图的左边界),如果是,则不能左移,函数返回1。其次,它检查方块的左侧是否有其他方块占据,如果有,则不能左移,函数同样返回1。

执行左移操作:如果上述检查都通过,说明方块可以左移,代码将执行左移操作。通过另一个两个嵌套的循环遍历方块的每个格子,找到当前方块的每个格子,并将其与其左侧的对应格子交换位置。这实际上是将整个方块向左移动了一列。

更新方块位置:在成功执行左移操作后,代码更新方块的__j属性值,将其减少1,以反映方块在游戏地图中的新位置。

这个函数的目的是处理方块的左移逻辑,包括检查是否可以左移、执行左移操作以及更新方块的位置。它是俄罗斯方块游戏中控制方块移动的重要部分。


    def moveRight(self):
        # 判断是否能右移
        for i in range(4):
            for j in range(3, -1, -1):
                if gameMap[self.__i + i][self.__j + j] == self.__color:
                    if self.__j + j + 1 >= MAX_J:
                        return 1
                    if gameMap[self.__i + i][self.__j + j + 1] != 0:
                        return 1

                    break

        # 右移
        for i in range(4):
            for j in range(3, -1, -1):
                if gameMap[self.__i + i][self.__j + j] == self.__color:
                    gameMap[self.__i + i][self.__j + j], gameMap[self.__i + i][self.__j + j + 1] = \
                        gameMap[self.__i + i][self.__j + j + 1], gameMap[self.__i + i][self.__j + j]

        self.__j += 1

分析:

该段代码的主要功能是处理俄罗斯方块游戏中方块的右移操作。以下是代码的主要功能概述:

判断是否可以右移:代码首先通过两个嵌套的循环遍历方块的每个格子,检查当前方块是否可以向右移动。它首先检查方块的右侧是否有足够的空间(即是否超出了地图的右边界),如果是,则不能右移,函数返回1。其次,它检查方块的右侧是否有其他方块占据,如果有,则不能右移,函数同样返回1。

执行右移操作:如果上述检查都通过,说明方块可以右移,代码将执行右移操作。通过另一个两个嵌套的循环遍历方块的每个格子,找到当前方块的每个格子,并将其与其右侧的对应格子交换位置。这实际上是将整个方块向右移动了一列。

更新方块位置:在成功执行右移操作后,代码更新方块的__j属性值,将其增加1,以反映方块在游戏地图中的新位置。

这个函数的目的是处理方块的右移逻辑,包括检查是否可以右移、执行右移操作以及更新方块的位置。它是俄罗斯方块游戏中控制方块移动的重要部分。与左移操作类似,但方向相反。

    def change(self):
        tMap = [[0 for j in range(4)] for i in range(4)]

        # 将所有方块顺时针旋转90度赋值到 tMap 中
        i = 0
        k = 3
        while i < 4:
            for j in range(4):
                if MAX_I > self.__i + j >= 0 and MAX_J > self.__j + k >= 0 and gameMap[self.__i + j][
                    self.__j + k] == 0 or \
                        gameMap[self.__i + j][self.__j + k] == self.__color:
                    tMap[j][k] = gameMap[self.__i + i][self.__j + j]

                else:
                    return

            i += 1
            k -= 1

        # 赋值
        for i in range(4):
            for j in range(4):
                gameMap[self.__i + i][self.__j + j] = tMap[i][j]

        playMyMusic('music/change.wav')

分析:

该段代码的主要功能是改变(旋转)当前方块的状态,具体来说是将方块顺时针旋转90度。以下是代码的主要功能概述:

创建临时地图:首先,代码创建了一个名为tMap的4x4二维列表,用于存储旋转后的方块状态。这个列表初始时所有元素都为0。

顺时针旋转方块:接下来,代码通过两个嵌套的循环来实现方块的顺时针旋转。外部循环控制旋转的行,内部循环控制旋转的列。在循环中,代码检查原始方块(在gameMap中)的每个格子,如果该格子为空(值为0)或者与当前方块的颜色相同,则将其值复制到tMap中相应的位置。如果遇到任何障碍物(即非空且颜色不同的格子),旋转操作将立即停止,并返回(不执行任何旋转)。

更新游戏地图:如果旋转操作成功完成(即没有遇到障碍物),代码将tMap中的新状态复制回gameMap,从而更新游戏地图中方块的位置和状态。

播放音效:最后,代码调用playMyMusic函数播放一个名为’change.wav’的音效文件,为玩家提供旋转操作的反馈。

总的来说,这个函数的作用是改变当前方块的方向,将其顺时针旋转90度,并更新游戏地图以反映这一变化。如果旋转过程中遇到障碍物,则不会进行任何更改。

    def deleteRow(self):
        # 找到有方块的最后一行
        lastRow = 0
        t = False
        for i in range(3, -1, -1):
            for j in range(4):
                if gameMap[self.__i + i][self.__j + j] == self.__color + 10:
                    lastRow = self.__i + i
                    t = True
                    break
            if t:
                break

        for i in range(lastRow, MAX_I - tetrisHeight - 1, -1):
            for j in range(MAX_J):
                if gameMap[i][j] == 0:
                    break
            else:
                global score
                score += 10
                playMyMusic('music/delete.wav')

                # 删除行
                gameMap.pop(i)
                gameMap.insert(0, [0 for j in range(MAX_J + 3)])

                # 增加等级
                global level
                level += score // 1000

                # 再次调用删除行函数操作删行
                self.deleteRow()

分析:

该段代码的主要功能是删除俄罗斯方块游戏中由玩家堆叠形成的完整行,并处理相应的得分和等级提升。以下是代码的主要功能概述:

找到有方块的最后一行:代码首先通过两个嵌套的循环遍历当前方块及其下方的行,查找最下方有方块的行(即最顶层的完整行)。它检查每个格子的值是否等于当前方块的颜色值加10(这是标记已停止方块的方式)。一旦找到这样的格子,就记录下其所在的行号,并跳出循环。

**删除完整行:**接下来,代码从最后一行开始向上遍历游戏地图。对于每一行,它检查该行是否所有格子都非空(即该行是一个完整行)。如果找到一个完整行,它将执行以下操作:

  • 增加玩家得分(通常增加10分)。
  • 播放一个音效文件(‘delete.wav’),为玩家提供反馈。
  • 从游戏地图中移除该完整行。这是通过将该行从列表中移除(gameMap.pop(i))并在列表的开头插入一个新行(所有格子都为空)来实现的。
  • 更新玩家的等级。这是通过将玩家的得分除以1000并向上取整来实现的,每1000分提升一个等级。

递归调用:在删除一行后,代码会再次调用自身(self.deleteRow()),以检查是否由于删除行而形成了新的完整行。这是必要的,因为在某些情况下,删除一行可能会导致上方的多行也成为完整行。递归调用将继续进行,直到没有新的完整行可以删除为止。

这个函数的目的是处理玩家堆叠形成的完整行,给予玩家相应的得分,并更新游戏状态,包括游戏地图、玩家得分和等级。它是俄罗斯方块游戏中的重要机制之一,用于管理游戏进程和玩家表现。

    def nextTetris(self):
        return self.__nextType, self.__nextColor


# 全局变量
screen = ''  # 屏幕
gameTetris = Tetris()

分析:

该方法用于返回下一个方块的类型和颜色。它返回两个私有成员变量:self.__nextTypeself.__nextColor。这两个变量通常在类的其他部分被设置,表示下一个将要出现的方块的类型(形状)和颜色。

此外,代码还定义了一个全局变量 screen,它被初始化为空字符串。这个变量可能用于表示游戏的屏幕或显示界面,但在这段代码中并没有进一步的使用或说明。

另一个全局变量 gameTetrisTetris 类的一个实例。Tetris 类可能包含了俄罗斯方块游戏的所有逻辑和状态信息,但由于代码中并没有给出 Tetris 类的具体实现,所以无法确定其具体的功能和结构。通常,这样的类会包含游戏的状态(如当前方块、下一个方块、游戏地图、得分等),以及控制游戏进程的方法(如开始新游戏、移动方块、旋转方块、删除行等)。

2.5 绘制游戏地图
# 绘制游戏地图
def drawMap():
    # 画上边框
    for i in range(MAX_I - 4):
        # 画右边
        myRect(screen, COLORS[2], [0, i * SIZE, SIZE, SIZE])
        # 画左边
        myRect(screen, COLORS[2], [(MAX_J + 1) * SIZE, i * SIZE, SIZE, SIZE])

    # 画下面
    for i in range(MAX_J + 2):
        myRect(screen, COLORS[2], [i * SIZE, (MAX_I - 4) * SIZE, SIZE, SIZE])

    # 给地图涂色
    for i in range(4, MAX_I):
        for j in range(MAX_J):
            t = gameMap[i][j] - 10 if gameMap[i][j] > 10 else gameMap[i][j]

            myRect(screen, COLORS[t], [(j + 1) * SIZE, (i - 4) * SIZE, SIZE, SIZE])

    # 文字内容,下一个方块
    drawMyText(screen, "下一块:", 305, 18, 15, (255, 255, 255))

    # 绘制下一块方块
    startX = 270
    startY = 30

    nextType, nextColor = gameTetris.nextTetris()

    # 显示下一个方块的背景
    pygame.draw.rect(screen, COLORS[5], [startX, startY, SIZE * 4, SIZE * 4], 1)
    mySize = SIZE * 0.8  # 缩小下一个方块大小

    # 根据形状,修改方块的位置(居中)
    if nextType == 0:
        startX += (SIZE * 4 - mySize) / 2
        startY += (SIZE * 4 - mySize * 4) / 2
    elif nextType == 2 or nextType == 3:
        startX += (SIZE * 4 - mySize * 2) / 2
        startY += (SIZE * 4 - mySize * 3) / 2
    elif nextType == 4 or nextType == 5 or nextType == 6:
        startX += (SIZE * 4 - mySize * 3) / 2
        startY += (SIZE * 4 - mySize * 2) / 2
    elif nextType == 1:
        startX += (SIZE * 4 - mySize * 4) / 2
        startY += (SIZE * 4 - mySize * 4) / 2

    # 绘制下一个方块
    for i in range(4):
        for j in range(4):
            # 绘制有图形地方
            if tetrises[nextType][i][j] == 1:
                # 根据不同的
                myRect(screen, COLORS[nextColor], [startX + j * mySize, startY + i * mySize, mySize, mySize])

    color = (255, 0, 0)
    # 绘制分数
    scoreText = "分数:{}".format(score)
    drawMyText(screen, scoreText, 300, 120, 15, color)

    # 等级
    drawMyText(screen, "等级:{}".format(level), 300, 140, 15, color)

    color = (255, 0, 255)
    # 绘制音乐
    textMusic = "音乐:"

    if isMusic:
        textMusic += "开"
    else:
        textMusic += '关'

    drawMyText(screen, textMusic, 300, 220, 15, color)

    # 绘制游戏暂停
    textPause = "暂停:"

    if isPause:
        textPause += "开"
    else:
        textPause += '关'

    drawMyText(screen, textPause, 300, 240, 15, color)


    # 绘制键值
    color = (130, 205, 255)
    drawMyText(screen, "↑ 旋转90度", 300, 300, 15, color)
    drawMyText(screen, "← 向左移动", 300, 320, 15, color)
    drawMyText(screen, "→ 向右移动", 300, 340, 15, color)
    drawMyText(screen, "↓ 快速向下", 300, 360, 15, color)

    # 绘制背景
    startY = 410
    color = (255, 255, 0)
    flower = "★"
    drawMyText(screen, flower, 300, startY + 0, 15, color)
    flower = "★★"
    drawMyText(screen, flower, 300, startY + 20, 15, color)
    flower = "★★★"
    drawMyText(screen, flower, 300, startY + 40, 15, color)

分析:

该段代码的主要功能是绘制俄罗斯方块游戏的游戏地图和界面上的其他元素。具体来说,它执行以下操作:

绘制游戏地图边框:首先,代码通过循环绘制了游戏地图的上、下、左、右四个边框。这些边框使用了一个特定的颜色(COLORS[2]),并且根据游戏地图的尺寸(MAX_IMAX_J)来确定位置和大小。

填充游戏地图:接下来,代码遍历游戏地图的每个格子,并根据格子的值(gameMap[i][j])来填充相应的颜色。如果格子的值大于10,则减去10来获取正确的颜色索引,因为游戏可能使用额外的值来表示特殊状态(如方块停止下落)。

绘制下一个方块:代码从gameTetris实例中获取下一个方块的类型(nextType)和颜色(nextColor)。然后,它绘制一个表示下一个方块的背景框,并根据下一个方块的形状调整其内部小方块的位置。不同的方块类型有不同的形状,因此代码通过条件语句来确定如何绘制每个小方块。

绘制文本信息:代码还绘制了界面上的文本信息,包括“下一块:”来提示玩家下一个方块即将出现,以及玩家的“分数”和“等级”。这些信息使用特定的颜色和字体大小绘制在屏幕上。

绘制音乐图标:最后,代码绘制了一个表示音乐的图标(尽管代码中并没有实际绘制图标的操作,只是预留了位置)。

2.6 游戏初始化
# 游戏初始化
def initGame():
    # 将地图倒数对大行全部赋值为-1
    for j in range(MAX_J):
        gameMap[MAX_I][j] = -1

    # 将地图倒数最大列全部赋值为-1
    for i in range(MAX_I):
        gameMap[i][MAX_J] = -1

    # 分数初始化
    score = 0

    # 加载背景音乐文件
    pygame.mixer.music.load('music/bgm.mp3')

    if isMusic:
        # 播放背景音乐,第一个参数为播放的次数(-1表示无限循环),第二个参数是设置播放的起点(单位为秒)
        pygame.mixer.music.play(-1, 0.0)

分析:

该段代码的主要功能是初始化俄罗斯方块游戏。具体来说,它执行了以下操作:

设置游戏地图的边缘:代码通过两个循环将游戏地图的边缘格子(即最底部和最右侧的格子)设置为-1。这通常表示这些格子不属于游戏区域,或者不可用于放置方块。

初始化分数:将玩家的分数(score)设置为0,表示游戏开始时玩家没有获得任何分数。

加载并播放背景音乐:代码使用pygame模块的mixer组件加载一个名为’bgm.mp3’的背景音乐文件。如果isMusic变量为True(表示允许播放音乐),则音乐将开始播放,并且设置为无限循环(-1表示循环播放),从音乐的开头(0.0秒处)开始播放。

这段代码是俄罗斯方块游戏初始化过程的一部分,确保游戏在开始时有正确的设置和配置,包括游戏地图的边缘定义、玩家分数的初始值,以及背景音乐的加载和播放。这些初始化步骤是游戏能够正常运行所必需的。

2.7 绘制有边框矩形
def myRect(screen, colorRect, pos, lineColor=COLORS[0], bold=1):
    pygame.draw.rect(screen, colorRect, pos)
    pygame.draw.rect(screen, lineColor, pos, bold)

分析:

该函数 myRect 的主要功能是在游戏屏幕(screen)上绘制一个矩形。它接受以下参数:

  • screen:这是一个pygame的Surface对象,通常代表游戏的主屏幕或窗口。
  • colorRect:这是矩形的填充颜色,通常是一个RGB元组,如 (255, 255, 255) 表示白色。
  • pos:这是一个包含矩形位置和大小的元组,格式为 (x, y, width, height)
  • lineColor:这是一个可选参数,用于指定矩形边框的颜色。如果没有提供,则默认为 COLORS[0]
  • bold:这是一个可选参数,用于指定矩形边框的宽度。如果没有提供,则默认为1。

函数内部调用了两次 pygame.draw.rect 方法。第一次调用绘制了填充了颜色的矩形,第二次调用绘制了矩形的边框。通过这种方式,myRect 函数能够在一个步骤中同时绘制矩形的填充和边框。

需要注意的是,pygame.draw.rect 方法的第四个参数通常用于指定线条的粗细(边框宽度)。在这个函数中,当 bold 参数被传递时,它会被用作 pygame.draw.rect 方法的第四个参数。如果 bold 参数未被传递或设置为1,则边框宽度将默认为1。

2.8 绘制我的文字
# 绘制我的文字
def drawMyText(screen, text, x, y, bold, fColor, bColor=None):
    # 通过字体文件获得字体对象
    fontObj = pygame.font.Font('font/SIMYOU.TTF', bold)

    # 配置要显示的文字
    textSurfaceObj = fontObj.render(text, False, fColor, bColor)

    # 获得要显示的对象的rect
    textRectObj = textSurfaceObj.get_rect()

    # 设置显示对象的坐标
    textRectObj.center = (x, y)

    # 绘制字体
    screen.blit(textSurfaceObj, textRectObj)

分析:

获取字体对象:使用pygame.font.Font函数和一个指定的字体文件(在这里是’font/SIMYOU.TTF’)以及字体大小(由bold参数指定)来创建一个字体对象。

渲染文本:使用字体对象的render方法来创建一个文本Surface对象。这个方法需要文本字符串、一个布尔值(在这里是False,表示文本不是抗锯齿的)、前景色和可选的背景色。

获取文本矩形:通过调用文本Surface对象的get_rect方法来获取一个矩形对象,这个矩形代表了文本在屏幕上占据的空间。

设置文本坐标:将文本矩形的中心坐标设置为函数参数中指定的xy坐标。

绘制文本:最后,使用screen.blit方法将文本Surface对象绘制到屏幕上的指定位置。

2.9 游戏主体
def my_game():
    # 得到屏幕
    global screen, isMusic, isPause
    screen = pygame.display.set_mode((350, 465))

    # 设置标题
    pygame.display.set_caption('俄罗斯方块')

    # 初始化游戏
    initGame()

    # 用于控制下落速度
    count = 0

    while True:

        if count == 3 + level * 2:
            if not isPause:  # 只有暂停是 False 才能下移
                if gameTetris.moveDown() == 1:
                    gameTetris.stopTetris()
                    gameTetris.createTetris()

            count = 0

        # 事件判断
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                # 停止播放背景音乐
                pygame.mixer.music.stop()

                pygame.quit()
                exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                # 控制音乐开关
                if 270 < event.pos[0] < 330 and 210 < event.pos[1] < 225:
                    # 处理音乐开关
                    if isMusic:
                        # 停止播放背景音乐
                        pygame.mixer.music.stop()
                    else:
                        # 播放背景音乐,第一个参数为播放的次数(-1表示无限循环),第二个参数是设置播放的起点(单位为秒)
                        pygame.mixer.music.play(-1, 0.0)

                    isMusic = not isMusic

                # 处理游戏暂停开关
                if 270 < event.pos[0] < 327 and 233 < event.pos[1] < 248:
                    isPause = not isPause

                    if isPause:
                        pygame.display.set_caption('俄罗斯方块:已暂停')
                    else:
                        pygame.display.set_caption('俄罗斯方块')

            elif event.type == pygame.KEYDOWN:
                if event.key == K_UP:
                    gameTetris.change()

        keyPressList = pygame.key.get_pressed()

        if keyPressList[K_DOWN]:
            gameTetris.moveDown()
        elif keyPressList[K_LEFT]:
            gameTetris.moveLeft()
        elif keyPressList[K_RIGHT]:
            gameTetris.moveRight()

        screen.fill((0, 0, 0))
        drawMap()
        pygame.display.update()
        count += 1

        pygame.time.Clock().tick(10)

分析:

该函数 my_game 是俄罗斯方块游戏的主函数,它负责初始化游戏、处理用户输入和事件、更新游戏状态以及渲染游戏画面。以下是该函数的主要功能:

初始化游戏:首先,它设置了一个全局的屏幕对象 screen 和一些全局变量(如 isMusicisPause)。然后,它调用 initGame 函数来初始化游戏,包括设置游戏地图的边缘、初始化分数以及加载并可能播放背景音乐。

控制下落速度:通过一个计数器 count 来控制方块的下落速度。当计数器达到一定的值时(由当前游戏级别 level 决定),如果游戏没有暂停(isPauseFalse),则尝试将当前方块下移一格。如果下移成功,则停止当前方块的下落并创建一个新的方块。

**事件处理:**函数使用一个循环来处理pygame事件。这些事件可能包括用户点击关闭按钮(退出游戏)、点击鼠标(控制音乐的播放和暂停以及游戏的暂停和继续)、以及按下键盘键(旋转方块)。

  • 当用户点击关闭按钮时,停止播放背景音乐并退出游戏。
  • 当用户在特定的屏幕区域内点击鼠标时,切换音乐的播放状态或游戏的暂停状态。
  • 当用户按下键盘上的上箭头键时,旋转当前方块。

键盘输入处理:函数还检查是否有键盘键被按下,并据此移动方块。如果下箭头键被持续按下,方块会持续下移;如果左或右箭头键被按下,方块会向左或向右移动。

渲染游戏画面:最后,函数使用黑色填充屏幕,并调用 drawMap 函数来绘制游戏地图和方块。这一步通常在每次循环的末尾进行,以确保游戏画面能够实时更新。

2.10 主程序运行
if __name__ == '__main__':
    my_game()

详细分析一下:

在Python中,if __name__ == '__main__': 是一个常见的代码块,用于判断当前脚本是否作为主程序运行。如果当前脚本是作为主程序直接运行的,而不是被其他脚本导入作为一个模块,那么 __name__ 这个内置变量就会被设置为 '__main__'

在你提供的代码片段中,if __name__ == '__main__': 这一行之后紧跟着调用了 my_game() 函数。这意味着,只有当这个脚本被直接运行时,my_game() 函数才会被执行。如果这个脚本被其他脚本导入作为一个模块,那么 my_game() 函数将不会自动执行。

这样做的好处是,你可以在一个文件中既定义函数和类(用于在其他脚本中导入和使用),又包含一些只在当前脚本直接运行时才需要执行的代码(比如启动游戏的主函数)。

总结来说,if __name__ == '__main__': 这一行用于区分直接运行和模块导入两种情况,并据此决定是否执行某些代码。在你提供的代码中,它确保了 my_game() 函数只有在该脚本被直接运行时才会被执行。

3.运行效果

4.注意事项

1.所有的代码放到同一个py文件中

2.在数据可视化过程中,难免会需要导入不同的库,这里建议使用WIN+R打开命令提示符,并使用国内镜像安装库(下载快),比如安装wordcloud库是,使用下列代码:

pip install wordcloud -i https://pypi.tuna.tsinghua.edu.cn/simple/

安装库的时候,建议更新一下你的pip库,命令:

python -m pip install --upgrade pip

游戏窗口的创建和初始化:你需要使用Pygame库创建一个游戏窗口,并设置其宽度、高度、标题等属性。你还需要初始化一些Pygame模块,如pygame.init()来初始化所有导入的Pygame模块。

游戏循环:游戏的核心是一个循环,通常称为游戏主循环或事件循环。在这个循环中,你需要处理用户输入(如键盘按键、鼠标点击等)、更新游戏状态(如方块的位置、得分等)和绘制游戏界面。

方块的绘制和移动:你需要定义方块的形状和颜色,并在游戏窗口中绘制它们。你还需要实现方块的移动功能,包括旋转、左右移动和下落。你可能需要使用键盘事件来捕捉用户的输入,并根据输入更新方块的位置。

消除行和得分:当方块下落并填满一行时,你需要实现消除行的功能,并相应地更新得分。这可能需要你检查每一行是否已经填满,如果是,则消除该行并增加得分。

游戏结束条件:你需要设置游戏结束的条件,如当方块堆积到游戏窗口的顶部时,游戏结束。在游戏结束时,你可以显示一条消息或弹出一个对话框来通知玩家。

5.附录源码

import pygame
from pygame.locals import *
from sys import exit
import random

# 使用pygame.init()初始化pygame库
pygame.init()

# 常量
MAX_I = 34
MAX_J = 15
# 定义地图的最大行数和列数
SIZE = 15
# 方块的大小

COLORS = [(0, 0, 0), (255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0), (255, 255, 255)]
# 一个颜色列表,用于表示不同的方块
gameMap = [[0 for j in range(MAX_J + 3)] for i in range(MAX_I + 3)]
# 一个二维列表,代表游戏地图。初始化为全0,表示没有方块。
tetrisHeight = 0
# 记录当前塔的高度,即已放下的方块行数

tetrises = [
    [
        [1, 0, 0, 0],
        [1, 0, 0, 0],
        [1, 0, 0, 0],
        [1, 0, 0, 0]
    ],
    [
        [0, 0, 0, 0],
        [0, 1, 1, 0],
        [0, 1, 1, 0],
        [0, 0, 0, 0]
    ],
    [
        [1, 0, 0, 0],
        [1, 1, 0, 0],
        [0, 1, 0, 0],
        [0, 0, 0, 0]
    ],
    [
        [0, 1, 0, 0],
        [1, 1, 0, 0],
        [1, 0, 0, 0],
        [0, 0, 0, 0]
    ],
    [
        [0, 1, 0, 0],
        [1, 1, 1, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]
    ],
    [
        [1, 0, 0, 0],
        [1, 1, 1, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]
    ],
    [
        [0, 0, 1, 0],
        [1, 1, 1, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]
    ]
]
# 一个列表,包含7种不同的基本方块形状。每个形状都是一个二维列表,表示方块的各个部分。
# 分数
score = 0
# 等级
level = 1
# 音乐开关
isMusic = True
# 游戏暂停
isPause = False


# 播放音乐
def playMyMusic(src):
    if isMusic:
        sound = pygame.mixer.Sound(src)
        sound.play()


# 方块类
class Tetris:
    __i = 0
    __j = 0
    __color = 0
    __nextColor = 0
    __nextType = 0

    def __init__(self):
        self.__nextColor = random.randint(0, 3) + 1  # 一共四种颜色
        self.__nextType = random.randint(0, 6)  # 一共七种类型
        self.createTetris()

    def createTetris(self):
        # 根据类型调整一下快出现的位置
        if self.__nextType == 0:
            self.__i = 1
            self.__j = 7
        else:
            self.__i = 2
            self.__j = 6
        self.__color = self.__nextColor

        # 根据方块模板,放置整个到地图
        for i in range(4):
            for j in range(4):
                if tetrises[self.__nextType][i][j] == 1:
                    if gameMap[self.__i + i][self.__j + j] == 0:
                        gameMap[self.__i + i][self.__j + j] = self.__color
                    else:
                        print('游戏失败!')
                        exit()
                        return -1

        # 产生下一种类型和颜色
        self.__nextColor = random.randint(0, 3) + 1  # 一共四种颜色
        self.__nextType = random.randint(0, 6)  # 一共七种类型

        playMyMusic('music/get.wav')

    def moveDown(self):
        global gameMap

        # 判断是否可以下移
        for j in range(4):
            for i in range(3, -1, -1):
                if gameMap[self.__i + i][self.__j + j] == self.__color:
                    # 判断是否到底
                    if self.__i + i + 1 > MAX_I:
                        return 1

                    # 判断前面是否有东西
                    if gameMap[self.__i + i + 1][self.__j + j] != 0:
                        return 1

                    break

        # 下移
        for j in range(4):
            for i in range(3, -1, -1):
                if gameMap[self.__i + i][self.__j + j] == self.__color:
                    gameMap[self.__i + i][self.__j + j], gameMap[self.__i + i + 1][self.__j + j] = \
                        gameMap[self.__i + i + 1][self.__j + j], gameMap[self.__i + i][self.__j + j]

        self.__i += 1

    def stopTetris(self):
        global tetrisHeight

        flag = True

        for i in range(4):
            for j in range(4):
                if gameMap[self.__i + i][self.__j + j] == self.__color:
                    gameMap[self.__i + i][self.__j + j] += 10

                    # 找到第一个颜色方块
                    if flag:
                        tetrisHeight = MAX_I - self.__i if tetrisHeight < MAX_I - self.__i else tetrisHeight
                        flag = False

        self.deleteRow()

    def moveLeft(self):
        # 判断是否能够左移
        for i in range(4):
            for j in range(4):
                if gameMap[self.__i + i][self.__j + j] == self.__color:
                    if self.__j + j - 1 < 0:
                        return 1
                    if gameMap[self.__i + i][self.__j + j - 1] != 0:
                        return 1

                    break

        # 左移
        for i in range(4):
            for j in range(4):
                if gameMap[self.__i + i][self.__j + j] == self.__color:
                    gameMap[self.__i + i][self.__j + j], gameMap[self.__i + i][self.__j + j - 1] = \
                        gameMap[self.__i + i][self.__j + j - 1], gameMap[self.__i + i][self.__j + j]

        self.__j -= 1

    def moveRight(self):
        # 判断是否能右移
        for i in range(4):
            for j in range(3, -1, -1):
                if gameMap[self.__i + i][self.__j + j] == self.__color:
                    if self.__j + j + 1 >= MAX_J:
                        return 1
                    if gameMap[self.__i + i][self.__j + j + 1] != 0:
                        return 1

                    break

        # 右移
        for i in range(4):
            for j in range(3, -1, -1):
                if gameMap[self.__i + i][self.__j + j] == self.__color:
                    gameMap[self.__i + i][self.__j + j], gameMap[self.__i + i][self.__j + j + 1] = \
                        gameMap[self.__i + i][self.__j + j + 1], gameMap[self.__i + i][self.__j + j]

        self.__j += 1

    def change(self):
        tMap = [[0 for j in range(4)] for i in range(4)]

        # 将所有方块顺时针旋转90度赋值到 tMap 中
        i = 0
        k = 3
        while i < 4:
            for j in range(4):
                if MAX_I > self.__i + j >= 0 and MAX_J > self.__j + k >= 0 and gameMap[self.__i + j][
                    self.__j + k] == 0 or \
                        gameMap[self.__i + j][self.__j + k] == self.__color:
                    tMap[j][k] = gameMap[self.__i + i][self.__j + j]

                else:
                    return

            i += 1
            k -= 1

        # 赋值
        for i in range(4):
            for j in range(4):
                gameMap[self.__i + i][self.__j + j] = tMap[i][j]

        playMyMusic('music/change.wav')

    def deleteRow(self):
        # 找到有方块的最后一行
        lastRow = 0
        t = False
        for i in range(3, -1, -1):
            for j in range(4):
                if gameMap[self.__i + i][self.__j + j] == self.__color + 10:
                    lastRow = self.__i + i
                    t = True
                    break
            if t:
                break

        for i in range(lastRow, MAX_I - tetrisHeight - 1, -1):
            for j in range(MAX_J):
                if gameMap[i][j] == 0:
                    break
            else:
                global score
                score += 10
                playMyMusic('music/delete.wav')

                # 删除行
                gameMap.pop(i)
                gameMap.insert(0, [0 for j in range(MAX_J + 3)])

                # 增加等级
                global level
                level += score // 1000

                # 再次调用删除行函数操作删行
                self.deleteRow()

    def nextTetris(self):
        return self.__nextType, self.__nextColor


# 全局变量
screen = ''  # 屏幕
gameTetris = Tetris()


# 绘制游戏地图
def drawMap():
    # 画上边框
    for i in range(MAX_I - 4):
        # 画右边
        myRect(screen, COLORS[2], [0, i * SIZE, SIZE, SIZE])
        # 画左边
        myRect(screen, COLORS[2], [(MAX_J + 1) * SIZE, i * SIZE, SIZE, SIZE])

    # 画下面
    for i in range(MAX_J + 2):
        myRect(screen, COLORS[2], [i * SIZE, (MAX_I - 4) * SIZE, SIZE, SIZE])

    # 给地图涂色
    for i in range(4, MAX_I):
        for j in range(MAX_J):
            t = gameMap[i][j] - 10 if gameMap[i][j] > 10 else gameMap[i][j]

            myRect(screen, COLORS[t], [(j + 1) * SIZE, (i - 4) * SIZE, SIZE, SIZE])

    # 文字内容,下一个方块
    drawMyText(screen, "下一块:", 305, 18, 15, (255, 255, 255))

    # 绘制下一块方块
    startX = 270
    startY = 30

    nextType, nextColor = gameTetris.nextTetris()

    # 显示下一个方块的背景
    pygame.draw.rect(screen, COLORS[5], [startX, startY, SIZE * 4, SIZE * 4], 1)
    mySize = SIZE * 0.8  # 缩小下一个方块大小

    # 根据形状,修改方块的位置(居中)
    if nextType == 0:
        startX += (SIZE * 4 - mySize) / 2
        startY += (SIZE * 4 - mySize * 4) / 2
    elif nextType == 2 or nextType == 3:
        startX += (SIZE * 4 - mySize * 2) / 2
        startY += (SIZE * 4 - mySize * 3) / 2
    elif nextType == 4 or nextType == 5 or nextType == 6:
        startX += (SIZE * 4 - mySize * 3) / 2
        startY += (SIZE * 4 - mySize * 2) / 2
    elif nextType == 1:
        startX += (SIZE * 4 - mySize * 4) / 2
        startY += (SIZE * 4 - mySize * 4) / 2

    # 绘制下一个方块
    for i in range(4):
        for j in range(4):
            # 绘制有图形地方
            if tetrises[nextType][i][j] == 1:
                # 根据不同的
                myRect(screen, COLORS[nextColor], [startX + j * mySize, startY + i * mySize, mySize, mySize])

    color = (255, 0, 0)
    # 绘制分数
    scoreText = "分数:{}".format(score)
    drawMyText(screen, scoreText, 300, 120, 15, color)

    # 等级
    drawMyText(screen, "等级:{}".format(level), 300, 140, 15, color)

    color = (255, 0, 255)
    # 绘制音乐
    textMusic = "音乐:"

    if isMusic:
        textMusic += "开"
    else:
        textMusic += '关'

    drawMyText(screen, textMusic, 300, 220, 15, color)

    # 绘制游戏暂停
    textPause = "暂停:"

    if isPause:
        textPause += "开"
    else:
        textPause += '关'

    drawMyText(screen, textPause, 300, 240, 15, color)


    # 绘制键值
    color = (130, 205, 255)
    drawMyText(screen, "↑ 旋转90度", 300, 300, 15, color)
    drawMyText(screen, "← 向左移动", 300, 320, 15, color)
    drawMyText(screen, "→ 向右移动", 300, 340, 15, color)
    drawMyText(screen, "↓ 快速向下", 300, 360, 15, color)

    # 绘制背景
    startY = 410
    color = (255, 255, 0)
    flower = "★"
    drawMyText(screen, flower, 300, startY + 0, 15, color)
    flower = "★★"
    drawMyText(screen, flower, 300, startY + 20, 15, color)
    flower = "★★★"
    drawMyText(screen, flower, 300, startY + 40, 15, color)


# 游戏初始化
def initGame():
    # 将地图倒数对大行全部赋值为-1
    for j in range(MAX_J):
        gameMap[MAX_I][j] = -1

    # 将地图倒数最大列全部赋值为-1
    for i in range(MAX_I):
        gameMap[i][MAX_J] = -1

    # 分数初始化
    score = 0

    # 加载背景音乐文件
    pygame.mixer.music.load('music/bgm.mp3')

    if isMusic:
        # 播放背景音乐,第一个参数为播放的次数(-1表示无限循环),第二个参数是设置播放的起点(单位为秒)
        pygame.mixer.music.play(-1, 0.0)


# 绘制有边框矩形
def myRect(screen, colorRect, pos, lineColor=COLORS[0], bold=1):
    pygame.draw.rect(screen, colorRect, pos)
    pygame.draw.rect(screen, lineColor, pos, bold)


# 绘制我的文字
def drawMyText(screen, text, x, y, bold, fColor, bColor=None):
    # 通过字体文件获得字体对象
    fontObj = pygame.font.Font('font/SIMYOU.TTF', bold)

    # 配置要显示的文字
    textSurfaceObj = fontObj.render(text, False, fColor, bColor)

    # 获得要显示的对象的rect
    textRectObj = textSurfaceObj.get_rect()

    # 设置显示对象的坐标
    textRectObj.center = (x, y)

    # 绘制字体
    screen.blit(textSurfaceObj, textRectObj)


# 游戏主体
def my_game():
    # 得到屏幕
    global screen, isMusic, isPause
    screen = pygame.display.set_mode((350, 465))

    # 设置标题
    pygame.display.set_caption('俄罗斯方块')

    # 初始化游戏
    initGame()

    # 用于控制下落速度
    count = 0

    while True:

        if count == 3 + level * 2:
            if not isPause:  # 只有暂停是 False 才能下移
                if gameTetris.moveDown() == 1:
                    gameTetris.stopTetris()
                    gameTetris.createTetris()

            count = 0

        # 事件判断
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                # 停止播放背景音乐
                pygame.mixer.music.stop()

                pygame.quit()
                exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                # 控制音乐开关
                if 270 < event.pos[0] < 330 and 210 < event.pos[1] < 225:
                    # 处理音乐开关
                    if isMusic:
                        # 停止播放背景音乐
                        pygame.mixer.music.stop()
                    else:
                        # 播放背景音乐,第一个参数为播放的次数(-1表示无限循环),第二个参数是设置播放的起点(单位为秒)
                        pygame.mixer.music.play(-1, 0.0)

                    isMusic = not isMusic

                # 处理游戏暂停开关
                if 270 < event.pos[0] < 327 and 233 < event.pos[1] < 248:
                    isPause = not isPause

                    if isPause:
                        pygame.display.set_caption('俄罗斯方块:已暂停')
                    else:
                        pygame.display.set_caption('俄罗斯方块')

            elif event.type == pygame.KEYDOWN:
                if event.key == K_UP:
                    gameTetris.change()

        keyPressList = pygame.key.get_pressed()

        if keyPressList[K_DOWN]:
            gameTetris.moveDown()
        elif keyPressList[K_LEFT]:
            gameTetris.moveLeft()
        elif keyPressList[K_RIGHT]:
            gameTetris.moveRight()

        screen.fill((0, 0, 0))
        drawMap()
        pygame.display.update()
        count += 1

        pygame.time.Clock().tick(10)


if __name__ == '__main__':
    my_game()

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

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

相关文章

go使用grpc编辑器 windows

先看最后效果&#xff1a; 当我执行 protoc --go_out. proto.proto 会生成proto.pb.go文件&#xff0c;主要存储的是封装好的结构体 执行 protoc --go-grpc_out. proto.proto 会生成对应的方法 那么现在提供解决方案&#xff1a; https://github.com/protocolbuffers…

kafka的架构

一、架构图 Broker&#xff1a;一台 kafka 服务器就是一个 broker。一个kakfa集群由多个 broker 组成。一个 broker 可以容纳多个 topic。 Producer&#xff1a;消息生产者&#xff0c;就是向 kafka broker 发消息的客户端 Consumer&#xff1a;消息消费者&#xff0c;向 kafk…

软考中级系统集成项目管理工程师备考笔记

目录 一&#xff0c;通用内容 &#xff08;一&#xff09;信息与信息化 1.1&#xff0c;信息 信息基本概念 信息的传输模型 信息的质量属性 1.2&#xff0c;信息系统 信息系统的基本概念 信息系统定义 信息系统集成 1.3&#xff0c;信息化 信息化层次 信息化的核心…

Prometheus在金融行业信息系统运维管理中的应用:实践与案例分析

Prometheus在金融行业信息系统运维管理中的应用&#xff1a;实践与案例分析 Prometheus是一款开源的监控系统和时序数据库&#xff0c;被广泛应用于各种行业的运维管理中&#xff0c;特别是在金融行业。它具有强大的数据采集和分析能力&#xff0c;能够实时监控系统的性能和状…

华为eNSP模拟器安装详细步骤

安装准备 安装eNSP需要先安装三个依赖软件才能运行&#xff0c;分别是VirtualBox、WinPcap、Wireshark 下载地址如下 eNSP&#xff1a;http://cloud.rsecc.cn/softlink/eNSP%20V100R003C00SPC100%20Setup.exe VirtualBox&#xff1a;http://cloud.rsecc.cn/softlink/Virtua…

Steam页面打不开?steam显示当前游戏不可用是怎么回事

Steam是全球最大的游戏综合发行平台&#xff0c;每年为无数玩家呈现了多款精彩游戏&#xff0c;不过由于网络问题或其他异常因素影响&#xff0c;有很多玩家会在访问steam或steam的游戏商品页时&#xff0c;遇到Steam提示当前游戏在您平台不可用、打不开游戏页面的情况&#xf…

自动化测试报告pytest-html样式美化

最近我将 pytest-html 样式优化了 一版 先看优化前&#xff1a; 优化后&#xff1a; 优化内容包括&#xff1a; 删除部分多余字段新增echart图表部分字体大小、行间距、颜色做了美化调整运行环境信息移至报告最后部分字段做了汉化处理&#xff08;没全部翻译是因为&#xf…

七天速通javaSE:第七天 面向对象:封装继承与多态

文章目录 前言一、封装1. 属性私有2. get&#xff0c;set3. 修饰符的可访问性4. 特点总结 二、继承1. 子承父业&#xff1a;extends2. 区分父子&#xff1a;super2.1 属性2.2 方法重写 三、多态&#xff08;不同类继承同一个类&#xff09; 前言 一、封装 概念&#xff1a;封装…

等保测评应该选择什么样的SSL证书

选择适合等保测评的SSL证书&#xff0c;需考虑证书的加密强度、认证机制以及是否满足国家相关的密码技术要求 1、证书类型&#xff1a;应选择符合国家或行业标准的SSL证书&#xff0c;这些证书通常采用RSA、DSA或ECC等国际认可的加密算法。同时&#xff0c;考虑到国内特定的合规…

IP地址修改方法攻略:类型、步骤与注意事项

在数字化时代&#xff0c;IP地址作为网络设备的唯一标识符&#xff0c;其重要性不言而喻。然而&#xff0c;在某些特定场景下&#xff0c;如保护个人隐私、绕过网络限制或实现特定网络访问需求&#xff0c;修改IP地址就显得尤为关键。本文将详细介绍IP地址修改方法有哪几种类型…

13. Java 生产者与消费者案例

1. 前言 本节内容是通过之前学习的 synchronized 关键字&#xff0c;实现多线程并发编程中最经典的生产者与消费者模式&#xff0c;这是本节课程的核心内容&#xff0c;所有的知识点都是围绕这一经典模型展开的。本节有如下知识点&#xff1a; 生产者与消费者模型介绍&#x…

昇思25天学习打卡营第13天 | SSD目标检测

模型简介 SSD&#xff0c;全称Single Shot MultiBox Detector&#xff0c;是Wei Liu在ECCV 2016上提出的一种目标检测算法。使用Nvidia Titan X在VOC 2007测试集上&#xff0c;SSD对于输入尺寸300x300的网络&#xff0c;达到74.3%mAP(mean Average Precision)以及59FPS&#x…

周界入侵自动监测摄像机

当今&#xff0c;随着科技的快速发展&#xff0c;周界入侵自动监测摄像机作为安全监控领域的重要创新&#xff0c;正逐渐成为各类场所安全防范的核心设备。这种摄像机以其先进的监测和预警功能&#xff0c;有效提升了安全管理的效率和实时响应能力&#xff0c;被广泛应用于各类…

电子看板,帮助工厂实现数字化管理

在数字化浪潮的推动下&#xff0c;制造业正经历着深刻的变革&#xff0c;数字工厂成为了行业发展的新趋势。而生产管理看板作为一种重要的管理工具&#xff0c;在提升数字工厂管理效率方面发挥着关键作用。 生产管理看板通过实时数据的展示&#xff0c;为数字工厂提供了清晰的全…

【微信小程序开发实战项目】——如何制作一个属于自己的花店微信小程序(1)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

Windows10录屏,教你3个方法,简单快速录屏

“我的电脑系统是Windows10的系统&#xff0c;今晚要进行线上开会&#xff0c;但我实在有事没办法参加会议&#xff0c;想把会议的内容录制下来方便我后续观看。但却找不到电脑录屏功能在哪里打开&#xff1f;求助一下&#xff0c;谁能帮帮我&#xff1f;” 在数字化时代&…

软考 有向图 数据库之关系模式范式

假设有一个关系 R(A, B, C, D)&#xff0c;并且已知以下函数依赖&#xff1a; A → B B → C BC → D 求候选键? 求候选码? 候选键/候选码 是同一个概念. 数据库范式也分为1NF,2NF,3NF,BCNF,4NF,5NF。 https://cloud.tencent.com/developer/article/2055118 2NF在1NF的基础…

如何定制化 ListView 界面

&#x1f604;作者简介&#xff1a; 小曾同学.com,一个致力于测试开发的博主⛽️&#xff0c;主要职责&#xff1a;测试开发、CI/CD 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起进步。 &#x1f60a; 座右铭&#xff1a;不…

PostgreSQL主从同步

目录 一、主从复制原理 二、配置主数据库 2.1 创建同步账号 2.2 配置同步账号访问控制 2.3 设置同步参数 3.4 重启主数据库 三、配置从数据库 3.1 停止从库 3.2 清空从库数据文件 3.3 拉取主库数据文件 3.4 配置从库同步参数 3.5 启动从库 四、测试主从 4.1在主库…

33 包装器

c11 也叫适配器。c中的function本质是一个类模板&#xff0c;也是一个包装器 为什么需要fuction呢&#xff1f; 当一个类型既可以是函数指针&#xff0c;也可以是仿函数和lambda比倒是&#xff0c;函数指针的类型不好理解&#xff0c;仿函数写起来麻烦&#xff0c;lambda无法拿…