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

如何用discord.py实现余额命令?求助搭建投注游戏货币系统

实现Discord机器人的货币系统与余额命令

嘿,别用纯TXT文件来记录成员数据啦——这真的不是个好选择!TXT完全没有结构化设计,读写效率低,碰到多个用户同时操作的时候还容易出现数据错乱的问题。更推荐用结构化的存储方式,比如Python内置的sqlite3数据库(不用额外装依赖,轻量又好用),或者JSON文件(比TXT好维护太多)。下面给你一步步拆解实现方案:

一、用SQLite3构建货币系统(最推荐长期使用)

SQLite是轻量级的本地数据库,特别适合小型Discord机器人,不需要额外部署,直接就能用。

1. 先初始化数据库

在机器人启动时创建一个存储用户余额的表:

import discord
from discord.ext import commands
import sqlite3

# 初始化机器人,记得开启必要的intents
bot = commands.Bot(command_prefix="!", intents=discord.Intents.all())

def init_database():
    # 连接(不存在则创建)名为economy.db的数据库
    conn = sqlite3.connect("economy.db")
    cursor = conn.cursor()
    # 创建用户表:用户ID(唯一标识)、余额(默认100初始币)、注册时间
    cursor.execute('''CREATE TABLE IF NOT EXISTS users
                     (user_id INTEGER PRIMARY KEY, 
                      balance INTEGER DEFAULT 100,
                      join_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP)''')
    conn.commit()
    conn.close()

@bot.event
async def on_ready():
    init_database()
    print(f"✅ 机器人已登录:{bot.user}")

2. 写核心工具函数

封装几个常用的数据库操作函数,方便后续命令调用:

def get_user_balance(user_id):
    conn = sqlite3.connect("economy.db")
    cursor = conn.cursor()
    cursor.execute("SELECT balance FROM users WHERE user_id = ?", (user_id,))
    result = cursor.fetchone()
    conn.close()
    # 如果用户是第一次使用,自动创建记录并返回初始余额
    if not result:
        add_new_user(user_id)
        return 100
    return result[0]

def add_new_user(user_id):
    conn = sqlite3.connect("economy.db")
    cursor = conn.cursor()
    # 用INSERT OR IGNORE避免重复添加
    cursor.execute("INSERT OR IGNORE INTO users (user_id) VALUES (?)", (user_id,))
    conn.commit()
    conn.close()

def update_user_balance(user_id, amount):
    conn = sqlite3.connect("economy.db")
    cursor = conn.cursor()
    # 确保用户存在后再更新余额
    add_new_user(user_id)
    cursor.execute("UPDATE users SET balance = balance + ? WHERE user_id = ?", (amount, user_id))
    conn.commit()
    conn.close()

3. 实现余额查询命令

做一个支持查询自己或他人余额的命令,用Embed让消息更美观:

@bot.command(name="balance", aliases=["bal", "余额"])
async def check_balance(ctx, member: discord.Member = None):
    # 默认查询自己,指定成员则查询对方
    target_user = member or ctx.author
    user_balance = get_user_balance(target_user.id)
    
    embed = discord.Embed(
        title=f"💸 {target_user.display_name} 的余额",
        description=f"当前持有:**{user_balance}** 硬币",
        color=discord.Color.green()
    )
    embed.set_thumbnail(url=target_user.display_avatar.url)
    await ctx.send(embed=embed)

二、如果想试试轻量的JSON方案

要是你暂时不想碰数据库,JSON文件比TXT友好太多,结构化存储,读写也简单:

1. 初始化JSON文件

import json
import os

def init_economy_json():
    if not os.path.exists("economy.json"):
        # 初始为空字典
        with open("economy.json", "w", encoding="utf-8") as f:
            json.dump({}, f, indent=4)

@bot.event
async def on_ready():
    init_economy_json()
    print(f"✅ 机器人已登录:{bot.user}")

2. 工具函数与余额命令

def get_balance_json(user_id):
    with open("economy.json", "r", encoding="utf-8") as f:
        data = json.load(f)
    # 不存在则返回初始100币
    return data.get(str(user_id), 100)

def update_balance_json(user_id, amount):
    with open("economy.json", "r", encoding="utf-8") as f:
        data = json.load(f)
    user_str = str(user_id)
    # 新用户自动初始化余额
    if user_str not in data:
        data[user_str] = 100
    data[user_str] += amount
    # 写入更新后的数据
    with open("economy.json", "w", encoding="utf-8") as f:
        json.dump(data, f, indent=4, ensure_ascii=False)

@bot.command(name="balance", aliases=["bal", "余额"])
async def check_balance(ctx, member: discord.Member = None):
    target_user = member or ctx.author
    user_balance = get_balance_json(target_user.id)
    await ctx.send(f"💸 {target_user.display_name} 的余额:**{user_balance}** 硬币")

三、扩展到你的投注游戏

有了货币系统,投注游戏的逻辑就顺理成章了,举个简单的骰子投注例子:

import random

@bot.command(name="bet", aliases=["投注"])
async def dice_bet(ctx, amount: int, guess: int):
    # 基础校验
    if amount <= 0:
        await ctx.send("⚠️ 投注金额必须大于0哦!")
        return
    user_balance = get_user_balance(ctx.author.id)
    if user_balance < amount:
        await ctx.send("❌ 你的余额不够啦!")
        return
    if guess not in range(1,7):
        await ctx.send("⚠️ 请猜1-6之间的数字哦!")
        return
    
    # 掷骰子
    dice_result = random.randint(1,6)
    if dice_result == guess:
        # 猜中,奖励等额投注金额(净赚1倍)
        update_user_balance(ctx.author.id, amount)
        await ctx.send(f"🎉 恭喜你猜中了!骰子点数是{dice_result},你获得了{amount}硬币!当前余额:{get_user_balance(ctx.author.id)}")
    else:
        # 没猜中,扣除投注金额
        update_user_balance(ctx.author.id, -amount)
        await ctx.send(f"😢 很遗憾没猜中,骰子点数是{dice_result},你损失了{amount}硬币!当前余额:{get_user_balance(ctx.author.id)}")

最后再强调下:真的别用纯TXT,你得自己处理数据拆分、格式维护,还要担心并发写入冲突,太折腾了。上面两种方案都比TXT靠谱,尤其是SQLite,后续要加交易记录、等级系统之类的扩展也很方便。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:49:53