You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python开发2048游戏触发RecursionError递归深度超限问题

报错说明

你遇到的RecursionError: maximum recursion depth exceeded in comparison是递归深度溢出错误:Python对函数递归调用的最大深度有默认限制(通常为1000层),当函数无终止条件反复调用自身、或者多个函数形成循环调用链时,调用栈会持续堆叠超过上限,就会触发这个报错。

触发原因

你的代码里有三处逻辑直接导致了无限递归:

  • game()和random_n()形成循环调用链:game()函数末尾判断变量不存在时会调用random_n(),而random_n()函数末尾无条件调用game(),两者形成game() -> random_n() -> game() -> random_n()...的无限循环,调用栈会快速堆满。
  • random_n()内部的错误自递归:你声明了n为全局变量,却用if not 'n' in locals()判断变量是否存在——locals()仅返回当前函数内部的局部变量字典,全局变量不会出现在其中,这个判断永远为真,每次进入函数都会执行n=0后再调用一次random_n(),平白增加调用栈层数。
  • keybinds()的自递归死循环:你在按键判断的else分支直接调用keybinds()自身,只要用户按下的按键不在你列出的WASD、方向键范围内,就会无限递归调用该函数,瞬间打满递归深度。

另外你在主事件循环内部定义keybinds()函数的写法也不合理,每次触发按键事件都会重新定义一次函数,带来不必要的性能开销。

修复方案
  • 拆分函数职责,切断循环调用链:game()仅负责棋盘、UI的绘制和游戏状态初始化,不要在函数内部反复触发random_n();random_n()仅负责生成随机数值、选择空白格子放置新方块,不要在函数末尾调用game()。
  • 移除错误的变量存在性判断:全局变量直接在游戏启动阶段完成初始化赋值,不需要在函数内部通过locals()判断是否存在,同时删掉random_n()内部无意义的自递归调用。
  • 移除keybinds()中else分支的自调用逻辑:未匹配到预设按键时直接跳过即可,不需要递归调用函数;同时把keybinds()的定义移到全局作用域,不要放在事件循环内部重复定义。
  • 调整初始方块生成逻辑:游戏首次启动时固定生成2个初始方块即可,不需要通过递归反复触发生成。

修复后的核心代码参考

import pygame
from random import randint

pygame.init()
w = 640
h = 780
screen = pygame.display.set_mode((w, h))
pygame.display.set_caption('2048')

# 全局变量统一在初始化阶段赋值
tile_number = 0
init_tile_count = 0
play = 0
# 此处省略原有颜色、字体、素材加载的定义代码

def random_n():
    global tile_number
    num = randint(0, 100)
    tile_number = 2 if num > 10 else 4
    # 此处补充选择空白棋盘格、绘制新方块的逻辑
    pygame.display.update()

def game():
    global init_tile_count
    # 此处省略原有棋盘、UI按钮的绘制代码
    # 首次启动时生成2个初始方块即可
    while init_tile_count < 2:
        random_n()
        init_tile_count += 1

# 把按键处理函数移到全局作用域定义
def keybinds(event):
    if event.key == pygame.K_w:
        print("Pressed W")
    elif event.key == pygame.K_a:
        print("Pressed A")
    elif event.key == pygame.K_s:
        print("Pressed S")
    elif event.key == pygame.K_d:
        print("Pressed D")
    elif event.key == pygame.K_UP:
        print("Pressed UP")
    elif event.key == pygame.K_LEFT:
        print("Pressed LEFT")
    elif event.key == pygame.K_DOWN:
        print("Pressed DOWN")
    elif event.key == pygame.K_RIGHT:
        print("Pressed RIGHT")
    # 按键对应移动逻辑执行完成后,生成1个新方块
    random_n()

# 主事件循环
while True:
    events = pygame.event.get()
    for event in events:
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            # 此处省略原有鼠标点击按钮的判断逻辑
            pass
        if event.type == pygame.KEYDOWN and play == 1:
            keybinds(event)

内容的提问来源于stack exchange,提问作者shoewis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 12:57:17