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
相关产品推荐
相关产品推荐

