discord.py开发blackjack命令点击hit表情后无响应如何解决
问题原因分析
- 仅执行了单次反应监听:代码仅在初始化游戏后调用了一次
await client.wait_for('reaction_add', check=check),只能响应用户的第一次表情点击,处理完hit逻辑后没有重新发起监听,函数执行完毕后就停止了所有交互处理。 - hit后新消息未添加交互表情:你在hit逻辑中发送了更新手牌后的新embed消息,但没有给这条新消息添加✅、❎表情,用户无法在新消息上触发交互,点击旧消息的表情也不会被后续逻辑识别。
- 额外隐患:大量使用全局变量存储游戏状态,如果有多个用户同时开启游戏,会出现状态冲突的问题。
修复方案
把反应监听、处理的逻辑套入while playing:循环,每次发送新的游戏消息后都补充添加对应表情,同时优化check函数校验消息来源,避免旧消息干扰,同时可以把全局变量改为函数内部变量避免多用户冲突。
修改后的完整代码如下:
import asyncio @client.command() async def blackjack(ctx): if ctx.author == client.user: return currentplayer = ctx.author playing = True deck = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] * 4 player_hand = deal(deck) dealer_hand = deal(deck) hit = '✅' stand = '❎' valid_reactions = ['✅', '❎'] # 初始化第一条游戏消息 msg = discord.Embed(title = f"<:blackjack:883416171834126366> {ctx.author.name}'s Blackjack game for $0", description = f"**{ctx.author.name}'s Hand:** {player_hand} \n Total: {total(player_hand)}\n \n **Dealer's Hand:** [{dealer_hand[0]}, ?]", color = 0xFFFF00) msg.add_field(name = chr(173), value = "React with ✅ to **hit** or ❎ to **stand**.") lobby = await ctx.send(embed=msg) await lobby.add_reaction("✅") await lobby.add_reaction("❎") # 循环监听交互,游戏未结束就持续监听 while playing: def check(reaction, user): # 额外校验反应的消息是当前最新的游戏消息,避免旧消息干扰 return user == ctx.author and str(reaction.emoji) in valid_reactions and reaction.message.id == lobby.id try: reaction, user = await client.wait_for('reaction_add', check=check, timeout=120) # 增加超时逻辑避免进程卡住 except asyncio.TimeoutError: await ctx.send("游戏超时已自动结束") playing = False endgame() return if str(reaction.emoji) == hit: draw(deck, player_hand) # 更新消息后补充添加交互表情 msg = discord.Embed(title = f"<:blackjack:883416171834126366> {ctx.author.name}'s Blackjack game for $0", description = f"**{ctx.author.name}'s Hand:** {player_hand} \n Total: {total(player_hand)}\n \n **Dealer's Hand:** [{dealer_hand[0]}, ?]", color = 0xFFFF00) msg.add_field(name = chr(173), value = "React with ✅ to **hit** or ❎ to **stand**.") lobby = await ctx.send(embed=msg) await lobby.add_reaction("✅") await lobby.add_reaction("❎") if total(player_hand) > 21: msg = discord.Embed(description = f"{ctx.author.name} busts! Dealer wins!") await ctx.send(embed = msg) playing = False endgame() return elif str(reaction.emoji) == stand: # 原有stand逻辑保持不变即可 while total(dealer_hand) < 17: draw(deck, dealer_hand) msg = discord.Embed(description = f"Dealer hits...") await ctx.send(embed = msg) if total(dealer_hand) > 21: msg = discord.Embed(title = f"<:blackjack:883416171834126366> {ctx.author.name}'s Blackjack game for $0", description = f"**{ctx.author.name}'s Hand:** {player_hand} \n Total: {total(player_hand)}\n \n **Dealer's Hand:** {dealer_hand}", color = 0xFFFF00) await ctx.send(embed=msg) msg = discord.Embed(description = f"Dealer busts! {ctx.author.name} wins!") await ctx.send(embed = msg) playing = False endgame() return msg = discord.Embed(title = f"<:blackjack:883416171834126366> {ctx.author.name}'s Blackjack game for $0", description = f"**{ctx.author.name}'s Hand:** {player_hand} \n Total: {total(player_hand)}\n \n **Dealer's Hand:** {dealer_hand} \n Total: {total(dealer_hand)}", color = 0xFFFF00) await ctx.send(embed=msg) if total(dealer_hand) > total(player_hand) and total(dealer_hand) <= 21: msg = discord.Embed(description = f"Dealer wins!") await ctx.send(embed = msg) playing = False endgame() return elif total(dealer_hand) == total(player_hand) and total(dealer_hand) <= 21: msg = discord.Embed(description = f"{ctx.author.name} and the Dealer tied.") await ctx.send(embed = msg) endgame() return else: msg = discord.Embed(description = f"{ctx.author.name} wins!") await ctx.send(embed = msg) playing = False endgame() return
如果不想每次发送新消息,也可以把lobby = await ctx.send(embed=msg)改为await lobby.edit(embed=msg)直接修改原有消息,交互体验更流畅。
内容的提问来源于stack exchange,提问作者Anthony
相关产品推荐
相关产品推荐

