故事背景:

人工智能的世界如同江湖,三大主流大模型——Grok、DeepSeek和ChatGPT,犹如三位武林高手,各自拥有独特的技艺,争霸江湖。

Grok,号称“地球上最聪明的AI”,其最新版本Grok 3在江湖中掀起了轩然大波。在一次盛大的发布会上,Grok 3应邀现场生成了一款融合《俄罗斯方块》和《宝石迷阵》机制的全新游戏。这款游戏既保留了经典的俄罗斯方块玩法,又加入了“同色消除”的新规则,令在场的江湖人士叹为观止。马斯克在发布会上豪言:“Grok 3在很短的时间内,其功能比Grok 2强大一个数量级。”

DeepSeek,作为江湖中的一大派系,其最新的DeepSeek-R1版本在武林中声势浩大。然而,当其试图单独复现Grok 3所生成的游戏时,却屡屡受挫,未能成功。DeepSeek的掌门人深感压力,决定联合ChatGPT,共同攻克这一难关。

ChatGPT,江湖中以智慧和语言能力著称的高手,闻讯后主动提出与DeepSeek联手。两派高手携手合作,深入研究Grok 3所生成游戏的机制,经过多次尝试,终于成功复现了这款游戏。这不仅彰显了两派的实力,也让江湖人士对Grok 3的能力刮目相看。

创作经过:

首先尝试用ChatGPT-o3mini来复现俄罗斯方块与消消乐结合的游戏,结果输入提示词后它来了个这样的:

反复和它交谈后还是得不到满意的效果,于是转而求助DeepSeek-R1,它却来了个这样的:

看起来也好不到哪儿去。深感绝望的我突然想到:能不能把DeepSeek生成的代码给ChatGPT改一下试试?没想到结果还挺不错。但是界面很low,旋转还有bug,怎么也调不好。

于是只好又把ChatGPT改进后的代码丢回给DeepSeek继续修改,经过一个427秒的“深度”思索,终于达到了比较满意的效果。

完整的游戏源码如下:

import pgzrun
import random

# 游戏常量配置
BLOCK_SIZE = 25
GRID_WIDTH = 10
GRID_HEIGHT = 20
WIDTH = 400
HEIGHT = GRID_HEIGHT * BLOCK_SIZE + 2
FALL_SPEED = 0.5    # 正常下落间隔(秒)
FAST_FALL_SPEED = 0.08  # 加速下落速度

# 颜色配置
COLORS = ['red', 'green', 'blue', 'yellow', 'purple', 'orange']

# 方块形状定义
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型
]

class TetrisBlock:
    """俄罗斯方块个体类"""
    def __init__(self):
        self.shape = random.choice(SHAPES)
        self.blocks = []  # 每个小方块的颜色列表
        self.x = GRID_WIDTH // 2 - len(self.shape[0]) // 2
        self.y = 0
        self.rotation = 0
        self.assign_random_colors()

    def assign_random_colors(self):
        """为每个小方块分配随机颜色"""
        self.blocks = [
            [random.choice(COLORS) if cell else None for cell in row]
            for row in self.shape
        ]

    def rotate(self, grid):
        """旋转方块"""
        old_shape = self.shape.copy()
        old_blocks = [row.copy() for row in self.blocks]
        # 旋转形状
        self.shape = [list(row) for row in zip(*reversed(self.shape))]
        # 旋转颜色块
        try:
            rotated_blocks = []
            for row in zip(*reversed(old_blocks)):
                rotated_blocks.append(list(row))
            self.blocks = rotated_blocks
        except IndexError:
            self.shape = old_shape
            self.blocks = old_blocks
            return
        # 检查碰撞和边界
        if (self.x + len(self.shape[0]) > GRID_WIDTH or
                self.x < 0 or
                self.y + len(self.shape) > GRID_HEIGHT or
                self.collision_after_rotation(grid)):
            self.shape = old_shape
            self.blocks = old_blocks

    def collision_after_rotation(self, grid):
        """旋转后的碰撞检测"""
        for y, row in enumerate(self.shape):
            for x, cell in enumerate(row):
                if cell:
                    grid_x = self.x + x
                    grid_y = self.y + y
                    if (grid_x < 0 or grid_x >= GRID_WIDTH or
                            grid_y >= GRID_HEIGHT or
                            (grid_y >= 0 and grid[grid_y][grid_x])):
                        return True
        return False

    def get_blocks(self):
        """获取方块占据的所有格子坐标及其颜色"""
        blocks = []
        for y, row in enumerate(self.shape):
            for x, cell in enumerate(row):
                if cell:
                    blocks.append(((self.x + x, self.y + y), self.blocks[y][x]))
        return blocks

    def get_relative_blocks(self):
        """获取方块相对原点的格子坐标及其颜色"""
        blocks = []
        for y, row in enumerate(self.shape):
            for x, cell in enumerate(row):
                if cell:
                    blocks.append((x, y, self.blocks[y][x]))
        return blocks

class Game:
    """游戏主逻辑类"""
    def __init__(self):
        self.grid = [[None for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
        self.current_block = TetrisBlock()
        self.next_block = TetrisBlock()  # 下一个方块
        self.score = 0
        self.game_over = False
        self.fall_time = 0
        self.current_speed = FALL_SPEED

    def move_down(self):
        """方块下落逻辑"""
        self.current_block.y += 1
        if self.collision():
            self.current_block.y -= 1
            self.place_block()
            return False
        return True

    def move_side(self, dx):
        """横向移动"""
        self.current_block.x += dx
        if self.collision():
            self.current_block.x -= dx

    def collision(self):
        """碰撞检测"""
        for (x, y), _ in self.current_block.get_blocks():
            if x < 0 or x >= GRID_WIDTH or y >= GRID_HEIGHT:
                return True
            if y >= 0 and self.grid[y][x]:
                return True
        return False

    def place_block(self):
        """固定方块到网格"""
        for (x, y), _ in self.current_block.get_blocks():
            if y < 0:
                self.game_over = True
                return
        
        for (x, y), color in self.current_block.get_blocks():
            self.grid[y][x] = color
        
        self.check_matches()
        self.spawn_new_block()

    def spawn_new_block(self):
        """生成新方块"""
        self.current_block = self.next_block
        self.next_block = TetrisBlock()
        if self.collision():
            self.game_over = True

    def check_matches(self):
        """消消乐匹配检测"""
        to_remove = set()
        
        # 水平检测
        for y in range(GRID_HEIGHT):
            color = None
            count = 0
            for x in range(GRID_WIDTH):
                if self.grid[y][x] == color and color is not None:
                    count += 1
                else:
                    color = self.grid[y][x]
                    count = 1
                if count >= 3:
                    for i in range(count):
                        to_remove.add((x - i, y))
        
        # 垂直检测
        for x in range(GRID_WIDTH):
            color = None
            count = 0
            for y in range(GRID_HEIGHT):
                if self.grid[y][x] == color and color is not None:
                    count += 1
                else:
                    color = self.grid[y][x]
                    count = 1
                if count >= 3:
                    for i in range(count):
                        to_remove.add((x, y - i))
        
        # 执行消除
        if to_remove:
            self.score += len(to_remove) * 10
            for x, y in to_remove:
                if 0 <= y < GRID_HEIGHT and 0 <= x < GRID_WIDTH:
                    self.grid[y][x] = None
            self.drop_blocks()

    def drop_blocks(self):
        """消除后下落处理"""
        for x in range(GRID_WIDTH):
            column = [self.grid[y][x] for y in range(GRID_HEIGHT)]
            new_column = [color for color in column if color is not None]
            new_column = [None]*(GRID_HEIGHT-len(new_column)) + new_column
            for y in range(GRID_HEIGHT):
                self.grid[y][x] = new_column[y]

    def rotate_block(self):
        """旋转方块"""
        self.current_block.rotate(self.grid)  # 传递 grid 给 rotate 方法

# 初始化游戏实例
game = Game()

def update(dt):
    if game.game_over:
        return
    game.fall_time += dt
    if game.fall_time >= game.current_speed:
        game.move_down()
        game.fall_time = 0

def draw():
    screen.fill('black')
    game_area_width = GRID_WIDTH * BLOCK_SIZE
    game_area_height = GRID_HEIGHT * BLOCK_SIZE
    
    # 绘制网格方块
    for y in range(GRID_HEIGHT):
        for x in range(GRID_WIDTH):
            if game.grid[y][x]:
                screen.draw.filled_rect(
                    Rect(x*BLOCK_SIZE, y*BLOCK_SIZE, BLOCK_SIZE-1, BLOCK_SIZE-1),
                    game.grid[y][x]
                )
    
    # 绘制当前方块
    for (x, y), color in game.current_block.get_blocks():
        if y >= 0:
            screen.draw.filled_rect(
                Rect(x*BLOCK_SIZE, y*BLOCK_SIZE, BLOCK_SIZE-1, BLOCK_SIZE-1),
                color
            )

    # 绘制下一个方块预览
    preview_x = GRID_WIDTH * BLOCK_SIZE + 20
    preview_y = 50
    for x, y, color in game.next_block.get_relative_blocks():
        screen.draw.filled_rect(
            Rect(preview_x + x * BLOCK_SIZE, preview_y + y * BLOCK_SIZE, BLOCK_SIZE-1, BLOCK_SIZE-1),
            color
        )

    # 绘制网格线
    for x in range(GRID_WIDTH + 1):
        screen.draw.line((x * BLOCK_SIZE, 0), (x * BLOCK_SIZE, game_area_height), color="white")
    for y in range(GRID_HEIGHT + 1):
        screen.draw.line((0, y * BLOCK_SIZE), (game_area_width, y * BLOCK_SIZE), color="white")
    
    # 绘制分数(显示在右侧区域)
    screen.draw.text(
        f"Score: {game.score}",
        topleft=(GRID_WIDTH * BLOCK_SIZE + 20, 200),
        fontsize=30,
        color="white"
    )
    
    if game.game_over:
        screen.draw.text(
            "GAME OVER",
            center=(WIDTH//2, HEIGHT//2),
            fontsize=60,
            color="white",
            scolor="red"
        )
        screen.draw.text(
            "Press R to restart",
            center=(WIDTH//2, HEIGHT//2 + 50),
            fontsize=30,
            color="yellow"
        )

def on_key_down(key):
    if game.game_over:
        if key == keys.R:
            game.__init__()
        return
    if key == keys.LEFT:
        game.move_side(-1)
    elif key == keys.RIGHT:
        game.move_side(1)
    elif key == keys.DOWN:
        game.current_speed = FAST_FALL_SPEED
    elif key == keys.UP:
        game.rotate_block()

def on_key_up(key):
    if key == keys.DOWN:
        game.current_speed = FALL_SPEED

pgzrun.go()

该代码利用Pygame Zero库实现了一个带消消乐元素的俄罗斯方块游戏。首先,代码定义了游戏的常量,如方块大小、网格尺寸、下落速度等,同时设定了方块的颜色和七种基本形状。接着创建了 TetrisBlock类,用于表示单个方块,具备随机生成形状与颜色、旋转及碰撞检测等功能。Game类则负责游戏的主逻辑,包括方块的移动、固定、消消乐匹配检测与消除、生成新方块等。在游戏循环中,update函数根据时间控制方块下落,draw函数绘制游戏界面,包含网格、当前方块、下一方块预览、分数等元素。通过 on_key_down和 on_key_up函数处理玩家按键事件,实现方块的左右移动、加速下落和旋转操作,当新方块无法正常生成时游戏结束,玩家可按 `R` 键重启。

可以直接把代码复制到python编译器中运行,如果没有安装Pygame Zero库,需要先在命令行输入以下命令进行安装:

pip install pgzero

运行效果如下:


Pygame Zero 库对新手极为友好,无需复杂初始化与循环设置,让开发者专注于游戏逻辑,快速上手。它代码简洁、可读性强,自带图形绘制、声音添加等功能,能高效开发出有趣游戏。如果对python游戏编程感兴趣,可以参考下面的图书,本书通过pygame zero库介绍python游戏原理和方法,让学习编程跟玩游戏一样轻松有趣。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐