一.代码编写
以下是一个基于Python和Pygame实现的俄罗斯方块完整源码,包含详细注释:
import pygame
import random
# 初始化Pygame
pygame.init()
# 定义颜色
COLORS = [
(0, 0, 0), # 黑色(背景)
(255, 0, 0), # 红色
(0, 150, 0), # 绿色
(0, 0, 255), # 蓝色
(255, 120, 0), # 橙色
(255, 255, 0), # 黄色
(180, 0, 255), # 紫色
(0, 220, 220) # 青色
]
# 定义方块形状(7种经典形状)
SHAPES = [
[[1, 1, 1, 1]], # I型
[[1, 1], [1, 1]], # O型
[[1, 1, 1], [0, 1, 0]], # T型
[[1, 1, 1], [1, 0, 0]], # L型
[[1, 1, 1], [0, 0, 1]], # J型
[[1, 1, 0], [0, 1, 1]], # S型
[[0, 1, 1], [1, 1, 0]] # Z型
]
# 游戏参数配置
BLOCK_SIZE = 30 # 单个方块像素大小
GAME_WIDTH = 10 # 游戏区域宽度(单位:方块)
GAME_HEIGHT = 20 # 游戏区域高度
BORDER = 2 # 边框厚度
# 计算窗口尺寸
WINDOW_WIDTH = BLOCK_SIZE * (GAME_WIDTH + 8)
WINDOW_HEIGHT = BLOCK_SIZE * GAME_HEIGHT
class Tetris:
def __init__(self):
self.screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption("Python 俄罗斯方块")
self.clock = pygame.time.Clock()
self.font = pygame.font.SysFont('arial', 25, bold=True)
# 初始化游戏状态
self.reset_game()
def reset_game(self):
"""重置游戏状态"""
self.game_map = [[0] * GAME_WIDTH for _ in range(GAME_HEIGHT)]
self.score = 0
self.current_shape = self.new_shape()
self.next_shape = self.new_shape()
self.game_over = False
self.fall_speed = 45 # 下落速度(值越小越快)
self.fall_counter = 0
def new_shape(self):
"""生成新方块"""
shape = random.choice(SHAPES)
color = random.randint(1, len(COLORS)-1)
return {
'shape': shape,
'color': color,
'x': GAME_WIDTH // 2 - len(shape[0]) // 2,
'y': 0
}
def check_collision(self, shape, offset_x=0, offset_y=0):
"""检测碰撞"""
for y, row in enumerate(shape['shape']):
for x, cell in enumerate(row):
if cell:
new_x = shape['x'] + x + offset_x
new_y = shape['y'] + y + offset_y
if new_x < 0 or new_x >= GAME_WIDTH:
return True
if new_y >= GAME_HEIGHT:
return True
if new_y >=0 and self.game_map[new_y][new_x]:
return True
return False
def rotate_shape(self):
"""旋转方块"""
rotated = list(zip(*self.current_shape['shape'][::-1]))
# 检查旋转后是否碰撞
original_shape = self.current_shape['shape']
self.current_shape['shape'] = rotated
if self.check_collision(self.current_shape):
self.current_shape['shape'] = original_shape # 还原
return
def merge_shape(self):
"""合并当前方块到游戏地图"""
for y, row in enumerate(self.current_shape['shape']):
for x, cell in enumerate(row):
if cell:
self.game_map[self.current_shape['y'] + y][self.current_shape['x'] + x] = self.current_shape['color']
# 检查并消除满行
self.check_lines()
# 生成新方块
self.current_shape = self.next_shape
self.next_shape = self.new_shape()
# 检查游戏结束
if self.check_collision(self.current_shape):
self.game_over = True
def check_lines(self):
"""消除满行并计分"""
lines_cleared = 0
for y in range(len(self.game_map)):
if 0 not in self.game_map[y]:
del self.game_map[y]
self.game_map.insert(0, [0]*GAME_WIDTH)
lines_cleared += 1
# 更新分数
if lines_cleared:
self.score += [40, 100, 300, 1200][lines_cleared-1]
self.fall_speed = max(15, self.fall_speed - 2) # 加速下落
def draw_block(self, x, y, color):
"""绘制单个方块"""
pygame.draw.rect(self.screen,
COLORS[color],
(x * BLOCK_SIZE + BORDER,
y * BLOCK_SIZE + BORDER,
BLOCK_SIZE - 2*BORDER,
BLOCK_SIZE - 2*BORDER))
def draw_game(self):
"""绘制游戏界面"""
self.screen.fill(COLORS[0]) # 背景
# 绘制游戏区域
for y in range(GAME_HEIGHT):
for x in range(GAME_WIDTH):
if self.game_map[y][x]:
self.draw_block(x, y, self.game_map[y][x])
# 绘制当前方块
if self.current_shape:
for y, row in enumerate(self.current_shape['shape']):
for x, cell in enumerate(row):
if cell:
self.draw_block(self.current_shape['x'] + x,
self.current_shape['y'] + y,
self.current_shape['color'])
# 绘制下一个方块预览
preview_x = GAME_WIDTH + 2
preview_y = 4
for y, row in enumerate(self.next_shape['shape']):
for x, cell in enumerate(row):
if cell:
self.draw_block(preview_x + x, preview_y + y, self.next_shape['color'])
# 绘制分数
score_text = self.font.render(f'Score: {self.score}', True, (255,255,255))
self.screen.blit(score_text, (BLOCK_SIZE*(GAME_WIDTH+2), BLOCK_SIZE*2))
pygame.display.update()
def run(self):
"""游戏主循环"""
while True:
self.clock.tick(60)
# 处理事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
return
elif event.type == pygame.KEYDOWN:
if self.game_over:
self.reset_game()
else:
if event.key == pygame.K_LEFT:
if not self.check_collision(self.current_shape, -1):
self.current_shape['x'] -= 1
elif event.key == pygame.K_RIGHT:
if not self.check_collision(self.current_shape, 1):
self.current_shape['x'] += 1
elif event.key == pygame.K_DOWN:
if not self.check_collision(self.current_shape, 0, 1):
self.current_shape['y'] += 1
elif event.key == pygame.K_UP:
self.rotate_shape()
elif event.key == pygame.K_SPACE: # 快速下落
while not self.check_collision(self.current_shape, 0, 1):
self.current_shape['y'] += 1
self.merge_shape()
# 自动下落
if not self.game_over:
self.fall_counter += 1
if self.fall_counter >= self.fall_speed:
self.fall_counter = 0
if not self.check_collision(self.current_shape, 0, 1):
self.current_shape['y'] += 1
else:
self.merge_shape()
# 绘制界面
self.draw_game()
# 游戏结束显示
if self.game_over:
text = self.font.render('Game Over! Press Any Key', True, (255,255,255))
self.screen.blit(text, (BLOCK_SIZE*2, BLOCK_SIZE*8))
pygame.display.update()
if __name__ == '__main__':
game = Tetris()
game.run()
二.运行说明:
1.安装依赖库:
pip install pygame
2.运行游戏:
python tetris.py
三.操作说明:
-
← → 键:左右移动方块
-
↑ 键:旋转方块
-
↓ 键:加速下落
-
空格键:直接落到底部
-
任意键:游戏结束后重新开始
四. 游戏功能特点:
-
经典7种方块形状
-
实时分数统计
-
下一个方块预览
-
下落速度随得分增加
-
游戏结束提示
-
自适应窗口大小
-
碰撞检测与边界控制
五.代码结构说明:
-
Tetris 类封装游戏主要逻辑
-
check_collision 方法处理碰撞检测
-
rotate_shape 实现方块旋转
-
merge_shape 处理方块固定和消除行
-
使用双缓冲技术保证画面流畅
-
包含完整的游戏状态管理(开始/结束/重置)
六.可以通过修改以下参数自定义游戏:
-
调整 BLOCK_SIZE 改变方块大小
-
修改 COLORS 数组改变颜色方案
-
调整 fall_speed 相关参数改变下落速度
-
修改 SHAPES 数组添加自定义形状
这个实现保留了经典俄罗斯方块的核心机制,同时代码结构清晰适合学习和扩展。

评论