当前位置: 首页 > news >正文

使用DeepSeek定制Python小游戏——以“俄罗斯方块”为例

前言

本来想再发几个小游戏后在整理一下流程的,但是今天试了一下这个俄罗斯方块的游戏结果发现本来修改的好好的的,结果后面越改越乱,前面的版本也没保存,根据AI修改他是在几个版本改来改去,想着要求还是不能这么高。我是采用DeepSeek+Pycharm+Lingma来操作的。

贪吃蛇(含Python源码)-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/147660127?spm=1001.2014.3001.5501

外星人入侵(python)_外星人入侵python源代码-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/135963588?spm=1001.2014.3001.5501

DeepSeek部分

对于DeepSeek我是直接询问“Python可以设计哪些简单的小游戏”,然后根据推荐的游戏挑选直接感兴趣的,比如可以询问“用Python代码实现俄罗斯方块小游戏”,于是就生成了以下的代码,因为我是选择了联网搜索,所以肯定会借鉴其他博主代码:

import pygame
import random# 初始化 Pygame
pygame.init()# 游戏窗口尺寸和颜色
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600
GRID_SIZE = 30
GRID_WIDTH = 10
GRID_HEIGHT = 20
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
COLORS = [(0, 255, 255),    # I 型(青色)(255, 165, 0),     # L 型(橙色)(0, 0, 255),      # J 型(蓝色)(255, 255, 0),    # O 型(黄色)(0, 255, 0),       # S 型(绿色)(255, 0, 255),     # T 型(紫色)(255, 0, 0)        # Z 型(红色)
]# 方块形状定义(4x4 矩阵)
SHAPES = [[[1, 1, 1, 1]],                   # I 型[[1, 0, 0], [1, 1, 1]],           # L 型[[0, 0, 1], [1, 1, 1]],           # J 型[[1, 1], [1, 1]],                 # O 型[[0, 1, 1], [1, 1, 0]],           # S 型[[0, 1, 0], [1, 1, 1]],           # T 型[[1, 1, 0], [0, 1, 1]]            # Z 型
]# 初始化窗口
screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption("俄罗斯方块")# 游戏区域矩阵(0表示空)
game_area = [[0] * GRID_WIDTH for _ in range(GRID_HEIGHT)]# 当前方块和位置
current_shape = None
current_pos = [0, 0]
current_color = None
score = 0def new_shape():"""生成新方块"""global current_shape, current_pos, current_colorcurrent_shape = random.choice(SHAPES)current_color = random.choice(COLORS)current_pos = [GRID_WIDTH // 2 - len(current_shape[0]) // 2, 0]def check_collision(shape, pos):"""检查方块是否与边界或已有方块碰撞"""for y, row in enumerate(shape):for x, cell in enumerate(row):if cell:px = pos[0] + xpy = pos[1] + yif px < 0 or px >= GRID_WIDTH or py >= GRID_HEIGHT:return Trueif py >= 0 and game_area[py][px]:return Truereturn Falsedef merge_shape():"""将当前方块合并到游戏区域"""for y, row in enumerate(current_shape):for x, cell in enumerate(row):if cell:game_area[current_pos[1] + y][current_pos[0] + x] = current_colordef clear_lines():"""消除满行并更新分数"""global scorelines_to_clear = [i for i, row in enumerate(game_area) if all(cell != 0 for cell in row)]for i in lines_to_clear:del game_area[i]game_area.insert(0, [0] * GRID_WIDTH)score += len(lines_to_clear) * 100def rotate_shape():"""旋转当前方块(顺时针)"""global current_shaperotated = list(zip(*current_shape[::-1]))if not check_collision(rotated, current_pos):current_shape = rotateddef draw_grid():"""绘制游戏区域"""for y in range(GRID_HEIGHT):for x in range(GRID_WIDTH):color = game_area[y][x]if color:pygame.draw.rect(screen, color, (x*GRID_SIZE, y*GRID_SIZE, GRID_SIZE-1, GRID_SIZE-1))def draw_current_shape():"""绘制当前下落的方块"""for y, row in enumerate(current_shape):for x, cell in enumerate(row):if cell:px = (current_pos[0] + x) * GRID_SIZEpy = (current_pos[1] + y) * GRID_SIZEpygame.draw.rect(screen, current_color, (px, py, GRID_SIZE-1, GRID_SIZE-1))def game_loop():clock = pygame.time.Clock()fall_time = 0fall_speed = 500  # 下落间隔(毫秒)new_shape()running = Truewhile running:screen.fill(BLACK)current_time = pygame.time.get_ticks()# 处理输入事件for event in pygame.event.get():if event.type == pygame.QUIT:running = Falseif event.type == pygame.KEYDOWN:if event.key == pygame.K_LEFT:current_pos[0] -= 1if check_collision(current_shape, current_pos):current_pos[0] += 1if event.key == pygame.K_RIGHT:current_pos[0] += 1if check_collision(current_shape, current_pos):current_pos[0] -= 1if event.key == pygame.K_DOWN:current_pos[1] += 1if check_collision(current_shape, current_pos):current_pos[1] -= 1if event.key == pygame.K_UP:rotate_shape()if event.key == pygame.K_SPACE:  # 快速下落while not check_collision(current_shape, current_pos):current_pos[1] += 1current_pos[1] -= 1# 自动下落if current_time - fall_time > fall_speed:current_pos[1] += 1if check_collision(current_shape, current_pos):current_pos[1] -= 1merge_shape()clear_lines()new_shape()if check_collision(current_shape, current_pos):running = False  # 游戏结束fall_time = current_time# 绘制界面draw_grid()draw_current_shape()pygame.display.update()clock.tick(60)# 游戏结束提示font = pygame.font.Font(None, 74)text = font.render(f'Game Over! Score: {score}', True, WHITE)screen.blit(text, (WINDOW_WIDTH//2 - 200, WINDOW_HEIGHT//2 - 50))pygame.display.update()pygame.time.wait(3000)if __name__ == "__main__":game_loop()pygame.quit()

如果直接运行当然会存在一些的问题,比如这个右侧是空白的,但是方块无法移动过去。 

 Pycharm+Lingma部分

我主要是用的这个插件进行修改代码,一方面可以让他对代码进行优化,另一方面还能询问可以增加什么特色的功能。

比如我想增加历史最高分的模块以及右侧可以用来显示下一个方块的相关信息,本来一切都向着好方向修改,结果却越改越乱,下面的代码用DeepSeek应该是修改不了,所以建议新增功能还是一个个功能的增加测试,不然不清楚哪里有问题,还需要慢慢调试,对于要修改的地方可以通过Ctrl+F来搜索进行快速定位,对于代码报错或者警告的信息也可以询问Lingma进行修改,甚至可以进行直接替换(但是感觉不保险,怕乱改)

以下的代码存在着很多问题,但是又不想删除(毕竟改了一下午),所以也放出来的,有感兴趣的大佬可以看一下,目前存在的问题是游戏无法结束,他触碰到上底后会在下底增加方块,还有这个生存模式根据DeepSeek的操作应该是要增加障碍,还有这个不同颜色方块的功能,应该就是突然增加太多了导致代码出问题了。

# -*- coding: utf-8 -*-
import pygame
import random
import os
from typing import List, Tuple, Optional# 初始化 Pygame
pygame.init()
os.environ['PYGAME_FREETYPE'] = '1'  # 启用更好字体渲染# 新增最高分文件路径
HIGHSCORE_FILE = "tetris_highscore.txt"# 在文件开头添加字体常量
FONT_CONFIG = {"simhei": {"path": "simhei.ttf","sizes": {"title": 36, "subtitle": 28, "normal": 24}},"backup": {"name": "arial","sizes": {"title": 36, "subtitle": 28, "normal": 24}}
}# 修改字体加载函数
def load_font(font_type: str, size_type: str):"""统一字体加载函数(优化版)"""# 直接使用系统字体名称try:return pygame.font.SysFont("simhei", FONT_CONFIG["simhei"]["sizes"][size_type])except Exception as e:print(f"系统字体加载失败: {e}")try:return pygame.font.Font(None, FONT_CONFIG["backup"]["sizes"][size_type])except:return pygame.font.SysFont(FONT_CONFIG["backup"]["name"],FONT_CONFIG["backup"]["sizes"][size_type])def load_highscore():"""加载历史最高分"""try:if os.path.exists(HIGHSCORE_FILE):with open(HIGHSCORE_FILE, 'r') as f:return int(f.read().strip() or 0)return 0except Exception as e:print(f"读取最高分失败: {e}")return 0def save_highscore(score):"""保存最高分"""with open(HIGHSCORE_FILE, 'w') as f:f.write(str(score))# 游戏窗口尺寸和颜色
WINDOW_HEIGHT = 600
GRID_SIZE = 30
GRID_WIDTH = 10
GRID_HEIGHT = 20
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
DARK_GRAY = (40, 40, 40)  # 游戏区域背景色
COLORS = [(0, 255, 255),  # I 型(青色)(255, 165, 0),  # L 型(橙色)(0, 0, 255),  # J 型(蓝色)(255, 255, 0),  # O 型(黄色)(0, 255, 0),  # S 型(绿色)(255, 0, 255),  # T 型(紫色)(255, 0, 0)  # Z 型(红色)
]
# 特殊方块颜色
SPECIAL_COLORS = [(255, 100, 100),  # 爆炸红:消除整行(100, 255, 100),  # 加速绿:下落速度x2(100, 100, 255)  # 护盾蓝:免疫下一次碰撞
]
COLORS += SPECIAL_COLORS# 方块形状定义(4x4 矩阵)
SHAPES = [[[1, 1, 1, 1]],  # I 型[[1, 0, 0], [1, 1, 1]],  # L 型[[0, 0, 1], [1, 1, 1]],  # J 型[[1, 1], [1, 1]],  # O 型[[0, 1, 1], [1, 1, 0]],  # S 型[[0, 1, 0], [1, 1, 1]],  # T 型[[1, 1, 0], [0, 1, 1]]  # Z 型
]
# 新增游戏状态常量
GAME_STATES = {'START': 0,'MODE_SELECT': 1,  # 新增模式选择状态'PLAYING': 2,'GAME_OVER': 3
}# 修改游戏界面布局参数(新增右侧信息面板)
INFO_PANEL_WIDTH = 200  # 右侧信息面板宽度
GAME_PANEL_WIDTH = GRID_WIDTH * GRID_SIZE  # 300
#  游戏界面宽度
WINDOW_WIDTH = GAME_PANEL_WIDTH + INFO_PANEL_WIDTH
# 初始化窗口
screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption("俄罗斯方块")# 游戏区域矩阵(0表示空)
game_area = [[None] * GRID_WIDTH for _ in range(GRID_HEIGHT)]# 当前方块和位置
current_shape: Optional[List[List[int]]] = None
current_pos = [0, 0]
current_color: Optional[Tuple[int, int, int]] = None
# 在全局变量声明区域添加:
next_shape: Optional[List[List[int]]] = None
next_color: Optional[Tuple[int, int, int]] = None
score = 0
# 新增全局变量
game_mode = 0  # 0-经典模式 1-生存模式
obstacle_timer = 0
special_effect = None
effect_duration = 0# 修改new_shape函数(添加下一个方块生成)
def new_shape():global current_shape, current_pos, current_color, next_shape, next_colorif not hasattr(new_shape, "_initialized"):current_shape = random.choice(SHAPES)current_color = random.choice(COLORS)next_shape = random.choice(SHAPES)next_color = random.choice(COLORS)new_shape._initialized = Trueelse:current_shape = next_shapecurrent_color = next_colornext_shape = random.choice(SHAPES)next_color = random.choice(COLORS)if random.random() < 0.2 and current_color not in SPECIAL_COLORS:current_color = random.choice(SPECIAL_COLORS)# 修复点1:计算方块总高度shape_height = len(current_shape)# 修复点2:调整生成位置计算逻辑 ▼base_offset = -shape_height  # 确保整个方块在屏幕外# 生存模式额外上移(原逻辑错误导致坐标计算为负值不够)if game_mode == 1:base_offset = -shape_height - 2  # 调整为-2格缓冲current_pos = [GRID_WIDTH // 2 - len(current_shape[0]) // 2,base_offset  # Y坐标修正]def check_collision(shape, pos):"""统一碰撞检测(移除模式判断)"""# 修改点1:block → shapefor y in range(len(shape)):  # ← 修改这里# 修改点2:block.shape → shapefor x in range(len(shape[y])):  # ← 修改这里# 修改点3:cell → shape[y][x]if shape[y][x]:  # ← 修改这里(原cell未定义)px = pos[0] + xpy = pos[1] + y# 边界检测if px < 0 or px >= GRID_WIDTH:return Trueif py >= GRID_HEIGHT:  # 底部边界return True# 有效区域检测(包含顶部边界)if py >= 0 and game_area[py][px] is not None:return Truereturn Falsedef merge_shape():"""将当前方块合并到游戏区域"""for y, row in enumerate(current_shape):for x, cell in enumerate(row):if cell:game_area[current_pos[1] + y][current_pos[0] + x] = current_colordef clear_lines():"""消除满行并更新分数"""global score, fall_speed, game_arealines_to_clear = [i for i, row in enumerate(game_area) if all(cell is not None for cell in row)]# 删除并补充新行(保持总行数不变)for _ in lines_to_clear:del game_area[0]  # 删除顶部行(原逻辑错误:删除指定索引行)game_area.append([None] * GRID_WIDTH)  # 在底部补充新行score += len(lines_to_clear) * 100fall_speed = max(50, 500 - (score // 100) * 50)  # 每得100分加快50msdef rotate_shape():"""旋转当前方块(顺时针)"""global current_shaperotated = [list(row) for row in zip(*current_shape[::-1])]  # 转换为列表的列表if not check_collision(rotated, current_pos):current_shape = rotateddef draw_grid():"""绘制游戏区域(增加维度保护)"""assert len(game_area) == GRID_HEIGHT, \f"游戏区域行数异常:{len(game_area)}(应保持{GRID_HEIGHT}行)"assert all(len(row) == GRID_WIDTH for row in game_area), \"游戏区域列数异常"for y in range(GRID_HEIGHT):for x in range(GRID_WIDTH):color = game_area[y][x]# 加颜色有效性验证(必须为三元组且数值合法)if color is not None and isinstance(color, tuple) and len(color) == 3:pygame.draw.rect(screen, color, (x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE - 1, GRID_SIZE - 1))def draw_current_shape():"""绘制当前下落的方块"""for y, row in enumerate(current_shape):for x, cell in enumerate(row):if cell:px = (current_pos[0] + x) * GRID_SIZEpy = (current_pos[1] + y) * GRID_SIZEpygame.draw.rect(screen, current_color, (px, py, GRID_SIZE - 1, GRID_SIZE - 1))# 新增右侧信息面板绘制函数
def draw_info_panel(score, highscore, next_shape, next_color, mode, effect):# 绘制右侧面板背景pygame.draw.rect(screen, BLACK, (GAME_PANEL_WIDTH, 0, INFO_PANEL_WIDTH, WINDOW_HEIGHT))# 统一字体加载(修改关键部分)main_font = load_font("simhei", "normal")  # 使用预设的24号字small_font = load_font("simhei", "subtitle")  # 使用28号字# 修改显示文本为中文# 显示下一个方块标题(修正坐标计算)title_text = main_font.render("下一个方块", True, WHITE)title_x = GAME_PANEL_WIDTH + (INFO_PANEL_WIDTH - title_text.get_width()) // 2screen.blit(title_text, (title_x, 30))  # 原100改为30避免重叠# 分数显示修正(使用统一字体)score_text = main_font.render(f"当前分数:{score}", True, WHITE)screen.blit(score_text, (GAME_PANEL_WIDTH + 10, 300))  # 原使用Font(None)处# 显示最高分highscore_text = main_font.render(f"最高纪录:{highscore}", True, WHITE)screen.blit(highscore_text, (GAME_PANEL_WIDTH + 10, 350))# 计算预览方块位置(居中显示)preview_size = len(next_shape[0]) * GRID_SIZEstart_x = GAME_PANEL_WIDTH + (INFO_PANEL_WIDTH - preview_size) // 2start_y = 100# 绘制预览方块for y, row in enumerate(next_shape):for x, cell in enumerate(row):if cell:pygame.draw.rect(screen, next_color, (start_x + x * GRID_SIZE,start_y + y * GRID_SIZE,GRID_SIZE - 1, GRID_SIZE - 1))# 添加模式显示mode_text = main_font.render(  # 使用已定义的main_fontf"模式:{'生存' if mode else '经典'}",True,(255, 0, 0) if mode else (0, 255, 0))screen.blit(mode_text, (GAME_PANEL_WIDTH + 10, 400))# 显示当前特效if effect:effect_mapping = {'speed': '加速', 'shield': '护盾'}effect_text = main_font.render(  # 使用已定义的main_fontf"特效:{effect_mapping.get(effect, '未知')}",True,(255, 255, 0))screen.blit(effect_text, (GAME_PANEL_WIDTH + 10, 450))# 新增开始界面
def show_start_screen(highscore):# 添加中文字体支持try:title_font = pygame.font.SysFont("SimHei", 36)text_font = pygame.font.SysFont("SimHei", 24)except:try:title_font = pygame.font.Font("msyh.ttc", 36)text_font = pygame.font.Font("msyh.ttc", 24)except:title_font = pygame.font.Font(None, 36)text_font = pygame.font.Font(None, 24)screen.fill(BLACK)title = title_font.render("俄罗斯方块", True, WHITE)title_rect = title.get_rect(center=(WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2 - 70))screen.blit(title, title_rect)font = pygame.font.Font(None, 32)prompt = title_font.render("按任意键开始游戏", True, WHITE)prompt_rect = prompt.get_rect(center=(WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2 + 30))screen.blit(prompt, prompt_rect)highscore_text = title_font.render(f"当前最高分: {highscore}", True, (200, 200, 200))highscore_rect = highscore_text.get_rect(center=(WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2 + 90))screen.blit(highscore_text, highscore_rect)pygame.display.update()waiting = Truewhile waiting:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()return Falseif event.type in (pygame.KEYDOWN, pygame.MOUSEBUTTONDOWN):waiting = Falsereturn True# 新增模式选择界面(在show_start_screen函数后添加)
def show_mode_menu():screen.fill(BLACK)# 加载中文字体的正确方式font = load_font("simhei", "subtitle")  # 28号字desc_font = load_font("simhei", "normal")  # 24号字# 打印调试信息print(f"当前使用字体: {font}")print("可用系统字体:", pygame.font.get_fonts())# 绘制标题title = font.render("选择游戏模式", True, (255, 255, 0))title_rect = title.get_rect(center=(WINDOW_WIDTH // 2, 60))screen.blit(title, title_rect)# 模式按钮参数modes = [{"text": "经典模式","desc": "标准俄罗斯方块规则","key": "1","color": (0, 255, 255),"rect": pygame.Rect(WINDOW_WIDTH // 2 - 180, 120, 360, 60)},{"text": "生存模式","desc": "每30秒生成障碍行","key": "2","color": (255, 0, 0),"rect": pygame.Rect(WINDOW_WIDTH // 2 - 180, 210, 360, 60)}]# 绘制模式选项for mode in modes:# 按钮背景pygame.draw.rect(screen, (30, 30, 30), mode["rect"], border_radius=10)# 模式名称text_surf = font.render(f"{mode['key']}. {mode['text']}", True, mode["color"])text_rect = text_surf.get_rect(left=mode["rect"].left + 20, centery=mode["rect"].centery - 15)screen.blit(text_surf, text_rect)# 模式描述desc_surf = desc_font.render(mode["desc"], True, (200, 200, 200))desc_rect = desc_surf.get_rect(left=mode["rect"].left + 20, centery=mode["rect"].centery + 15)screen.blit(desc_surf, desc_rect)# 绘制提示文字prompt = desc_font.render("使用数字键选择 或 鼠标点击选择", True, (150, 150, 150))prompt_rect = prompt.get_rect(center=(WINDOW_WIDTH // 2, 320))screen.blit(prompt, prompt_rect)pygame.display.update()while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()exit()if event.type == pygame.KEYDOWN:if event.key == pygame.K_1: return 0if event.key == pygame.K_2: return 1if event.type == pygame.MOUSEBUTTONDOWN:mouse_pos = pygame.mouse.get_pos()for idx, mode in enumerate(modes):if mode["rect"].collidepoint(mouse_pos):return idx  # 0或1对应模式def game_loop():'''游戏主循环'''global score, game_area, current_shape, current_pos, current_color, next_shape, next_colorglobal game_mode, obstacle_timer, special_effect, effect_duration# 初始化游戏状态current_state = GAME_STATES['START']highscore = load_highscore()running = Trueclock = pygame.time.Clock()fall_time = pygame.time.get_ticks()fall_speed = 10  # 下落间隔(毫秒)while running:current_time = pygame.time.get_ticks()# 状态处理if current_state == GAME_STATES['PLAYING']:assert len(game_area) == GRID_HEIGHT, "游戏区域行数异常"assert all(len(row) == GRID_WIDTH for row in game_area), "游戏区域列数异常"if current_state == GAME_STATES['START']:if not show_start_screen(highscore):returncurrent_state = GAME_STATES['MODE_SELECT']if current_state == GAME_STATES['MODE_SELECT']:game_mode = show_mode_menu()game_area = [[None] * GRID_WIDTH for _ in range(GRID_HEIGHT)]score = 0if game_mode == 1:game_area = [[None] * GRID_WIDTH for _ in range(GRID_HEIGHT)]obstacle_timer = pygame.time.get_ticks()for _ in range(3):obstacle_row = [DARK_GRAY if random.random() < 0.3 else None for _ in range(GRID_WIDTH)]game_area.insert(0, obstacle_row)del game_area[-1]if hasattr(new_shape, "_initialized"):del new_shape._initializednew_shape()new_shape()current_state = GAME_STATES['PLAYING']# 事件处理for event in pygame.event.get():if event.type == pygame.QUIT:running = Falseif event.type == pygame.KEYDOWN:if event.key == pygame.K_LEFT:current_pos[0] -= 1if check_collision(current_shape, current_pos):current_pos[0] += 1if event.key == pygame.K_RIGHT:current_pos[0] += 1if check_collision(current_shape, current_pos):current_pos[0] -= 1if event.key == pygame.K_DOWN:current_pos[1] += 1if check_collision(current_shape, current_pos):current_pos[1] -= 1if event.key == pygame.K_UP:rotate_shape()if event.key == pygame.K_SPACE:  # 快速下落while not check_collision(current_shape, current_pos):current_pos[1] += 1current_pos[1] -= 1draw_current_shape()pygame.display.update()# 自动下落逻辑if current_time - fall_time > (fall_speed if special_effect != 'speed' else fall_speed // 2):current_pos[1] += 1fall_time = current_timeif check_collision(current_shape, current_pos):current_pos[1] -= 1# 经典模式立即合并if game_mode == 0:merge_shape()clear_lines()new_shape()# 生存模式特殊处理else:if (current_pos[1] + len(current_shape)) > 0:  # 底部进入可见区域merge_shape()clear_lines()new_shape()# 生存模式障碍生成if game_mode == 1:if current_time - obstacle_timer > 30000:new_row = [DARK_GRAY if random.random() < 0.7 else None for _ in range(GRID_WIDTH)]game_area.insert(0, new_row)del game_area[-1]obstacle_timer = current_time# 统一结束判断if check_collision(current_shape, current_pos) and special_effect != 'shield':# 经典模式:触顶即结束if game_mode == 0 and current_pos[1] < 0:running = False# 生存模式:完全进入后碰撞才结束elif game_mode == 1 and (current_pos[1] + len(current_shape)) >= 0:running = False# 特效处理if special_effect and effect_duration > 0:effect_duration -= clock.get_time()if effect_duration <= 0:special_effect = None# 绘制界面screen.fill(DARK_GRAY)draw_grid()draw_current_shape()draw_info_panel(score, highscore, next_shape, next_color, game_mode, special_effect)pygame.display.update()clock.tick(60)# 游戏结束处理if not running:if score > highscore:save_highscore(score)highscore = scorescreen.fill(BLACK)try:font = pygame.font.SysFont("simhei", 48)except:font = pygame.font.Font(None, 48)game_over_text = font.render("游戏结束", True, (255, 0, 0))text_rect = game_over_text.get_rect(center=(WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2 - 30))screen.blit(game_over_text, text_rect)score_text = font.render(f"最终得分: {score}", True, WHITE)score_rect = score_text.get_rect(center=(WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2 + 30))screen.blit(score_text, score_rect)pygame.display.update()pygame.time.wait(3000)current_state = GAME_STATES['GAME_OVER']if current_state == GAME_STATES['GAME_OVER']:if not show_start_screen(highscore):running = Falseelse:current_state = GAME_STATES['START']if __name__ == "__main__":game_loop()pygame.quit()

修改后的代码 

我测试了几次,主要之前出现的问题就是

  1. 游戏无法正常结束,当方块触碰到上方越界后,方块从最下方更新。
  2. 方块没有正常清除,当本行方块填满后他整体上移,而不是清除的效果。
  3. 游戏无法正常开始,方块下移的速度太快,开始游戏后直接结束了。
  4. 方块预览和实际出现的方块之间没有关系。

修改后游戏具备一下的特色功能:

下一个方块预览

  • 在右侧信息面板实时显示即将出现的方块形状与颜色
  • 实现方法:通过 draw_info_panel 方法中的预览方块绘制逻辑

速度递增机制

  • 得分每增加50分下落速度提升25ms(最大速度50ms)
  • 代码体现:self.fall_speed = max(50, 500 - (self.score // 50) * 25)

智能位置修正

  • 旋转时若超出边界自动尝试左右平移(rotate_shape 方法)
  • 特征:最多平移至边界,若仍碰撞则取消旋转
  • 优势:减少无效旋转操作挫败感

本地高分记录,使用 tetris_highscore.txt 文件存储历史最高分 功能点:

  • 启动时自动读取 (load_highscore)
  • 破纪录时自动保存 (save_highscore)

三维检测体系,check_collision 方法实现:

  • 底部越界检测 (py >= GRID_HEIGHT)
  • 侧边越界检测 (px < 0 or px >= GRID_WIDTH)
  • 方块重叠检测 (game_area[py][px] is not None)
# -*- coding: utf-8 -*-
import pygame
import random
import os# 初始化 Pygame
pygame.init()
os.environ['PYGAME_FREETYPE'] = '1'# 常量定义
HIGHSCORE_FILE = "tetris_highscore.txt"
WINDOW_HEIGHT = 600
GRID_SIZE = 30
GRID_WIDTH = 10
GRID_HEIGHT = 20
INFO_PANEL_WIDTH = 200
GAME_PANEL_WIDTH = GRID_WIDTH * GRID_SIZE
WINDOW_WIDTH = GAME_PANEL_WIDTH + INFO_PANEL_WIDTH# 颜色定义
COLORS = [(0, 255, 255),  # I型(255, 165, 0),  # L型(0, 0, 255),  # J型(255, 255, 0),  # O型(0, 255, 0),  # S型(255, 0, 255),  # T型(255, 0, 0)  # Z型
]
BLACK = (0, 0, 0)
DARK_GRAY = (40, 40, 40)
WHITE = (255, 255, 255)# 方块形状定义
SHAPES = [[[1, 1, 1, 1]],[[1, 0, 0], [1, 1, 1]],[[0, 0, 1], [1, 1, 1]],[[1, 1], [1, 1]],[[0, 1, 1], [1, 1, 0]],[[0, 1, 0], [1, 1, 1]],[[1, 1, 0], [0, 1, 1]]
]# 初始化窗口
screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption("俄罗斯方块")def load_font(size):try:return pygame.font.SysFont("simhei", size)except:return pygame.font.Font(None, size)def load_highscore():try:if os.path.exists(HIGHSCORE_FILE):with open(HIGHSCORE_FILE, 'r') as f:return int(f.read().strip() or 0)return 0except:return 0def save_highscore(score):with open(HIGHSCORE_FILE, 'w') as f:f.write(str(score))class GameState:def __init__(self):self.reset()def reset(self):self.game_area = [[None] * GRID_WIDTH for _ in range(GRID_HEIGHT)]self.score = 0self.highscore = load_highscore()# 仅初始化next_shapeself.next_shape = random.choice(SHAPES)self.next_color = random.choice(COLORS)self.fall_speed = 500self.running = Trueself.initialize_shapes()  # 在此方法中生成current_shapedef initialize_shapes(self):self.current_shape = self.next_shape  # 继承next_shapeself.current_color = self.next_color# 生成新next_shapeself.next_shape = random.choice(SHAPES)self.next_color = random.choice(COLORS)self.reset_position()def reset_position(self):shape_height = len(self.current_shape)self.current_pos = [GRID_WIDTH // 2 - len(self.current_shape[0]) // 2,-shape_height + 1  # 完全在游戏区域外生成]# 如果初始位置就碰撞,说明游戏结束if self.check_collision(self.current_shape, self.current_pos):self.game_over()def check_collision(self, shape, pos):for y in range(len(shape)):for x in range(len(shape[y])):if shape[y][x]:px = pos[0] + xpy = pos[1] + yif py >= GRID_HEIGHT:return Trueif px < 0 or px >= GRID_WIDTH:return Trueif py >= 0 and self.game_area[py][px] is not None:return Truereturn Falsedef rotate_shape(self):original_shape = self.current_shapeoriginal_pos = self.current_pos.copy()# 尝试旋转rotated = [list(row) for row in zip(*original_shape[::-1])]self.current_shape = rotated# 旋转后位置修正while self.check_collision(self.current_shape, self.current_pos):if self.current_pos[0] < 0:self.current_pos[0] += 1  # 右移else:self.current_pos[0] -= 1  # 左移if self.current_pos[0] < 0 or self.current_pos[0] >= GRID_WIDTH:self.current_shape = original_shape  # 还原形状self.current_pos = original_posbreakdef merge_shape(self):for y, row in enumerate(self.current_shape):for x, cell in enumerate(row):if cell:px = self.current_pos[0] + x  # 计算实际网格坐标py = self.current_pos[1] + y# 添加双重边界检查if 0 <= px < GRID_WIDTH and 0 <= py < GRID_HEIGHT:self.game_area[py][px] = self.current_colordef clear_lines(self):# 获取待消除行索引(从下往上检测)lines_to_clear = [i for i, row in enumerate(self.game_area) if all(cell is not None for cell in row)]if lines_to_clear:# 从下往上删除已满行(避免索引错位)for idx in reversed(lines_to_clear):del self.game_area[idx]# 在顶部补充新空行(数量=消除行数)new_rows = [[None] * GRID_WIDTH for _ in lines_to_clear]self.game_area = new_rows + self.game_area# 更新分数和速度self.score += len(lines_to_clear) * 100self.fall_speed = max(50, 500 - (self.score // 50) * 25)  # 更平缓的速度变化def draw_grid(self):for y in range(GRID_HEIGHT):for x in range(GRID_WIDTH):color = self.game_area[y][x]# 添加颜色类型安全检查if isinstance(color, tuple) and len(color) == 3:pygame.draw.rect(screen, color,(x * GRID_SIZE, y * GRID_SIZE,GRID_SIZE - 1, GRID_SIZE - 1))def draw_current_shape(self):for y, row in enumerate(self.current_shape):for x, cell in enumerate(row):if cell:px = (self.current_pos[0] + x) * GRID_SIZEpy = (self.current_pos[1] + y) * GRID_SIZEpygame.draw.rect(screen, self.current_color,(px, py, GRID_SIZE - 1, GRID_SIZE - 1))def draw_info_panel(self):font = load_font(24)pygame.draw.rect(screen, BLACK, (GAME_PANEL_WIDTH, 0, INFO_PANEL_WIDTH, WINDOW_HEIGHT))# 下一个方块title = font.render("下一个方块", True, WHITE)screen.blit(title, (GAME_PANEL_WIDTH + 10, 30))# 预览方块start_x = GAME_PANEL_WIDTH + (INFO_PANEL_WIDTH - len(self.next_shape[0]) * GRID_SIZE) // 2start_y = 100for y, row in enumerate(self.next_shape):for x, cell in enumerate(row):if cell:pygame.draw.rect(screen, self.next_color,(start_x + x * GRID_SIZE, start_y + y * GRID_SIZE, GRID_SIZE - 1, GRID_SIZE - 1))# 分数显示score_text = font.render(f"分数: {self.score}", True, WHITE)screen.blit(score_text, (GAME_PANEL_WIDTH + 10, 300))highscore_text = font.render(f"最高分: {self.highscore}", True, WHITE)screen.blit(highscore_text, (GAME_PANEL_WIDTH + 10, 350))def handle_input(self):for event in pygame.event.get():if event.type == pygame.QUIT:self.running = Falseif event.type == pygame.KEYDOWN:if event.key == pygame.K_LEFT:self.current_pos[0] -= 1if self.check_collision(self.current_shape, self.current_pos):self.current_pos[0] += 1elif event.key == pygame.K_RIGHT:self.current_pos[0] += 1if self.check_collision(self.current_shape, self.current_pos):self.current_pos[0] -= 1elif event.key == pygame.K_DOWN:self.current_pos[1] += 1if self.check_collision(self.current_shape, self.current_pos):self.current_pos[1] -= 1elif event.key == pygame.K_UP:self.rotate_shape()elif event.key == pygame.K_SPACE:while not self.check_collision(self.current_shape, self.current_pos):self.current_pos[1] += 1self.current_pos[1] -= 1def game_over(self):if self.score > self.highscore:save_highscore(self.score)screen.fill(BLACK)font = load_font(48)text = font.render("游戏结束", True, (255, 0, 0))text_rect = text.get_rect(center=(WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2 - 30))screen.blit(text, text_rect)score_text = font.render(f"得分: {self.score}", True, WHITE)score_rect = score_text.get_rect(center=(WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2 + 30))screen.blit(score_text, score_rect)pygame.display.update()pygame.time.wait(3000)self.running = Falsedef run(self):clock = pygame.time.Clock()fall_time = pygame.time.get_ticks()while self.running:current_time = pygame.time.get_ticks()self.handle_input()# 自动下落if current_time - fall_time > self.fall_speed:self.current_pos[1] += 1if self.check_collision(self.current_shape, self.current_pos):self.current_pos[1] -= 1self.merge_shape()self.clear_lines()self.initialize_shapes()  # 生成新方块# 游戏结束检测if self.check_collision(self.current_shape, self.current_pos):self.game_over()fall_time = current_time# 绘制界面screen.fill(DARK_GRAY)self.draw_grid()self.draw_current_shape()self.draw_info_panel()pygame.display.update()clock.tick(60)if __name__ == "__main__":game = GameState()game.run()pygame.quit()

 

总结

  1. 先使用DeepSeek生成可以执行的代码
  2. 使用Lingma优化代码
  3. 使用Lingma增加特色功能(建议不要一次性增加多个模块,可以一个个模块进行增加调试,对相对满意的模块可以先进行保存)
  4. 可以通过Ctrl+F调出搜索界面实现快速定位,可以询问Lingma解决警告和报错信息。

当然有Python基础的当然可以理解一下代码的逻辑然后进行修改,但是像我这种什么都不懂的同学就只能以AI为主,通过人工辅助询问一些问题来开发自己的小游戏,个人感觉非常消耗时间,最后如果有什么问题可以在评论区留言,欢迎各位大佬来批评指正!!!

http://www.xdnf.cn/news/269083.html

相关文章:

  • 回溯算法详解(Java实现):从组合到排列的全面解析
  • 方案解读:华为-智慧园区数字平台技术方案【附全文阅读】
  • 安卓基础(MediaProjection)
  • Qt/C++源码/实时视音频通话示例/极低延迟/可外网通话/画中画/支持嵌入式板子
  • 赛季7靶场 -- Checker --User flag
  • 一键部署自己的私域直播
  • 生物化学笔记:神经生物学概论08 运动系统 人类逐渐建立运动技能 不同层次的运动发起
  • 第43周:GAN总结
  • python下载
  • CGI 协议是否会具体到通讯报文?
  • 节流 和 防抖的使用
  • C++类_初始化列表
  • Linux进程控制与替换详解
  • MySQL视图
  • 数据分析业务拆解底层思维
  • VMware Pro17.6虚拟机工具软件安装教程
  • 重塑数学边界:人工智能如何引领数学研究的新纪元
  • 动态库与ELF加载
  • LabVIEW三轴电机控制
  • 如何实现一个虚拟dom
  • 5月3日星期六今日早报简报微语报早读
  • Vue3学习笔记2——路由守卫
  • 修改或禁用Cursor的全局搜索默认快捷键
  • CSS 优化与渲染性能调研
  • Java变量简介
  • 【2025软考高级架构师】——软件专利(12)
  • 【STM32】定时器输出比较模式
  • C# 方法(控制流和方法调用)
  • 论面向方面编程及其应用
  • 失败复盘:2077首发灾难的原因