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

Telegram文本冒险Bot按钮失效求助:回调数据无法区分

解决Telegram Bot游戏中按钮回调数据失效问题

问题描述

我正在学习Python,想要将之前制作的终端文本游戏改成一个简单的Telegram Bot。目前遇到了问题:当游戏推进到第6个房间(熊房间)时,按钮完全失效——无论点击哪个按钮,都会发送相同的回调数据,脚本没有崩溃但无法进入下一游戏状态。我测试到该房间后就无法继续,尝试替换该位置的房间,发现无论设置哪个房间,程序都无法区分不同的回调数据,仿佛所有按钮都是同一个。我猜测可能是函数过大导致的,请问该如何解决?

附代码

from telebot import TeleBot, types
from random import randint
import random

# 注意:需补充Bot Token与全局变量初始化
bot = TeleBot("你的Bot Token")
states = {}
inventories = {}
pictures = {}  # 存储各状态对应的图片ID/链接

@bot.message_handler(commands=["start"])
def start_game(message):
    user = message.chat.id
    states[user] = 0
    inventories[user] = []
    bot.send_message(user, "Добро пожаловать в игру!")
    process_state(user, states[user], inventories[user])

@bot.callback_query_handler(func=lambda call: True)
def user_answer(call):
    user = call.message.chat.id
    process_answer(user, call.data)

def process_state(user, state, inventory):
    kb = types.InlineKeyboardMarkup()
    bot.send_photo(user, pictures[state])
    # 死亡状态
    if state == -1:
        bot.send_message(user, "Вы проиграли. Начать заново: /start")
        return
    # 初始状态(4扇门)
    elif state == 0:
        kb.add(types.InlineKeyboardButton(text="пойти направо", callback_data="1"))
        kb.add(types.InlineKeyboardButton(text="пойти налево", callback_data="2"))
        kb.add(types.InlineKeyboardButton(text="пойти назад", callback_data="3"))
        kb.add(types.InlineKeyboardButton(text="пойти прямо", callback_data="4"))
        bot.send_message(user, "Вы в оказались в темном подземелье, перед вами 4 прохода.", reply_markup=kb)
    # 此处省略11个状态的处理逻辑

def process_answer(user, answer):
    # 初始状态处理
    if states[user] == 0:
        if answer == "1":
            # 进入地下湖房间
            states[user] = 1
        elif answer == "3":
            # 玩家死亡,设置状态为-1
            states[user] = -1
        elif answer == "4":
            states[user] = 2
        else:
            # 尝试打开左侧的门
            if "key" in inventories[user]:
                bot.send_message(user,
                                 "Перед вами закрытая дверь. Вы пробуете открыть ее ключем, и дверь поддается. За ней блестит артефакт, вы не знаете зачем он вам, но берете с собой на всякий случай.")
                states[user] = 0
                inventories[user].append("artifact")
            else: 
                bot.send_message(user, "Перед вами закрытая дверь, и, кажется, без ключа ее не открыть. Придется вернуться обратно.")
                states[user] = 0  # 返回初始状态
    # 此处省略11个状态的回答处理逻辑
    process_state(user, states[user], inventories[user])

bot.polling(none_stop=True)

解决方案

1. 确保回调数据唯一性

检查第6个房间对应的按钮创建代码,给每个按钮设置唯一的callback_data,比如用"6_run"、"6_attack"这种带状态后缀的格式,避免所有按钮使用相同的回调值。

2. 拆分臃肿函数,降低逻辑复杂度

把大的process_state和process_answer拆分为按状态划分的小函数,示例:

# 单独处理第6个房间的按钮创建
def create_state_6_keyboard():
    kb = types.InlineKeyboardMarkup()
    kb.add(types.InlineKeyboardButton(text="Убежать от медведя", callback_data="6_run"))
    kb.add(types.InlineKeyboardButton(text="Подойти к медведю", callback_data="6_approach"))
    kb.add(types.InlineKeyboardButton(text="Использовать мясо", callback_data="6_meat"))
    return kb

# 单独处理第6个房间的回答逻辑
def handle_state_6_answer(user, answer):
    if answer == "6_run":
        states[user] = 0  # 返回初始房间
        bot.send_message(user, "Вы успешно убежали от медведя!")
    elif answer == "6_approach":
        states[user] = -1  # 死亡
    elif answer == "6_meat":
        if "meat" in inventories[user]:
            states[user] = 7  # 进入下一个房间
            inventories[user].remove("meat")
            bot.send_message(user, "Медведь съел мясо и отвлекся! Вы проходите дальше.")
        else:
            bot.send_message(user, "У вас нет мяса, чтобы отвлечь медведя!")
            states[user] = 6  # 留在当前房间

3. 必须回复回调查询

在user_answer函数中添加bot.answer_callback_query(call.id),否则Telegram客户端会认为请求未处理,重复发送回调数据导致逻辑混乱:

@bot.callback_query_handler(func=lambda call: True)
def user_answer(call):
    user = call.message.chat.id
    # 回复回调查询,避免客户端重复请求
    bot.answer_callback_query(call.id)
    process_answer(user, call.data)

4. 添加调试日志排查问题

在关键位置打印日志,确认收到的回调数据和当前用户状态是否正确:

def user_answer(call):
    user = call.message.chat.id
    print(f"用户{user} 当前状态: {states.get(user, '未知')}, 收到回调数据: {call.data}")
    bot.answer_callback_query(call.id)
    process_answer(user, call.data)

5. 检查全局变量初始化

确保states、inventories、pictures和bot实例在脚本开头正确初始化,避免因未定义变量导致的隐性错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 01:33:11