俄罗斯方块简易版 python

目录

俄罗斯方块简易版 pygame

控制下落时间:

需求:

QJ版本 deepseek:

QJ版本 gpt:


俄罗斯方块简易版 pygame

控制下落时间:

fall_interval = 0.2
import pygame
import random
import time

# 初始化 Pygame
pygame.init()

# 颜色定义
COLORS = {'I': (0, 255, 255),  # 青色
    'O': (255, 255, 0),  # 黄色
    'T': (128, 0, 128),  # 紫色
    'J': (0, 0, 255),  # 蓝色
    'L': (255, 165, 0),  # 橙色
    'S': (0, 255, 0),  # 绿色
    'Z': (255, 0, 0),  # 红色
    'background': (0, 0, 0), 'grid': (40, 40, 40)}

# 游戏区域尺寸
WIDTH, HEIGHT = 10, 20
CELL_SIZE = 30
SCREEN_WIDTH = CELL_SIZE * (WIDTH + 6)
SCREEN_HEIGHT = CELL_SIZE * HEIGHT

# 方块形状定义
SHAPES = {'I': [[1, 1, 1, 1]], 'O': [[1, 1], [1, 1]], 'T': [[0, 1, 0], [1, 1, 1]], 'J': [[1, 0, 0], [1, 1, 1]], 'L': [[0, 0, 1], [1, 1, 1]], 'S': [[0, 1, 1], [1, 1, 0]], 'Z': [[1, 1, 0], [0, 1, 1]]}


class Tetris:
    def __init__(self):
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        pygame.display.set_caption("俄罗斯方块")
        self.clock = pygame.time.Clock()
        self.board = [[None for _ in range(WIDTH)] for _ in range(HEIGHT)]
        self.current_piece = None
        self.next_piece = None
        self.score = 0
        self.game_over = False
        self.spawn_new_piece()

    def spawn_new_piece(self):
        if self.next_piece is None:
            shapes = list(SHAPES.keys())
            self.current_piece = Piece(random.choice(shapes), (WIDTH // 2 - 2, 0))
            self.next_piece = Piece(random.choice(shapes), (WIDTH + 1, 2))
        else:
            self.current_piece = self.next_piece
            self.next_piece = Piece(random.choice(list(SHAPES.keys())), (WIDTH + 1, 2))
            self.current_piece.pos = (WIDTH // 2 - 2, 0)

        if self.check_collision(self.current_piece.shape, self.current_piece.pos):
            self.game_over = True

    def check_collision(self, shape, offset):
        off_x, off_y = offset
        for y, row in enumerate(shape):
            for x, cell in enumerate(row):
                if cell:
                    px = x + off_x
                    py = y + off_y
                    if px < 0 or px >= WIDTH or py >= HEIGHT:
                        return True
                    if py >= 0 and self.board[py][px] is not None:
                        return True
        return False

    def rotate_piece(self):
        new_shape = list(zip(*self.current_piece.shape[::-1]))
        if not self.check_collision(new_shape, self.current_piece.pos):
            self.current_piece.shape = new_shape

    def move(self, dx):
        new_pos = (self.current_piece.pos[0] + dx, self.current_piece.pos[1])
        if not self.check_collision(self.current_piece.shape, new_pos):
            self.current_piece.pos = new_pos

    def hard_drop(self):
        while not self.check_collision(self.current_piece.shape, (self.current_piece.pos[0], self.current_piece.pos[1] + 1)):
            self.current_piece.pos = (self.current_piece.pos[0], self.current_piece.pos[1] + 1)
        self.place_piece()

    def place_piece(self):
        shape = self.current_piece.shape
        pos = self.current_piece.pos
        for y, row in enumerate(shape):
            for x, cell in enumerate(row):
                if cell:
                    px = x + pos[0]
                    py = y + pos[1]
                    if 0 <= px < WIDTH and 0 <= py < HEIGHT:
                        self.board[py][px] = self.current_piece.color
        self.clear_lines()
        self.spawn_new_piece()

    def clear_lines(self):
        lines_cleared = 0
        new_board = []
        for row in self.board:
            if None not in row:
                lines_cleared += 1
            else:
                new_board.append(row)

        self.score += [0, 100, 300, 500, 800][lines_cleared]
        self.board = [[None] * WIDTH for _ in range(lines_cleared)] + new_board

    def draw(self):
        self.screen.fill(COLORS['background'])

        # 绘制游戏区域
        for y in range(HEIGHT):
            for x in range(WIDTH):
                color = self.board[y][x] or COLORS['grid']
                pygame.draw.rect(self.screen, color, (x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE - 1, CELL_SIZE - 1))

        # 绘制当前方块
        if self.current_piece:
            for y, row in enumerate(self.current_piece.shape):
                for x, cell in enumerate(row):
                    if cell:
                        px = (x + self.current_piece.pos[0]) * CELL_SIZE
                        py = (y + self.current_piece.pos[1]) * CELL_SIZE
                        pygame.draw.rect(self.screen, self.current_piece.color, (px, py, CELL_SIZE - 1, CELL_SIZE - 1))

        # 绘制下一个方块预览
        next_x = (WIDTH + 1) * CELL_SIZE
        pygame.draw.rect(self.screen, (255, 255, 255), (next_x, 50, 100, 100), 2)
        if self.next_piece:
            for y, row in enumerate(self.next_piece.shape):
                for x, cell in enumerate(row):
                    if cell:
                        px = next_x + x * CELL_SIZE
                        py = 50 + y * CELL_SIZE
                        pygame.draw.rect(self.screen, self.next_piece.color, (px, py, CELL_SIZE - 1, CELL_SIZE - 1))

        # 绘制分数
        font = pygame.font.Font(None, 36)
        text = font.render(f"Score: {self.score}", True, (255, 255, 255))
        self.screen.blit(text, (next_x, 200))

        pygame.display.flip()

    def run(self):
        last_fall = time.time()
        fall_interval = 0.5

        while not self.game_over:
            dt = time.time() - last_fall
            self.clock.tick(30)

            # 自动下落
            if dt > fall_interval:
                if not self.check_collision(self.current_piece.shape, (self.current_piece.pos[0], self.current_piece.pos[1] + 1)):
                    self.current_piece.pos = (self.current_piece.pos[0], self.current_piece.pos[1] + 1)
                else:
                    self.place_piece()
                last_fall = time.time()

            # 事件处理
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.game_over = True
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_LEFT:
                        self.move(-1)
                    elif event.key == pygame.K_RIGHT:
                        self.move(1)
                    elif event.key == pygame.K_UP:
                        self.rotate_piece()
                    elif event.key == pygame.K_SPACE:
                        self.hard_drop()

            self.draw()

        pygame.quit()


class Piece:
    def __init__(self, shape_type, pos):
        self.shape = SHAPES[shape_type]
        self.color = COLORS[shape_type]
        self.pos = pos  # (x, y)


if __name__ == "__main__":
    game = Tetris()
    game.run()

需求:

游戏界面由20行×10列的可视区域组成,7种不同形状的四格方块(I/T/O/J/L/S/Z型)随机从顶部生成下落(具体形状如下图所示),并且在一个方块生成后,玩家可以知道下一个方块的形状。

• 横向范围:X轴区间 [0, 9](共10列)
• 纵向范围:Y轴区间 [0, 19](共20行,Y=0为底部,Y=19为顶部)• 死亡判定线:Y ≥ 15(当方块堆叠高度触达此线时游戏结束)
在本问题中玩家使用的是简化版的操作规则,只能进行以下三种操作:
• 横向移动:左右平移• 旋转操作:支持0°、90°、180°、270°四向旋转• 瞬间落地:瞬间抵达当前可到达的最底部位置
当一行及以上(Y轴坐标相同)的全部位置被完全填充时,这些行将被消除,并且玩家将根据同时消除的行数获得分数:
• 单行消除:100分• 双行消除:300分• 三行消除:500分• 四行消除:800分



OJ版输入
第一行为两个单字符,即So和S1(So、S €{I,T,O,J,L,S,Z})。So和S1.分别表示第一个要下落的方块和第二个要下落的方块的形状。交互过程中,你每次依次输出一个方块的放置方案。在你每次输出放置方块的方案后,交互程序将再给你一行新的输入,该输入为一个单字符,即S:(S:€{I,T,O,J,工,S,Z,X,E}表示一个新的下个要下落的方块的形状。若S为x表示x前边的方块是最后
一个方块,程序应该在输出最后一个方块的放置方案后结束。若S为E表示玩家的放置方案已导致游戏结束(堆叠高度触达死亡判定线),程序应直接退出。测试数据均采用随机种子生成,且保证输入数据的总长度(即掉落的方块总数)小于1.000.000.

QJ版本 deepseek:

import sys

# 定义每个方块的各种旋转形态的相对坐标(dx, dy)
tetrominoes = {
    'I': [
        [(0, 0), (1, 0), (2, 0), (3, 0)],  # 旋转0度
        [(1, -1), (1, 0), (1, 1), (1, 2)], # 旋转90度
        [(0, 0), (1, 0), (2, 0), (3, 0)],  # 旋转180度
        [(1, -1), (1, 0), (1, 1), (1, 2)]  # 旋转270度
    ],
    'O': [
        [(0, 0), (1, 0), (0, 1), (1, 1)] for _ in range(4)
    ],
    'T': [
        [(0, 0), (1, 0), (2, 0), (1, 1)],  # 旋转0度
        [(1, -1), (1, 0), (1, 1), (0, 0)], # 旋转90度
        [(0, 0), (1, 0), (2, 0), (1, -1)], # 旋转180度
        [(1, -1), (1, 0), (1, 1), (2, 0)]  # 旋转270度
    ],
    'S': [
        [(0, 1), (1, 1), (1, 0), (2, 0)], # 旋转0度
        [(1, -1), (1, 0), (0, 0), (0, 1)], # 旋转90度
        [(0, 1), (1, 1), (1, 0), (2, 0)], # 旋转180度
        [(1, -1), (1, 0), (0, 0), (0, 1)]  # 旋转270度
    ],
    'Z': [
        [(0, 0), (1, 0), (1, 1), (2, 1)], # 旋转0度
        [(1, -1), (0, 0), (1, 0), (0, 1)], # 旋转90度
        [(0, 0), (1, 0), (1, 1), (2, 1)], # 旋转180度
        [(1, -1), (0, 0), (1, 0), (0, 1)]  # 旋转270度
    ],
    'J': [
        [(0, 0), (0, 1), (1, 1), (2, 1)], # 旋转0度
        [(1, -1), (2, -1), (1, 0), (1, 1)], # 旋转90度
        [(0, 0), (1, 0), (2, 0), (2, -1)], # 旋转180度
        [(0, 1), (1, 1), (0, 0), (0, 2)]  # 旋转270度
    ],
    'L': [
        [(0, 1), (1, 1), (2, 1), (2, 0)], # 旋转0度
        [(1, -1), (1, 0), (1, 1), (0, 1)], # 旋转90度
        [(0, 0), (0, 1), (1, 0), (2, 0)], # 旋转180度
        [(1, -1), (2, -1), (1, 0), (1, 1)]  # 旋转270度
    ]
}

def main():
    # 初始化游戏区域
    grid = [[False for _ in range(10)] for _ in range(20)]
    existing_heights = [-1] * 10
    score = 0

    # 读取初始输入
    line = sys.stdin.readline().strip()
    if not line:
        return
    s0, s1 = line.split()
    current_piece = s0
    next_piece = s1

    while True:
        best_move = None
        best_score = -1
        best_lines = -1
        best_height = 20  # 用较低的堆叠高度更优

        for rotate in range(4):
            if current_piece not in tetrominoes:
                break
            blocks = tetrominoes[current_piece][rotate]
            dx_list = [dx for dx, dy in blocks]
            dy_list = [dy for dx, dy in blocks]

            min_dx = min(dx_list)
            max_dx = max(dx_list)
            x_shift_min = max(0 - min_dx, 0)
            x_shift_max = min(9 - max_dx, 9)
            if x_shift_min > x_shift_max:
                continue

            for x_shift in range(x_shift_min, x_shift_max + 1):
                x_coords = [x_shift + dx for dx in dx_list]
                if any(x < 0 or x >= 10 for x in x_coords):
                    continue

                required_y0 = []
                for i in range(4):
                    x = x_coords[i]
                    dy = dy_list[i]
                    required_y0.append(existing_heights[x] - dy)
                y0 = max(required_y0)
                y_coords = [y0 + dy_list[i] for i in range(4)]

                if any(y < 0 or y >= 20 for y in y_coords):
                    continue
                if any(y >= 15 for y in y_coords):
                    continue

                # 模拟放置到临时网格
                temp_grid = [row.copy() for row in grid]
                valid = True
                for x, y in zip(x_coords, y_coords):
                    if y < 0 or y >= 20 or x < 0 or x >= 10:
                        valid = False
                        break
                    if temp_grid[y][x]:
                        valid = False
                        break
                    temp_grid[y][x] = True
                if not valid:
                    continue

                # 检查哪些行被消除
                lines_cleared = 0
                filled_y = set(y_coords)
                for y in filled_y:
                    if 0 <= y < 20 and all(temp_grid[y][x] for x in range(10)):
                        lines_cleared += 1

                current_score = 0
                if lines_cleared == 1:
                    current_score = 100
                elif lines_cleared == 2:
                    current_score = 300
                elif lines_cleared == 3:
                    current_score = 500
                elif lines_cleared == 4:
                    current_score = 800

                max_y = max(y_coords) if y_coords else 0

                if current_score > best_score or (current_score == best_score and max_y < best_height) or (current_score == best_score and max_y == best_height and (best_move is None or x_shift < best_move[1] or (x_shift == best_move[1] and rotate < best_move[0]))):
                    best_score = current_score
                    best_move = (rotate, x_shift)
                    best_height = max_y
                    best_lines = lines_cleared

        if best_move is None:
            print("E")
            return

        rotate, x_shift = best_move
        print(f"{rotate} {x_shift}")
        sys.stdout.flush()

        # 更新实际网格
        blocks = tetrominoes[current_piece][rotate]
        dx_list = [dx for dx, dy in blocks]
        dy_list = [dy for dx, dy in blocks]
        x_coords = [x_shift + dx for dx in dx_list]
        required_y0 = []
        for i in range(4):
            x = x_coords[i]
            dy = dy_list[i]
            required_y0.append(existing_heights[x] - dy)
        y0 = max(required_y0)
        y_coords = [y0 + dy for dy in dy_list]

        for x, y in zip(x_coords, y_coords):
            if 0 <= y < 20 and 0 <= x < 10:
                grid[y][x] = True

        if any(y >= 15 for y in y_coords):
            return

        # 处理行消除
        lines_to_clear = []
        for y in range(20):
            if all(grid[y][x] for x in range(10)):
                lines_to_clear.append(y)

        if lines_to_clear:
            lines_to_clear.sort(reverse=True)
            for y in lines_to_clear:
                del grid[y]
                grid.insert(0, [False]*10)

            existing_heights = [-1] * 10
            for x in range(10):
                for y in range(19, -1, -1):
                    if grid[y][x]:
                        existing_heights[x] = y
                        break
        else:
            # 更新 existing_heights
            for x in range(10):
                max_y = -1
                for y in range(20):
                    if grid[y][x]:
                        max_y = y
                existing_heights[x] = max_y

        # 读取下一个方块
        next_input = sys.stdin.readline().strip()
        if next_input == 'X':
            break
        elif next_input == 'E':
            return
        current_piece = next_input

if __name__ == "__main__":
    main()

QJ版本 gpt:


import sys

BOARD_WIDTH = 10
BOARD_HEIGHT = 20
DEATH_LINE = 15

SCORES = [0, 100, 300, 500, 800]  # 行消除得分:1行~4行

BLOCKS = {
    'I': [
        [(0, 1), (1, 1), (2, 1), (3, 1)],
        [(2, 0), (2, 1), (2, 2), (2, 3)],
        [(0, 2), (1, 2), (2, 2), (3, 2)],
        [(1, 0), (1, 1), (1, 2), (1, 3)],
    ],
    'O': [
        [(1, 0), (2, 0), (1, 1), (2, 1)] for _ in range(4)
    ],
    'T': [
        [(1, 0), (0, 1), (1, 1), (2, 1)],
        [(1, 0), (1, 1), (1, 2), (2, 1)],
        [(0, 1), (1, 1), (2, 1), (1, 2)],
        [(1, 0), (0, 1), (1, 1), (1, 2)],
    ],
    'S': [
        [(1, 0), (2, 0), (0, 1), (1, 1)],
        [(1, 0), (1, 1), (2, 1), (2, 2)],
        [(1, 1), (2, 1), (0, 2), (1, 2)],
        [(0, 0), (0, 1), (1, 1), (1, 2)],
    ],
    'Z': [
        [(0, 0), (1, 0), (1, 1), (2, 1)],
        [(2, 0), (1, 1), (2, 1), (1, 2)],
        [(0, 1), (1, 1), (1, 2), (2, 2)],
        [(1, 0), (0, 1), (1, 1), (0, 2)],
    ],
    'J': [
        [(0, 0), (0, 1), (1, 1), (2, 1)],
        [(1, 0), (2, 0), (1, 1), (1, 2)],
        [(0, 1), (1, 1), (2, 1), (2, 2)],
        [(1, 0), (1, 1), (0, 2), (1, 2)],
    ],
    'L': [
        [(2, 0), (0, 1), (1, 1), (2, 1)],
        [(1, 0), (1, 1), (1, 2), (2, 2)],
        [(0, 1), (1, 1), (2, 1), (0, 2)],
        [(0, 0), (1, 0), (1, 1), (1, 2)],
    ]
}

class Tetris:
    def __init__(self):
        self.board = [[0] * BOARD_WIDTH for _ in range(BOARD_HEIGHT)]
        self.score = 0

    def can_place(self, shape, x, y):
        for dx, dy in shape:
            nx, ny = x + dx, y + dy
            if nx < 0 or nx >= BOARD_WIDTH or ny < 0 or ny >= BOARD_HEIGHT:
                return False
            if self.board[ny][nx]:
                return False
        return True

    def find_drop_y(self, shape, x):
        for y in range(BOARD_HEIGHT - 1, -1, -1):
            if self.can_place(shape, x, y):
                return y
        return -1

    def drop(self, shape_name):
        best_x = None
        best_rot = None
        best_y = -1

        for rot in range(4):
            shape = BLOCKS[shape_name][rot]
            max_dx = max(dx for dx, _ in shape)
            for x in range(BOARD_WIDTH - max_dx):
                y = self.find_drop_y(shape, x)
                if y == -1:
                    continue
                if y > best_y or (y == best_y and (best_x is None or x < best_x)):
                    best_x = x
                    best_rot = rot
                    best_y = y

        return best_x, best_rot

    def place_block(self, shape_name, x, rot):
        shape = BLOCKS[shape_name][rot]
        y = self.find_drop_y(shape, x)
        if y == -1:
            return False  # 无法放置
        for dx, dy in shape:
            self.board[y + dy][x + dx] = 1
        return True

    def clear_lines(self):
        new_board = []
        cleared = 0
        for row in self.board:
            if all(row):
                cleared += 1
            else:
                new_board.append(row)
        while len(new_board) < BOARD_HEIGHT:
            new_board.insert(0, [0] * BOARD_WIDTH)
        self.board = new_board
        self.score += SCORES[cleared]

    def is_game_over(self):
        for y in range(DEATH_LINE, BOARD_HEIGHT):
            if any(self.board[y][x] for x in range(BOARD_WIDTH)):
                return True
        return False

    def play(self):
        s0, s1 = input().strip().split()
        curr, next_shape = s0, s1

        while True:
            # 放置当前方块
            x, rot = self.drop(curr)
            if x is None or rot is None:
                print("0 0")
                sys.stdout.flush()
                return
            print(f"{x} {rot}")
            sys.stdout.flush()

            # 落地并消除
            placed = self.place_block(curr, x, rot)
            self.clear_lines()

            # 判定是否死亡
            if self.is_game_over():
                return

            # 读取下一个方块
            curr = input().strip()
            if curr == 'X':
                # 最后一个,放置完就退出
                x, rot = self.drop(next_shape)
                if x is None or rot is None:
                    print("0 0")
                    sys.stdout.flush()
                    return
                print(f"{x} {rot}")
                sys.stdout.flush()
                self.place_block(next_shape, x, rot)
                self.clear_lines()
                return
            elif curr == 'E':
                return
            else:
                curr, next_shape = next_shape, curr


if __name__ == "__main__":
    game = Tetris()
    game.play()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI算法网奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值