You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何为现有Discord骰子机器人实现仿Avrae的单次指令多枚骰子投掷功能?

实现多枚骰子投掷功能的完整方案

嘿,我明白你想把现有的骰子命令改成像Avrae那样支持一次投多枚的需求,这其实不难,咱们一步步来调整代码:

第一步:调整命令参数接收方式

原来的参数拆分不太适配多骰子格式,我们改成接收一个完整的骰子表达式字符串(比如5 d203d6),这样灵活性更高。把命令定义改成:

@client.command(aliases=['r', 'dado', 'dice'])
async def roll(ctx, *, dice_str: str = 'd20'):

这里用*表示接收所有后续输入作为单个参数,默认值设为d20,方便用户直接输-r就能投1枚d20。

第二步:解析骰子表达式

用正则表达式来提取骰子数量和面数,不管用户输入5d20还是5 d20都能精准识别。添加匹配逻辑:

import re
# 匹配格式:数字+d+数字,中间允许有空格
match = re.match(r'(\d*)\s*d(\d+)', dice_str.lower())
if not match:
    await ctx.send(f'{ctx.author.mention} ❌ 格式不对哦!请用类似 `-r 5 d20` 或 `-r 3d6` 的格式~')
    return

# 提取数量和面数,没写数量默认投1枚
count = int(match.group(1)) if match.group(1) else 1
sides = int(match.group(2))

第三步:执行多枚骰子投掷

循环生成每个骰子的结果,同时保留你原来的暴击/大失败加粗效果:

rolls = []
total = 0
for _ in range(count):
    num = random.randint(1, sides)
    # 对1和当前骰子的最大面数加粗(如果是d20就保留1和20的特殊标记)
    if (sides == 20 and (num == 1 or num == 20)) or (num == 1 or num == sides):
        rolls.append(f'**{num}**')
    else:
        rolls.append(str(num))
    total += num

第四步:格式化输出

按照你想要的样式拼接结果,清晰展示每枚骰子的数值和总和:

# 把结果列表转成带括号的字符串
rolls_str = f'({", ".join(rolls)})'
await ctx.send(f'{ctx.author.mention} 🎇 \n**{count}枚D{sides}骰子结果**: {rolls_str}\n**总和**: {total}')

完整修改后的代码

整合所有逻辑,同时修正原代码里的小bug(比如total == '1'的赋值错误):

import random
import re
from discord.ext import commands

@client.command(aliases=['r', 'dado', 'dice'])
async def roll(ctx, *, dice_str: str = 'd20'):
    # 解析骰子表达式
    match = re.match(r'(\d*)\s*d(\d+)', dice_str.lower())
    if not match:
        await ctx.send(f'{ctx.author.mention} ❌ 格式错误!请使用 `-r <数量> d<面数>` 或 `-r <数量>d<面数>`,例如 `-r 5 d20`、`-r 3d6`。')
        return
    
    count = int(match.group(1)) if match.group(1) else 1
    sides = int(match.group(2))
    
    # 处理非法数值
    if count <= 0 or sides < 2:
        await ctx.send(f'{ctx.author.mention} ❌ 骰子数量必须大于0,面数至少为2哦!')
        return
    
    # 执行投掷
    rolls = []
    total = 0
    for _ in range(count):
        num = random.randint(1, sides)
        # 对1和最大面数加粗
        if (sides == 20 and (num == 1 or num == 20)) or (num == 1 or num == sides):
            rolls.append(f'**{num}**')
        else:
            rolls.append(str(num))
        total += num
    
    # 格式化输出
    rolls_str = f'({", ".join(rolls)})'
    await ctx.send(f'{ctx.author.mention} 🎇 \n**{count}枚D{sides}骰子结果**: {rolls_str}\n**总和**: {total}')

额外优化小建议

如果之后想扩展功能,可以考虑支持带 modifier 的格式(比如-r 2d6+3),或者同时投掷多组不同骰子(比如-r 2d6 + 3d8),这些都可以通过扩展正则匹配逻辑来实现~

内容的提问来源于stack exchange,提问作者日本Jorge

火山引擎 最新活动