如何修复Wordle克隆Telegram Bot有效输入仍触发「无效输入」的问题?
问题根源
你的代码核心问题是错误地在onUpdateReceived里使用死循环。Telegram LongPollingBot是事件驱动模型:每收到一条用户消息,就会调用一次onUpdateReceived方法。你在用户输入"Wordle"后启动的while(true)循环,会一直复用当前的update对象(也就是用户输入"Wordle"的那条消息),永远获取不到用户后续输入的新单词,导致playerWord始终是"Wordle",自然通不过checkString校验,反复触发"invalid input"提示。
另外,turns、last这些游戏状态变量是onUpdateReceived的局部变量,每次收到新消息都会被重置,根本无法保存游戏进度。
修复方案
1. 定义游戏状态类
先创建一个类来保存每个聊天的游戏状态:
data class GameState( val targetWord: String, var turns: Int = 0, var matchedLetters: String = "" )
2. 全局维护游戏状态映射
在Bot类里添加一个Map,用来记录每个聊天ID对应的游戏状态:
class MyAmazingBot : TelegramLongPollingBot() { // 保存每个聊天的游戏状态,key是chatId字符串 private val activeGames = mutableMapOf<String, GameState>() // 省略getBotToken()等必要方法... }
3. 重构onUpdateReceived逻辑
移除死循环,改成事件驱动的分支处理:
override fun onUpdateReceived(update: Update) { if (!update.hasMessage() || !update.message.hasText()) return val chatId = update.message.chatId.toString() val input = update.message.text.trim() val message = SendMessage(chatId, "") // 分支1:用户启动游戏 if (input == "Wordle") { val candidateWordsFile = "candidate words file" val targetWord = getRandomWord(candidateWordsFile) // 初始化游戏状态 activeGames[chatId] = GameState(targetWord) message.text = "Please enter a 5-letter word: " execute(message) return } // 分支2:用户输入/exit退出游戏 if (input == "/exit") { activeGames.remove(chatId) message.text = "The game is over." execute(message) return } // 分支3:处理游戏中的用户猜测 val gameState = activeGames[chatId] ?: return // 不在游戏中则直接返回 // 校验输入格式 if (!checkString(input)) { message.text = "Invalid input. Please enter a valid 5-letter word." execute(message) return } // 校验单词是否在词典中 val dictionaryFile = "dictionary file" if (!File(dictionaryFile).readLines().contains(input)) { message.text = "The input word isn't included in my words list." execute(message) return } gameState.turns++ // 猜对了的情况 if (input == gameState.targetWord) { message.text = "Correct! The solution was found after ${gameState.turns} tries." execute(message) activeGames.remove(chatId) // 结束游戏 return } // 未猜对,生成反馈 val matchResult = findMatches(input, gameState.targetWord) val incorrectPositions = matchResult.substring(0, 5) gameState.matchedLetters += matchResult.substring(5) val uniqueMatchedLetters = gameState.matchedLetters.toSet().sorted().joinToString("") message.text = "Matching letters: $uniqueMatchedLetters\nIncorrect positions: $incorrectPositions" execute(message) }
关键修改点说明
- 移除了
while(true)死循环,改用事件驱动的分支判断,每次用户输入都会触发对应的逻辑 - 用
activeGamesMap保存每个聊天的游戏状态,避免每次调用onUpdateReceived时重置状态 - 明确区分了「启动游戏」「退出游戏」「游戏中猜测」三种场景,逻辑更清晰
- 每次处理完用户输入后直接返回,不会阻塞后续的消息处理
内容的提问来源于stack exchange,提问作者Condor mitnick
相关产品推荐
相关产品推荐

