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

使用discord.py开发Discord猜数字小游戏时遇参数错误

解决Discord机器人猜数字游戏的报错问题

首先看你的错误信息:Destination must be Channel... Received NoneType,这是因为你在on_message事件里用了drone.say()——这个方法是命令上下文专属的,它需要从commands.Context对象里获取频道信息,而在on_message事件中直接调用drone.say()的话,没有对应的上下文,自然找不到频道,就返回了None。

除此之外,你的代码还有几个关键问题:

  • 在chat命令函数内部嵌套定义on_message事件,这会导致事件注册混乱,Discord.py会覆盖之前的事件处理逻辑,运行时肯定出问题。
  • wait_for_message(int)的用法完全错误,这个方法的参数不是类型,而是用于过滤消息的检查函数。
  • 没有处理用户输入非数字的情况,容易触发ValueError。

修正后的完整代码示例

我帮你重构了代码,把猜数字功能做成一个独立的命令(或者你也可以改成on_message触发,这里用命令更规范):

import random
import discord
from discord.ext import commands
import asyncio

drone = commands.Bot(command_prefix="!")

# 猜数字命令
@drone.command(name="guess", help="猜数字游戏:1-100,有7次机会")
async def guess_game(ctx):
    z = random.randint(1, 100)
    await ctx.send("我想了一个1到100之间的数字,来猜吧!你有7次机会~")
    
    for gT in range(1, 8):
        await ctx.send(f"第{gT}次猜测:输入你的数字")
        
        # 等待用户输入,只接收发起命令的用户的消息,且内容是数字
        def check(msg):
            return msg.author == ctx.author and msg.content.isdigit()
        
        try:
            guess_msg = await drone.wait_for("message", check=check, timeout=30.0)
            g = int(guess_msg.content)
        except asyncio.TimeoutError:
            await ctx.send("超时啦!游戏结束,正确数字是:" + str(z))
            return
        except ValueError:
            await ctx.send("请输入有效的数字!")
            continue  # 跳过当前循环,不消耗次数
        
        if g > z:
            await ctx.send("太大啦!")
        elif g < z:
            await ctx.send("太小啦!")
        else:
            await ctx.send(f"恭喜你猜对了!就是{z}!你用了{gT}次机会~")
            return
    
    # 循环结束没猜对
    await ctx.send(f"7次机会用完啦,正确数字是:{str(z)}")

# 启动机器人(记得替换成你的token)
drone.run("YOUR_BOT_TOKEN")

关键修改点说明

  1. 移除嵌套的事件定义:把猜数字功能做成独立的!guess命令,避免事件和命令的逻辑混乱。
  2. 用ctx.send()替代drone.say()/drone.send_message():在命令里使用ctx(上下文)的send方法,能正确获取当前频道,不会出现NoneType错误。
  3. 修正wait_for的用法:用wait_for("message")替代旧的wait_for_message(旧方法在新版本已废弃),并通过check函数确保只接收发起命令的用户的数字输入。
  4. 增加异常处理:处理超时和非数字输入的情况,让游戏更健壮。
  5. 优化循环逻辑:猜对后直接return结束命令,不用等到循环结束。

如果你还是想通过on_message事件触发(比如用户发"guess number"时启动游戏),可以这样写:

@drone.event
async def on_message(message):
    # 避免机器人自己触发
    if message.author == drone.user:
        return
    
    if message.content.lower().startswith("guess number"):
        z = random.randint(1, 100)
        await message.channel.send("我想了一个1到100之间的数字,来猜吧!你有7次机会~")
        
        for gT in range(1, 8):
            await message.channel.send(f"第{gT}次猜测:输入你的数字")
            
            def check(msg):
                return msg.author == message.author and msg.content.isdigit()
            
            try:
                guess_msg = await drone.wait_for("message", check=check, timeout=30.0)
                g = int(guess_msg.content)
            except asyncio.TimeoutError:
                await message.channel.send("超时啦!游戏结束,正确数字是:" + str(z))
                return
            except ValueError:
                await message.channel.send("请输入有效的数字!")
                continue
            
            if g > z:
                await message.channel.send("太大啦!")
            elif g < z:
                await message.channel.send("太小啦!")
            else:
                await message.channel.send(f"恭喜你猜对了!就是{z}!你用了{gT}次机会~")
                return
        
        await message.channel.send(f"7次机会用完啦,正确数字是:{str(z)}")
    
    # 必须加这一行,否则命令会失效
    await drone.process_commands(message)

注意:如果用on_message处理,最后一定要加await drone.process_commands(message),否则你的其他命令(比如!chat)会无法触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:07:44