俄罗斯方块游戏代码

article/2025/9/25 2:25:25

♥️作者:小刘在C站

♥️个人主页:小刘主页

♥️每天分享云计算网络运维课堂笔记,努力不一定有回报,但一定会有收获加油!一起努力,共赴美好人生!

♥️夕阳下,是最美的,绽放,愿所有的美好,再疫情结束后如约而至。

目录

一.什么是python

二.游戏代码效果呈现

三.游戏主代码二

1.shapes

2.misc

3.gameboard

4.__init__

5.README


一.什么是python

Python由荷兰数学和计算机科学研究学会的吉多·范罗苏姆于1990年代初设计,作为一门叫做ABC语言的替代品。   Python提供了高效的高级数据结构,还能简单有效地面向对象编程。Python语法和动态类型,以及解释型语言的本质,使它成为多数平台上写脚本和快速开发应用的编程语言, [ 随着版本的不断更新和语言新功能的添加,逐渐被用于独立的、大型项目的开发。

Python解释器易于扩展,可以使用C语言或C++(或者其他可以通过C调用的语言)扩展新的功能和数据类型。Python也可用于可定制化软件中的扩展程序语言。Python丰富的标准库,提供了适用于各个主要系统平台的源码或机器码

二.游戏代码效果呈现

 三.游戏主代码

'''

'''
import os
import sys
import random
from modules import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *


'''定义俄罗斯方块游戏类'''
class TetrisGame(QMainWindow):
    def __init__(self, parent=None):
        super(TetrisGame, self).__init__(parent)
        # 是否暂停ing
        self.is_paused = False
        # 是否开始ing
        self.is_started = False
        self.initUI()
    '''界面初始化'''
    def initUI(self):
        # icon
        self.setWindowIcon(QIcon(os.path.join(os.getcwd(), 'resources/icon.jpg')))
        # 块大小
        self.grid_size = 22
        # 游戏帧率
        self.fps = 200
        self.timer = QBasicTimer()
        # 焦点
        self.setFocusPolicy(Qt.StrongFocus)
        # 水平布局
        layout_horizontal = QHBoxLayout()
        self.inner_board = InnerBoard()
        self.external_board = ExternalBoard(self, self.grid_size, self.inner_board)
        layout_horizontal.addWidget(self.external_board)
        self.side_panel = SidePanel(self, self.grid_size, self.inner_board)
        layout_horizontal.addWidget(self.side_panel)
        self.status_bar = self.statusBar()
        self.external_board.score_signal[str].connect(self.status_bar.showMessage)
        self.start()
        self.center()
        self.setWindowTitle('俄罗斯方块儿 —— 源码基地:959755565')
        self.show()
        self.setFixedSize(self.external_board.width() + self.side_panel.width(), self.side_panel.height() + self.status_bar.height())
    '''游戏界面移动到屏幕中间'''
    def center(self):
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()
        self.move((screen.width() - size.width()) // 2, (screen.height() - size.height()) // 2)
    '''更新界面'''
    def updateWindow(self):
        self.external_board.updateData()
        self.side_panel.updateData()
        self.update()
    '''开始'''
    def start(self):
        if self.is_started:
            return
        self.is_started = True
        self.inner_board.createNewTetris()
        self.timer.start(self.fps, self)
    '''暂停/不暂停'''
    def pause(self):
        if not self.is_started:
            return
        self.is_paused = not self.is_paused
        if self.is_paused:
            self.timer.stop()
            self.external_board.score_signal.emit('Paused')
        else:
            self.timer.start(self.fps, self)
        self.updateWindow()
    '''计时器事件'''
    def timerEvent(self, event):
        if event.timerId() == self.timer.timerId():
            removed_lines = self.inner_board.moveDown()
            self.external_board.score += removed_lines
            self.updateWindow()
        else:
            super(TetrisGame, self).timerEvent(event)
    '''按键事件'''
    def keyPressEvent(self, event):
        if not self.is_started or self.inner_board.current_tetris == tetrisShape().shape_empty:
            super(TetrisGame, self).keyPressEvent(event)
            return
        key = event.key()
        # P键暂停
        if key == Qt.Key_P:
            self.pause()
            return
        if self.is_paused:
            return
        # 向左
        elif key == Qt.Key_Left:
            self.inner_board.moveLeft()
        # 向右
        elif key == Qt.Key_Right:
            self.inner_board.moveRight()
        # 旋转
        elif key == Qt.Key_Up:
            self.inner_board.rotateAnticlockwise()
        # 快速坠落
        elif key == Qt.Key_Space:
            self.external_board.score += self.inner_board.dropDown()
        else:
            super(TetrisGame, self).keyPressEvent(event)
        self.updateWindow()


'''run'''
if __name__ == '__main__':
    app = QApplication([])
    tetris = TetrisGame()
    sys.exit(app.exec_())

三.游戏主代码二

1.shapes

'''
Function:
    定义俄罗斯方块的形状

'''
'''定义一个俄罗斯方块的形状'''
class tetrisShape():
    def __init__(self, shape=0):
        # 空块
        self.shape_empty = 0
        # 一字型块
        self.shape_I = 1
        # L型块
        self.shape_L = 2
        # 向左的L型块
        self.shape_J = 3
        # T型块
        self.shape_T = 4
        # 田字型块
        self.shape_O = 5
        # 反向Z型块
        self.shape_S = 6
        # Z型块
        self.shape_Z = 7
        # 每种块包含的四个小方块相对坐标分布
        self.shapes_relative_coords = [
            [[0, 0], [0, 0], [0, 0], [0, 0]],
            [[0, -1], [0, 0], [0, 1], [0, 2]],
            [[0, -1], [0, 0], [0, 1], [1, 1]],
            [[0, -1], [0, 0], [0, 1], [-1, 1]],
            [[0, -1], [0, 0], [0, 1], [1, 0]],
            [[0, 0], [0, -1], [1, 0], [1, -1]],
            [[0, 0], [0, -1], [-1, 0], [1, -1]],
            [[0, 0], [0, -1], [1, 0], [-1, -1]]
        ]
        self.shape = shape
        self.relative_coords = self.shapes_relative_coords[self.shape]
    '''获得该形状当前旋转状态的四个小方块的相对坐标分布'''
    def getRotatedRelativeCoords(self, direction):
        # 初始分布
        if direction == 0 or self.shape == self.shape_O:
            return self.relative_coords
        # 逆时针旋转90度
        if direction == 1:
            return [[-y, x] for x, y in self.relative_coords]
        # 逆时针旋转180度
        if direction == 2:
            if self.shape in [self.shape_I, self.shape_Z, self.shape_S]:
                return self.relative_coords
            else:
                return [[-x, -y] for x, y in self.relative_coords]
        # 逆时针旋转270度
        if direction == 3:
            if self.shape in [self.shape_I, self.shape_Z, self.shape_S]:
                return [[-y, x] for x, y in self.relative_coords]
            else:
                return [[y, -x] for x, y in self.relative_coords]
    '''获得该俄罗斯方块的各个小块绝对坐标'''
    def getAbsoluteCoords(self, direction, x, y):
        return [[x + i, y + j] for i, j in self.getRotatedRelativeCoords(direction)]
    '''获得相对坐标的边界'''
    def getRelativeBoundary(self, direction):
        relative_coords_now = self.getRotatedRelativeCoords(direction)
        xs = [i[0] for i in relative_coords_now]
        ys = [i[1] for i in relative_coords_now]
        return min(xs), max(xs), min(ys), max(ys)

2.misc

'''
Function:
    其他工具函数

'''
from PyQt5.QtGui import *


'''给板块的一个Cell填色'''
def drawCell(painter, x, y, shape, grid_size):
    colors = [0x000000, 0xCC6666, 0x66CC66, 0x6666CC, 0xCCCC66, 0xCC66CC, 0x66CCCC, 0xDAAA00]
    if shape == 0:
        return
    color = QColor(colors[shape])
    painter.fillRect(x + 1, y + 1, grid_size - 2, grid_size - 2, color)
    painter.setPen(color.lighter())
    painter.drawLine(x, y + grid_size - 1, x, y)
    painter.drawLine(x, y, x + grid_size - 1, y)
    painter.setPen(color.darker())
    painter.drawLine(x + 1, y + grid_size - 1, x + grid_size - 1, y + grid_size - 1)
    painter.drawLine(x + grid_size - 1, y + grid_size - 1, x + grid_size - 1, y + 1)

3.gameboard

'''
Function:'''
import random
from .misc import *
from .shapes import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QFrame'''内部板块'''
class InnerBoard():def __init__(self, width=10, height=22):# 宽和长, 单位长度为小方块边长self.width = widthself.height = heightself.reset()'''判断当前俄罗斯方块是否可以移动到某位置'''def ableMove(self, coord, direction=None):assert len(coord) == 2if direction is None:direction = self.current_directionfor x, y in self.current_tetris.getAbsoluteCoords(direction, coord[0], coord[1]):# 超出边界if x >= self.width or x < 0 or y >= self.height or y < 0:return False# 该位置有俄罗斯方块了if self.getCoordValue([x, y]) > 0:return Falsereturn True'''向右移动'''def moveRight(self):if self.ableMove([self.current_coord[0] + 1, self.current_coord[1]]):self.current_coord[0] += 1'''向左移动'''def moveLeft(self):if self.ableMove([self.current_coord[0] - 1, self.current_coord[1]]):self.current_coord[0] -= 1'''顺时针转'''def rotateClockwise(self):if self.ableMove(self.current_coord, (self.current_direction - 1) % 4):self.current_direction = (self.current_direction-1) % 4'''逆时针转'''def rotateAnticlockwise(self):if self.ableMove(self.current_coord, (self.current_direction + 1) % 4):self.current_direction = (self.current_direction+1) % 4'''向下移动'''def moveDown(self):removed_lines = 0if self.ableMove([self.current_coord[0], self.current_coord[1] + 1]):self.current_coord[1] += 1else:x_min, x_max, y_min, y_max = self.current_tetris.getRelativeBoundary(self.current_direction)# 简单起见, 有超出屏幕就判定游戏结束if self.current_coord[1] + y_min < 0:self.is_gameover = Truereturn removed_linesself.mergeTetris()removed_lines = self.removeFullLines()self.createNewTetris()return removed_lines'''坠落'''def dropDown(self):removed_lines = 0while self.ableMove([self.current_coord[0], self.current_coord[1] + 1]):self.current_coord[1] += 1x_min, x_max, y_min, y_max = self.current_tetris.getRelativeBoundary(self.current_direction)# 简单起见, 有超出屏幕就判定游戏结束if self.current_coord[1] + y_min < 0:self.is_gameover = Truereturn removed_linesself.mergeTetris()removed_lines = self.removeFullLines()self.createNewTetris()return removed_lines'''合并俄罗斯方块(最下面定型不能再动的那些)'''def mergeTetris(self):for x, y in self.current_tetris.getAbsoluteCoords(self.current_direction, self.current_coord[0], self.current_coord[1]):self.board_data[x + y * self.width] = self.current_tetris.shapeself.current_coord = [-1, -1]self.current_direction = 0self.current_tetris = tetrisShape()'''移出整行都有小方块的'''def removeFullLines(self):new_board_data = [0] * self.width * self.heightnew_y = self.height - 1removed_lines = 0for y in range(self.height - 1, -1, -1):cell_count = sum([1 if self.board_data[x + y * self.width] > 0 else 0 for x in range(self.width)])if cell_count < self.width:for x in range(self.width):new_board_data[x + new_y * self.width] = self.board_data[x + y * self.width]new_y -= 1else:removed_lines += 1self.board_data = new_board_datareturn removed_lines'''创建新的俄罗斯方块(即将next_tetris变为current_tetris)'''def createNewTetris(self):x_min, x_max, y_min, y_max = self.next_tetris.getRelativeBoundary(0)# y_min肯定是-1if self.ableMove([self.init_x, -y_min]):self.current_coord = [self.init_x, -y_min]self.current_tetris = self.next_tetrisself.next_tetris = self.getNextTetris()else:self.is_gameover = Trueself.shape_statistics[self.current_tetris.shape] += 1'''获得下个俄罗斯方块'''def getNextTetris(self):return tetrisShape(random.randint(1, 7))'''获得板块数据'''def getBoardData(self):return self.board_data'''获得板块数据上某坐标的值'''def getCoordValue(self, coord):return self.board_data[coord[0] + coord[1] * self.width]'''获得俄罗斯方块各个小块的绝对坐标'''def getCurrentTetrisCoords(self):return self.current_tetris.getAbsoluteCoords(self.current_direction, self.current_coord[0], self.current_coord[1])'''重置'''def reset(self):# 记录板块数据self.board_data = [0] * self.width * self.height# 当前俄罗斯方块的旋转状态self.current_direction = 0# 当前俄罗斯方块的坐标, 单位长度为小方块边长self.current_coord = [-1, -1]# 下一个俄罗斯方块self.next_tetris = self.getNextTetris()# 当前俄罗斯方块self.current_tetris = tetrisShape()# 游戏是否结束self.is_gameover = False# 俄罗斯方块的初始x位置self.init_x = self.width // 2# 形状数量统计self.shape_statistics = [0] * 8'''外部板块'''
class ExternalBoard(QFrame):score_signal = pyqtSignal(str)def __init__(self, parent, grid_size, inner_board):super(ExternalBoard, self).__init__(parent)self.grid_size = grid_sizeself.inner_board = inner_boardself.setFixedSize(grid_size * inner_board.width, grid_size * inner_board.height)self.initExternalBoard()'''外部板块初始化'''def initExternalBoard(self):self.score = 0'''把内部板块结构画出来'''def paintEvent(self, event):painter = QPainter(self)for x in range(self.inner_board.width):for y in range(self.inner_board.height):shape = self.inner_board.getCoordValue([x, y])drawCell(painter, x * self.grid_size, y * self.grid_size, shape, self.grid_size)for x, y in self.inner_board.getCurrentTetrisCoords():shape = self.inner_board.current_tetris.shapedrawCell(painter, x * self.grid_size, y * self.grid_size, shape, self.grid_size)painter.setPen(QColor(0x777777))painter.drawLine(0, self.height() - 1, self.width(), self.height() - 1)painter.drawLine(self.width() - 1, 0, self.width() - 1, self.height())painter.setPen(QColor(0xCCCCCC))painter.drawLine(self.width(), 0, self.width(), self.height())painter.drawLine(0, self.height(), self.width(), self.height())'''数据更新'''def updateData(self):self.score_signal.emit(str(self.score))self.update()'''侧面板, 右边显示下一个俄罗斯方块的形状'''
class SidePanel(QFrame):def __init__(self, parent, grid_size, inner_board):super(SidePanel, self).__init__(parent)self.grid_size = grid_sizeself.inner_board = inner_boardself.setFixedSize(grid_size * 5, grid_size * inner_board.height)self.move(grid_size * inner_board.width, 0)'''画侧面板'''def paintEvent(self, event):painter = QPainter(self)x_min, x_max, y_min, y_max = self.inner_board.next_tetris.getRelativeBoundary(0)dy = 3 * self.grid_sizedx = (self.width() - (x_max - x_min) * self.grid_size) / 2shape = self.inner_board.next_tetris.shapefor x, y in self.inner_board.next_tetris.getAbsoluteCoords(0, 0, -y_min):drawCell(painter, x * self.grid_size + dx, y * self.grid_size + dy, shape, self.grid_size)'''更新数据'''def updateData(self):self.update()

4.__init__

'''初始化'''
from .shapes import tetrisShape
from .gameboard import InnerBoard, ExternalBoard, SidePanel

5.README

requirements

♥️关注,就是我创作的动力

♥️点赞,就是对我最大的认可

♥️这里是小刘,励志用心做好每一篇文章,谢谢大家


http://chatgpt.dhexx.cn/article/Gr5PhGuG.shtml

相关文章

C语言实现俄罗斯方块

目录 一、游戏效果展示 二、完整代码&#xff0c;可以直接拷贝运行 三、所需开发环境 四、具体项目实现 ①游戏欢迎界面 welcome( ) ②游戏背景 initGameScreen( ) ③方块表示 int block[ ][ ][ ] ④新方块表示nextBlock( ) ⑤设计游戏循环main( ) ⑥搭建用户操作框…

❤️VS Code❤️,cmd终端窗口运行,解决中文乱码问题

目录 问题归纳VS Code默认终端配置window窗口弹出相关解释 解决中文乱码问题运行俄罗斯方块程序 问题归纳 在软件Visual Studio中一切都是配置好的&#xff0c;默认终端运行采用弹出cmd窗口形式。而在VS Code中除了一些默认的配置设置外&#xff0c;所有环境配置、界面显示等操…

俄罗斯方块(C语言实现)

文章目录 游戏说明游戏效果展示游戏代码游戏代码详解游戏框架构建隐藏光标光标跳转初始化界面初始化方块信息颜色设置画出方块空格覆盖合法性判断判断得分与结束游戏主体逻辑函数从文件读取最高分更新最高分到文件主函数 游戏说明 俄罗斯方块相信大家都知道&#xff0c;这里就…

IDEA 设置类注释模板

效果展示 步骤&#xff1a;File-->settings-->Editor-->File and Code Templates-->Files 选择Class文件&#xff08;当然你要设置接口的还也可以选择Interface文件&#xff09;

设置idea类注释模板

1.File-->Settings...&#xff0c;或者直接按快捷键CtrlAltS. 2. Editor-->File and Code Templates-->Includes-->File Header,根据右下角Description的提示&#xff0c;添加自己需要的注释。 3.在右侧空白处设置自己的模板&#xff0c;若提示cant parse class.可…

IDEA 创建类注释模板设置

1.idea类注释 打开&#xff1a;file->setting->Editor->Filr and Code Templates->Includes->File Header 类注释模板&#xff1a; /** * title: ${NAME}* projectName ${PROJECT_NAME}* description: TODO* author ${USER}* date ${DATE}${TIME}*/ 2.方法注释…

java idea 配置注释模板

java idea 配置注释模板 最近项目组在加强代码规范管理。代码优雅从代码注释开始。奥力给&#xff01;&#xff01;&#xff01; 类注释的 File >> Settings >> Editor >> File and code Templates >> Files >> class 上图中的模板内容如下&…

idea类注释模板,方法注释模板。

idea设置--实时模板 新建组 类模板 /*** description $description$* author YJJ* date $date$ $time$* version 1.0*/ 方法模板 ** * description $description$ $params$ $return$* author YJJ* date $date$ $time$*/ params脚本&#xff1a; groovyScript("def r…

IDEA代码注释模板

存在问题: 每次写代码&#xff0c;新建类都没有注释&#xff0c;这对一个拥有代码强迫症患者来说&#xff0c;是多么不爽的一件事&#xff0c;不利于开发和后期问题排查 举个例子&#xff1a; 上次写代码的时候&#xff0c;这一段只有我和上帝知道&#xff0c;而现在&#xff0…

idea添加注释模板

自动添加描述 class // 创建时间有的也没有 仅仅就是class的描述信息&#xff0c;看个人公司情况吧&#xff0c;描述信息最好创建时间有一个空行&#xff0c;我忘记了/** * 描述信息 * * create: ${YEAR}-${MONTH}-${DAY} ${HOUR}:${MINUTE} */method // 一会要写入模板的内…

【idea生成类注释模板快捷键设置】

idea类注释模板快捷键 设置在方法上生成注释的快捷键1&#xff0c;ctrlaltS打开idea设置设置模板中的参数取值来源使用效果展示 设置在方法上生成注释的快捷键 1&#xff0c;ctrlaltS打开idea设置 设置模板中的参数取值来源 使用效果展示

IntelliJ IDEA类和方法注释模板配置

1、设置文件注释 设置Java类的注释模板&#xff0c;创建Java类自动生成该注释模板。 先看文件注释效果&#xff1a; 1.1、选择 IntelliJ IDEA —> 选择 Preferences... 打开IDEA属性设置面板 1.2、选择 File Code Templates—>选择 Includes 选项卡—>选择 File He…

IDEA配置方法类注释模板

IDEA配置方法类注释模板 IDEA20.1配置方法注释注释的种类注释使用规范 摘自阿里开发手册 IDEA方法模板注释一、打开idea 点击菜单File->Setting-Editor->Live Template二、选择Live Template 添加快键键缩写注释模板代码三、配置Edit variables四、配置入参和返回字段的d…

IDEA类和方法注释模板配置

1、类的注释模板配置 File-->Settings-->Editor-->File and Code Templates-->File --->Class: 模板代码下所示&#xff1a; /*** ClassName: ${NAME}* Author : ${USER}* Date :${DATE} ${TIME}* Description: TODO* Version :1.0*/ 上述${NAME}为类名&…

IDEA方法注释模板设置

IDEA类和方法注释模板设置 1、File–>Settings–>Editor–>Live Templates &#xff08;1&#xff09;新建组&#xff1a;命名为userDefine &#xff08;2&#xff09;新建模板&#xff1a;选中你刚才创建的组&#xff0c;然后右上角新建模板&#xff0c;命名为* &…

IDEA注释模板配置

最初&#xff0c;从Eclipse转到IDEA&#xff0c;总是不习惯IDEA的注释方式&#xff0c;所以在网上找来找去加上自己的测试&#xff0c;终于形成一套相对详细的配置流程。之前每次用到都靠收藏里的别人文章应付&#xff0c;但是在配置新的开发环境或者有新的小组成员加入时总要用…

IDEA类文档注释模板设置

IDEA类文档注释模板设置&#xff1a; 在【File and Code Templates】页面设置类&#xff08;Class&#xff09;的文档注释 . 注意&#xff1a;public class ${NAME} {}一定不能删 /***ClassName ${NAME}*Description TODO*Author ${USER}*Date ${DATE} ${TIME}*Version 1.0*…

IDEA 创建类注释模板

一、引言 在写Java代码过程中&#xff0c;当我们创建类的时候往往需要在类上写一些注释信息&#xff0c;而这些注释信息就主要是几个注释点&#xff0c;如果全部都手写就比较浪费时间了&#xff0c;这个时间后我们就可以通过使用注释模板添加自己的自定义的注释在类或者方法上。…

IDEA 设置注释模板顺序

配置注释模板Live Templates时&#xff0c;模板展示顺序只会按照首字母顺序进行排序&#xff0c;若想按照自己配置的模板进行排序&#xff0c;可按照下图关闭设置即可。

IDEA设置注释模板

目录 一、设置类注释模板 二、设置方法注释模板 一、设置类注释模板 打开File->setting->File and Code Templates,选择Includes&#xff0c;选中File Header.如下图所示&#xff1a; 勾选"Enable Live Templates",在内容框中填入注释模板信息。 /*** 创建…