此代码定义了俄罗斯方块游戏中的方块和游戏逻辑,同时使用 pygame 库实现了游戏的图形界面。你可以运行此代码,用上下左右键来控制方块的移动和旋转。

import pygame
import random

# 初始化 Pygame
pygame.init()

# 定义常量
WIDTH = 300
HEIGHT = 600
BLOCK_SIZE = 30
BOARD_WIDTH = WIDTH // BLOCK_SIZE
BOARD_HEIGHT = HEIGHT // BLOCK_SIZE

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
CYAN = (0, 255, 255)
YELLOW = (255, 255, 0)
MAGENTA = (255, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
ORANGE = (255, 165, 0)

# 形状定义
SHAPES = [
    [[1, 1, 1, 1]],
    [[1, 1], [1, 1]],
    [[1, 1, 0], [0, 1, 1]],
    [[0, 1, 1], [1, 1, 0]],
    [[1, 1, 1], [0, 1, 0]],
    [[1, 1, 1], [1, 0, 0]],
    [[1, 1, 1], [0, 0, 1]]
]

SHAPE_COLORS = [CYAN, YELLOW, MAGENTA, GREEN, RED, BLUE, ORANGE]


class Block:
    def __init__(self, x, y, shape):
        self.x = x
        self.y = y
        self.shape = shape
        self.color = random.choice(SHAPE_COLORS)

    def move_down(self):
        self.y += 1

    def move_left(self):
        self.x -= 1

    def move_right(self):
        self.x += 1

    def rotate(self):
        self.shape = list(map(list, zip(*self.shape[::-1])))


class Tetris:
    def __init__(self):
        self.board = [[0] * BOARD_WIDTH for _ in range(BOARD_HEIGHT)]
        self.current_block = Block(BOARD_WIDTH // 2 - len(SHAPES[0][0]) // 2, 0, random.choice(SHAPES))

    def is_collision(self, block):
        for y, row in enumerate(block.shape):
            for x, cell in enumerate(row):
                if cell:
                    new_x = block.x + x
                    new_y = block.y + y
                    if new_x < 0 or new_x >= BOARD_WIDTH or new_y >= BOARD_HEIGHT or (
                            new_y >= 0 and self.board[new_y][new_x]):
                        return True
        return False

    def merge_block(self, block):
        for y, row in enumerate(block.shape):
            for x, cell in enumerate(row):
                if cell:
                    self.board[block.y + y][block.x + x] = 1

    def clear_lines(self):
        full_lines = []
        for i, row in enumerate(self.board):
            if all(row):
                full_lines.append(i)
        for line in full_lines:
            del self.board[line]
            self.board = [[0] * BOARD_WIDTH] + self.board

    def new_block(self):
        self.current_block = Block(BOARD_WIDTH // 2 - len(SHAPES[0][0]) // 2, 0, random.choice(SHAPES))
        if self.is_collision(self.current_block):
            return False
        return True

    def move_down(self):
        new_block = Block(self.current_block.x, self.current_block.y + 1, self.current_block.shape)
        if self.is_collision(new_block):
            self.merge_block(self.current_block)
            self.clear_lines()
            return self.new_block()
        else:
            self.current_block.move_down()
        return True

    def move_left(self):
        new_block = Block(self.current_block.x - 1, self.current_block.y, self.current_block.shape)
        if not self.is_collision(new_block):
            self.current_block.move_left()

    def move_right(self):
        new_block = Block(self.current_block.x + 1, self.current_block.y, self.current_block.shape)
        if not self.is_collision(new_block):
            self.current_block.move_right()

    def rotate(self):
        new_shape = list(map(list, zip(*self.current_block.shape[::-1])))
        new_block = Block(self.current_block.x, self.current_block.y, new_shape)
        if not self.is_collision(new_block):
            self.current_block.rotate()


# 创建窗口
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Tetris")

# 创建游戏对象
game = Tetris()

clock = pygame.time.Clock()
fall_time = 0
fall_speed = 0.3

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_LEFT:
                game.move_left()
            elif event.key == pygame.K_RIGHT:
                game.move_right()
            elif event.key == pygame.K_DOWN:
                game.move_down()
            elif event.key == pygame.K_UP:
                game.rotate()

    # 自动下落
    fall_time += clock.get_rawtime()
    clock.tick()

    if fall_time / 1000 >= fall_speed:
        if not game.move_down():
            running = False
        fall_time = 0

    # 绘制背景
    screen.fill(BLACK)

    # 绘制网格
    for i in range(BOARD_WIDTH):
        for j in range(BOARD_HEIGHT):
            pygame.draw.rect(screen, WHITE,
                             (i * BLOCK_SIZE, j * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE), 1)

    # 绘制当前方块
    for y, row in enumerate(game.current_block.shape):
        for x, cell in enumerate(row):
            if cell:
                pygame.draw.rect(screen, game.current_block.color,
                                 ((game.current_block.x + x) * BLOCK_SIZE, (game.current_block.y + y) * BLOCK_SIZE,
                                  BLOCK_SIZE, BLOCK_SIZE))

    # 绘制已固定的方块
    for y, row in enumerate(game.board):
        for x, cell in enumerate(row):
            if cell:
                pygame.draw.rect(screen, SHAPE_COLORS[0], (x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))

    pygame.display.flip()

pygame.quit()
    

程序员老叶
1 声望0 粉丝

十年老程序猿一枚