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

如何使用Discord.py开发21大冒险游戏 实现轮流输入与数字校验

21大冒险Discord机器人开发指南

核心功能实现

1. 玩家轮流操作机制

拿到通过反应收集的players列表后,首先过滤掉机器人自身账号,避免把机器人算入玩家队列。之后维护一个current_player_idx整数变量,初始值为0,每完成一名玩家的操作后将变量加1,再对玩家总数取模,即可循环按顺序调度玩家。
注意不要使用同步的time.sleep(10),会阻塞整个机器人的所有指令响应,替换为await asyncio.sleep(10)异步等待。

2. 玩家输入校验规则

维护两个游戏状态变量:last_num记录上一名玩家输出的最后一个数字,初始值为0;current_round记录当前轮次。
每条玩家输入需要同时满足以下条件才视为有效:

  • 发送消息的用户为当前轮次指定的玩家,且消息发送频道为游戏所在频道
  • 消息内容按分隔符(支持顿号、空格)拆分后可转为1-3个正整数
  • 拆分后的第一个数字等于last_num + 1
  • 所有数字为连续递增序列,无跳数、无重复
  • 若数字序列包含21,当前玩家直接判定为落败

修正后可运行代码

import asyncio
import discord
from discord.ext import commands

class GameCog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command()
    async def tod(self, ctx, user: discord.Member = None):
        '''21大冒险游戏'''
        the_author = ctx.author
        channel = ctx.channel

        # 邀请逻辑
        if user is None:
            embed = discord.Embed(title="21大冒险游戏", color=discord.Colour.orange(),
                                  description=f"{the_author.mention} 正在邀请大家玩21大冒险!\n\n点击下方✅反应参与游戏,10秒后自动开始。")
        elif user != the_author and not user.bot:
            embed = discord.Embed(title="21大冒险游戏", color=discord.Colour.orange(),
                                  description=f"{the_author.mention} 邀请 {user.mention} 玩21大冒险!\n\n点击下方✅反应参与游戏,10秒后自动开始。")
        else:
            await ctx.send(embed=discord.Embed(title="错误:不能邀请自己或者机器人参与游戏!"))
            return
        
        msg = await channel.send(embed=embed)
        await msg.add_reaction("✅")

        # 异步等待10秒收集参与者
        await asyncio.sleep(10)
        # 刷新消息状态,获取最新反应用户
        msg = await channel.fetch_message(msg.id)
        reaction = msg.reactions[0]
        players = [user async for user in reaction.users() if not user.bot]
        
        if len(players) < 2:
            await channel.send(embed=discord.Embed(title="参与人数不足2人,游戏取消"))
            return

        # 初始化游戏状态
        current_player_idx = 0
        last_num = 0
        game_over = False

        while not game_over:
            current_player = players[current_player_idx]
            await channel.send(f"轮到 {current_player.mention} 输入数字,请输入1-3个连续数字,首个数字需为 {last_num + 1}")

            # 校验函数
            def check(message):
                if message.author != current_player or message.channel != channel:
                    return False
                # 尝试拆分转数字
                try:
                    # 支持顿号、空格分隔
                    parts = message.content.replace('、', ' ').split()
                    nums = [int(p) for p in parts]
                except:
                    return False
                # 校验数量
                if len(nums) <1 or len(nums)>3:
                    return False
                # 校验首数字
                if nums[0] != last_num + 1:
                    return False
                # 校验连续
                for i in range(len(nums)-1):
                    if nums[i+1] != nums[i] +1:
                        return False
                # 校验是否超过21
                if nums[-1] >21:
                    return False
                return True

            try:
                resp = await self.bot.wait_for('message', check=check, timeout=30)
            except asyncio.TimeoutError:
                await channel.send(f"{current_player.mention} 超时未作答,判负!")
                game_over = True
                break

            # 处理有效输入
            nums = [int(p) for p in resp.content.replace('、', ' ').split()]
            # 判断是否踩中21
            if 21 in nums:
                await channel.send(f"{current_player.mention} 说出了21,本轮游戏落败!请接受大冒险惩罚~")
                game_over = True
                break
            # 更新状态
            last_num = nums[-1]
            # 切换到下一名玩家
            current_player_idx = (current_player_idx + 1) % len(players)

Discord.py开发小技巧

  • 所有等待、延迟操作都使用asyncio提供的异步方法,避免使用同步阻塞方法导致机器人无响应
  • 收集反应用户时,discord.py v2.0以上版本需要用异步迭代方式获取用户,不要用已经废弃的flatten()方法
  • 校验函数要同时校验发送者、频道两个维度,避免其他频道的消息或者其他玩家的消息干扰游戏流程
  • 游戏相关的状态变量都定义在游戏函数内部,不要用全局变量,避免同时开多局游戏时状态冲突

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 09:18:04