Python Tetromino怎么实现?python俄罗斯方块代码

Python Tetromino (俄罗斯方块)

下面是一个完整的、可运行的 Python Tetromino(俄罗斯方块)实现,使用 pygame 库。

安装依赖

pip install pygame

完整代码

import pygame
import random
import sys
# 初始化 pygame
pygame.init()
# ==================== 常量 ====================
BLOCK_SIZE = 30
COLS = 10
ROWS = 20
SCREEN_WIDTH = COLS  BLOCK_SIZE + 200  # 留出侧边栏
SCREEN_HEIGHT = ROWS  BLOCK_SIZE
# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (40, 40, 40)
DARK_GRAY = (80, 80, 80)
# 方块颜色
COLORS = [
    (0, 255, 255),    # I - 青色
    (0, 0, 255),      # J - 蓝色
    (255, 165, 0),    # L - 橙色
    (255, 255, 0),    # O - 黄色
    (0, 255, 0),      # S - 绿色
    (128, 0, 128),    # T - 紫色
    (255, 0, 0),      # Z - 红色
]
# 方块形状定义 (每个方块有4个旋转状态)
SHAPES = [
    # I
    [
        [[1, 1, 1, 1]],
        [[1], [1], [1], [1]],
    ],
    # J
    [
        [[1, 0, 0], [1, 1, 1]],
        [[1, 1], [1, 0], [1, 0]],
        [[1, 1, 1], [0, 0, 1]],
        [[0, 0, 1], [0, 1], [0, 1]],
    ],
    # L
    [
        [[0, 0, 1], [1, 1, 1]],
        [[1, 0], [1, 0], [1, 1]],
        [[1, 1, 1], [1, 0, 0]],
        [[0, 1], [0, 1], [1, 1]],
    ],
    # O
    [
        [[1, 1], [1, 1]],
    ],
    # S
    [
        [[0, 1, 1], [1, 1, 0]],
        [[1, 0], [1, 1], [0, 1]],
    ],
    # T
    [
        [[0, 1, 0], [1, 1, 1]],
        [[0, 1], [1, 1], [0, 1]],
        [[1, 1, 1], [0, 1, 0]],
        [[1, 0], [1, 1], [1, 0]],
    ],
    # Z
    [
        [[1, 1, 0], [0, 1, 1]],
        [[0, 1], [1, 1], [1, 0]],
    ],
]
# ==================== 方块类 ====================
class Piece:
    def __init__(self, shape_index=None):
        if shape_index is None:
            self.shape_index = random.randint(0, len(SHAPES) - 1)
        else:
            self.shape_index = shape_index
        self.color = COLORS[self.shape_index]
        self.rotation = 0
        # 初始位置:顶部中间
        self.x = COLS // 2 - 1
        self.y = 0
    def get_shape(self):
        """获取当前旋转状态下的形状"""
        shapes = SHAPES[self.shape_index]
        return shapes[self.rotation % len(shapes)]
    def rotate(self):
        """旋转方块"""
        self.rotation = (self.rotation + 1) % len(SHAPES[self.shape_index])
# ==================== 游戏主类 ====================
class Tetris:
    def __init__(self):
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        pygame.display.set_caption("Tetromino - 俄罗斯方块")
        self.clock = pygame.time.Clock()
        self.font = pygame.font.SysFont("arial", 24)
        self.big_font = pygame.font.SysFont("arial", 48, bold=True)
        self.reset_game()
    def reset_game(self):
        """重置游戏状态"""
        self.board = [[None]  COLS for _ in range(ROWS)]
        self.current_piece = Piece()
        self.next_piece = Piece()
        self.score = 0
        self.level = 1
        self.lines_cleared = 0
        self.game_over = False
        self.drop_timer = 0
        self.drop_interval = 500  # 毫秒,随等级加快
    def get_valid_positions(self, piece, dx=0, dy=0):
        """获取方块所有有效位置(用于碰撞检测)"""
        shape = piece.get_shape()
        positions = []
        for r, row in enumerate(shape):
            for c, cell in enumerate(row):
                if cell:
                    new_x = piece.x + c + dx
                    new_y = piece.y + r + dy
                    positions.append((new_x, new_y))
        return positions
    def is_valid(self, piece, dx=0, dy=0):
        """检查方块位置是否合法"""
        positions = self.get_valid_positions(piece, dx, dy)
        for x, y in positions:
    

Python Tetromino怎么实现?python俄罗斯方块代码

全网最详细-使用python实现俄罗斯方块小游戏
加载中
全网最详细-使用python实现俄罗斯方块小游戏
# 检查边界 if x < 0 or x >= COLS or y >= ROWS: return False # 检查是否与已有方块重叠 if y >= 0 and self.board[y][x] is not None: return False return True def lock_piece(self): """将当前方块锁定到棋盘""" shape = self.current_piece.get_shape() for r, row in enumerate(shape): for c, cell in enumerate(row): if cell: x = self.current_piece.x + c y = self.current_piece.y + r if 0 <= y < ROWS and 0 <= x < COLS: self.board[y][x] = self.current_piece.color def clear_lines(self): """清除完整行并计分""" lines_to_clear = [] for r in range(ROWS): if all(cell is not None for cell in self.board[r]): lines_to_clear.append(r) if lines_to_clear: # 从下往上删除行 for line in sorted(lines_to_clear, reverse=True): del self.board[line] self.board.insert(0, [None] COLS) num_lines = len(lines_to_clear) # 计分规则 points = [0, 100, 300, 500, 800] self.score += points[num_lines] self.level self.lines_cleared += num_lines # 每10行升一级 self.level = self.lines_cleared // 10 + 1 self.drop_interval = max(100, 500 - (self.level - 1) 40) def spawn_new_piece(self): """生成新方块""" self.current_piece = self.next_piece self.next_piece = Piece() # 检查新方块是否立即碰撞(游戏结束) if not self.is_valid(self.current_piece): self.game_over = True def get_ghost_piece(self): """获取幽灵方块(预测落点)""" ghost = Piece() ghost.shape_index = self.current_piece.shape_index ghost.color = self.current_piece.color ghost.rotation = self.current_piece.rotation ghost.x = self.current_piece.x ghost.y = self.current_piece.y while self.is_valid(ghost, dy=1): ghost.y += 1 return ghost def draw_board(self): """绘制游戏棋盘""" # 背景 self.screen.fill(BLACK) # 绘制网格线 for r in range(ROWS + 1): pygame.draw.line(self.screen, GRAY, (0, r BLOCK_SIZE), (COLS BLOCK_SIZE, r BLOCK_SIZE)) for c in range(COLS + 1): pygame.draw.line(self.screen, GRAY, (c BLOCK_SIZE, 0), (c BLOCK_SIZE, ROWS BLOCK_SIZE)) # 绘制已锁定的方块 for r in range(ROWS): for c in range(COLS): if self.board[r][c] is not None: rect = pygame.Rect(c BLOCK_SIZE, r BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE) pygame.draw.rect(self.screen, self.board[r][c], rect) pygame.draw.rect(self.screen, DARK_GRAY, rect, 2) # 绘制幽灵方块 if not self.game_over: ghost = self.get_ghost_piece() shape = ghost.get_shape() for r, row in enumerate(shape): for c, cell in enumerate(row): if cell: gx = ghost.x + c gy = ghost.y + r if 0 <= gy < ROWS: rect = pygame.Rect(gx BLOCK_SIZE, gy BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE) pygame.draw.rect(self.screen, (255, 255, 255, 50), rect, 2) # 绘制当前方块 if not self.game_over: shape = self.current_piece.get_shape()

Python Tetromino怎么实现?python俄罗斯方块代码

for r, row in enumerate(shape): for c, cell in enumerate(row): if cell: x = self.current_piece.x + c y = self.current_piece.y + r if y >= 0: # 只绘制可见部分 rect = pygame.Rect(x BLOCK_SIZE, y BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE) pygame.draw.rect(self.screen, self.current_piece.color, rect) pygame.draw.rect(self.screen, DARK_GRAY, rect, 2) def draw_sidebar(self): """绘制侧边栏(分数、下一个方块等)""" sidebar_x = COLS BLOCK_SIZE + 20 # 标题 title = self.big_font.render("TETRIS", True, WHITE) self.screen.blit(title, (sidebar_x, 20)) # 分数 score_text = self.font.render(f"Score: {self.score}", True, WHITE) self.screen.blit(score_text, (sidebar_x, 100)) # 等级 level_text = self.font.render(f"Level: {self.level}", True, WHITE) self.screen.blit(level_text, (sidebar_x, 140)) # 行数 lines_text = self.font.render(f"Lines: {self.lines_cleared}", True, WHITE) self.screen.blit(lines_text, (sidebar_x, 180)) # 下一个方块 next_title = self.font.render("Next:", True, WHITE) self.screen.blit(next_title, (sidebar_x, 240)) # 绘制下一个方块预览 shape = self.next_piece.get_shape() preview_x = sidebar_x + 10 preview_y = 280 for r, row in enumerate(shape): for c, cell in enumerate(row): if cell: rect = pygame.Rect(preview_x + c BLOCK_SIZE, preview_y + r BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE) pygame.draw.rect(self.screen, self.next_piece.color, rect) pygame.draw.rect(self.screen, DARK_GRAY, rect, 2) # 操作说明 controls_y = 400 controls = [ "Controls:", "← → : Move", "↑ : Rotate", "↓ : Soft Drop", "Space: Hard Drop", "P : Pause", "R : Restart", "Q : Quit" ] for i, text in enumerate(controls): color = WHITE if i > 0 else (200, 200, 0) t = self.font.render(text, True, color) self.screen.blit(t, (sidebar_x, controls_y + i 28)) # 游戏结束 if self.game_over: overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT)) overlay.set_alpha(180) overlay.fill(BLACK) self.screen.blit(overlay, (0, 0)) go_text = self.big_font.render("GAME OVER", True, (255, 0, 0)) text_rect = go_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 30)) self.screen.blit(go_text, text_rect) score_text = self.font.render(f"Final Score: {self.score}", True, WHITE) score_rect = score_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 20)) self.screen.blit(score_text, score_rect) restart_text = self.font.render("Press R to Restart", True, WHITE) restart_rect = restart_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 60)) self.screen.blit(restart_text, restart_rect) def draw(self): """绘制整个游戏画面""" self.draw_board() self.draw_sidebar() pygame.display.flip() def handle_input(self): """处理用户输入""" keys = pygame.key.get_pressed() dt = self.clock.get_time() if not self.game_over: # 左右移动 if keys[pygame.K_LEFT]: if self.is_valid(self.current_piece, dx=-1):

Python Tetromino怎么实现?python俄罗斯方块代码

self.current_piece.x -= 1 if keys[pygame.K_RIGHT]: if self.is_valid(self.current_piece, dx=1): self.current_piece.x += 1 # 旋转 if keys[pygame.K_UP]: old_rotation = self.current_piece.rotation self.current_piece.rotate() if not self.is_valid(self.current_piece): # 尝试墙踢(wall kick) for offset in [-1, 1, -2, 2]: if self.is_valid(self.current_piece, dx=offset): self.current_piece.x += offset break else: # 回滚旋转 self.current_piece.rotation = old_rotation break # 软降 if keys[pygame.K_DOWN]: self.drop_timer += dt 3 # 加速下落 # 硬降 if keys[pygame.K_SPACE]: while self.is_valid(self.current_piece, dy=1): self.current_piece.y += 1 self.lock_piece() self.clear_lines() self.spawn_new_piece() self.drop_timer = 0 # 暂停 if keys[pygame.K_p]: pass # 简化:不实现暂停切换 # 重启 if keys[pygame.K_r]: self.reset_game() # 退出 if keys[pygame.K_q]: pygame.quit() sys.exit() def update(self): """更新游戏状态""" if not self.game_over: self.drop_timer += self.clock.get_time() if self.drop_timer >= self.drop_interval: if self.is_valid(self.current_piece, dy=1): self.current_piece.y += 1 else: # 锁定方块 self.lock_piece() self.clear_lines() self.spawn_new_piece() self.drop_timer = 0 def run(self): """游戏主循环""" running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_q: running = False elif event.key == pygame.K_r: self.reset_game() self.handle_input() self.update() self.draw() self.clock.tick(60) # 60 FPS pygame.quit() sys.exit() # ==================== 运行游戏 ==================== if __name__ == "__main__": game = Tetris() game.run()

功能特性

功能 说明
7种标准方块 I, J, L, O, S, T, Z
旋转系统 支持墙踢(Wall Kick)
幽灵方块 白色半透明预览落点
下一个方块预览 侧边栏显示下一个方块
计分系统 单行100分,双行300分,三行500分,四行800分(乘以等级)
等级系统 每清除10行升一级,下落速度加快
硬降/软降 空格硬降,↓键软降

操作说明

  • : 左右移动
  • : 旋转
  • : 加速下落
  • 空格 : 直接落到底部
  • R : 重新开始
  • Q : 退出游戏

运行方式

python tetromino.py

确保已安装 pygamepip install pygame

首发原创文章,作者:世雄 - 原生数据库架构专家,如若转载,请注明出处:https://idctop.com/article/484379.html

(0)
Curese Python是什么?Python新手入门教程
上一篇 2026年7月12日 01:57
cdn供应商哪家好,cdn供应商排名
下一篇 2026年7月12日 01:59

相关推荐

  • 个人移动开发者中心怎么注册?申请流程及费用详解

    个人移动开发者中心是独立开发者低成本构建、测试及分发移动应用的核心枢纽,通过集成官方SDK与自动化构建工具,可显著缩短从代码到上架的全流程周期,对于大多数独立开发者而言,传统的开发环境配置往往伴随着繁琐的依赖管理和复杂的权限申请流程,这不仅消耗大量时间,还容易因环境差异导致“在我机器上能跑”的尴尬局面,个人移动……

    2026年5月27日
    3800
  • 个人注册的域名能用于企业备案吗?域名备案主体不一致怎么解决

    个人注册的域名完全可以用于企业备案,但前提是域名持有者必须将域名所有权过户至企业名下,且企业需具备合法的营业执照,很多创业者在起步阶段,为了节省成本或图方便,直接用个人身份证注册了域名,随后发现公司刚成立,想给网站做ICP备案时却卡了壳,这种“个人域名+企业主体”的错位,是新手最容易踩的坑,别急,这个问题有明确……

    2026年5月28日
    3900
  • 个人网站备案信息真实性核验单怎么填?备案核验单填写模板

    填写个人网站备案信息真实性核验单的核心在于确保所有信息与身份证、手机号及网站内容完全一致,严禁使用虚假资料或代填,否则将直接导致备案失败,备案审核是网站上线前的必经关卡,很多站长在这里卡壳并非因为技术难题,而是因为对核验单的填写规则理解偏差,这份表格不仅是形式审查,更是工信部对网站主体身份的真实性的法律确认,一……

    服务器运维 2026年5月26日
    2800
  • 服务器开发者专享优惠活动有哪些?开发者服务器优惠活动推荐

    服务器开发者专享优惠活动是降低研发成本、加速项目上线的高效途径,其核心价值在于通过专属折扣与资源配置,精准解决开发者在测试、部署及运维阶段的资金与技术瓶颈,对于技术团队而言,抓住此类优惠活动,不仅意味着直接减少IT基础设施支出,更能获得云厂商提供的技术护航,实现“低成本、高效率”的项目交付,核心优势:成本优化与……

    2026年3月28日
    7600
  • 服务器常用命令有哪些?Linux服务器运维指令大全

    服务器管理的核心在于通过命令行界面实现高效、精准的系统控制,熟练掌握服务器常用命令是保障系统稳定性与安全性的基石,对于运维人员而言,图形界面虽直观,但在处理高并发、远程管理及自动化任务时,命令行工具拥有不可替代的优势,核心结论是:构建一套结构清晰、逻辑严密的命令知识体系,能够帮助管理员快速定位故障、优化性能并防……

    2026年4月4日
    8600
  • 个人怎么购买域名?域名注册流程及注意事项

    个人购买域名最稳妥的方式是通过ICANN认证的正规域名注册商(如阿里云、腾讯云、GoDaddy等)进行在线注册,完成实名认证后即可拥有该域名的管理权,域名是互联网世界的门牌号,对于个人站长、博主或小型创作者而言,拥有一个专属域名不仅是品牌化的第一步,更是掌握自己网络资产所有权的关键,很多人误以为域名只是随便填个……

    2026年5月30日
    4300
  • 服务器怎么挂载云盘?详细步骤教程与常见问题解决

    服务器挂载云盘的核心在于“正确识别磁盘设备、精准分区格式化、配置挂载信息”这三步闭环操作,无论使用何种操作系统,挂载的本质是将物理或逻辑存储设备映射到文件系统目录树中,使其可被读写,操作前务必做好数据快照备份,防止误操作导致数据丢失,这是保障数据安全不可逾越的红线, 挂载前的环境准备与核心认知在执行具体操作前……

    2026年3月18日
    9400
  • 服务器怎么加带宽?服务器增加带宽的具体步骤有哪些

    服务器增加带宽的核心在于精准识别性能瓶颈,通过升级硬件配置、优化软件架构以及引入内容分发网络(CDN)等多维手段综合实现,而非单纯依赖运营商线路扩容,带宽升级的本质是解决数据传输通道的拥堵问题,必须遵循“先优化、后扩容”的原则,以实现成本与性能的最佳平衡, 物理扩容:运营商线路升级与硬件瓶颈排查当服务器带宽利用……

    2026年3月21日
    10300
  • 服务器忘记了终端密码怎么办?终端密码忘记怎么找回

    服务器终端密码遗忘并非不可逆转的灾难,通过正确的重启引导模式或使用云平台控制台的远程连接功能,管理员可以在几分钟内重置密码并恢复系统的完全控制权,核心解决路径在于打破现有系统的权限壁垒,利用单用户模式或救援模式获得根权限,进而修改密码文件,这一过程在物理服务器和云服务器上虽有操作差异,但底层逻辑一致,面对密码遗……

    2026年3月24日
    9900
  • 服务器搭建与管理下载哪里有?服务器管理软件免费版下载

    高效、稳定的服务器环境是保障数据传输速度与业务连续性的基石,服务器搭建与管理下载的核心在于构建一套安全、可扩展且易于维护的系统架构,这要求运维人员不仅要掌握Linux或Windows Server的系统配置,更要精通权限管理、网络优化及自动化运维策略,以实现从环境部署到资源分发的全流程高效闭环, 硬件选型与基础……

    2026年3月5日
    10800

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注