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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 12:51:03