Sui.

帖子

分享您的知识。

article banner.
0xduckmove.
Mar 07, 2025
文章

在 Sui Move 中开发骰子游戏合约

在本教程中,我将指导你完成使用Sui Move创建骰子游戏智能合约的过程.

该合同允许玩家下注**掷骰子的结果,**由管理员管理奖池. 最后,你将拥有一份功能齐全的合约,并对Sui Move的几个关键概念有扎实的了解.

简介

我们将构建的骰子游戏合约允许以下功能:

  • 初始化:合约创建者设置游戏.
  • 管理员管理:管理员可以将代币存入奖池并根据需要将其提取.
  • 玩家互动:玩家通过猜测掷骰子结果和下注来参与.

本教程假设你对Sui Move有基本的了解,重点是通过实际实现引入新概念. 在深入研究代码之前,让我们探索一下您将遇到的关键概念:

1.1 添加依赖关系:

要使用其他合约(例如水龙头代币合约)中的代币,您需要将其作为依赖项添加到您的项目中. 这是通过更新Move.toml合同文件来完成的:

[dependencies]
coin_duck = { local = "../coin_duck"”}

在这里,coin_duck 是位于指定路径的水龙头代币合约. 依赖合约还必须使用发布时获得的软件包 ID 在自己的 move.toml 中指定其 published-at 字段,如下所示: 生锈

published-at = "packageId_from_publication"

1.2 使用断言

断言可确保在合同执行期间满足某些条件. assert!宏检查条件,如果失败,则抛出错误并停止执行.
这对于防止无效状态很有用,例如下注超过玩家余额.

1.3 生成随机数

骰子游戏中的公平性依赖于随机数的生成. Sui Mov randome 为此提供了该模块.
您将创建一个RandomGenerator对象并使用它生成 1 到 6 之间的随机数,模拟掷骰子.

1.4 使用硬币和余额

在 Sui Move 中,代币使用硬币和余额模块进行管理:

  • 硬币:余额周围的包装,用于转移代币.

  • 余额:代表实际代币金额,允许进行拆分和合并等操作.

关键方法包括:

  • coin:: value (in_coin):返回硬币对象的总值.
  • coin:: take(&mut 余额,金额,ctx):从余额中提取指定金额以创建硬币.
  • in_coin.balance_mut () .split(金额):从硬币余额中拆分指定金额.
  • balance.join(平衡):将一个余额合并到另一个余额中.

这些操作将用于管理游戏的奖池和玩家投注.

骰子游戏合约

以下是骰子游戏合约的完整代码,随后是详细说明:

/// Game: Dice rolling. Players bet and guess the number. If correct, they win an amount equal to their bet; if incorrect, the bet goes to the game pool.

module game_duck:game_duck;

use sui::balance::{Self, Balance};
use sui::coin::{Self, Coin};
use sui::random::{Random, new_generator, generate_u8_in_range};
use coin_duck::duckfaucet::DUCKFAUCET;

const ErrorUserInsufficient: u64 = 0x101;
const ErrorGameInsufficient: u64 = 0x102;

public struct Game has key {
    id: UID,
    pool_amount: Balance<DUCKFAUCET>,
}

public struct Admin has key {
    id: UID,
}

fun init(ctx: &mut TxContext) {
    let game = Game {
        id: object::new(ctx),
        pool_amount: balance::zero()
    };
    transfer::share_object(game);

    let admin = Admin { id: object::new(ctx) };
    transfer::transfer(admin, ctx.sender());
}

public entry fun addCoinToGamePool(game: &mut Game, in_coin: &mut Coin<DUCKFAUCET>, amount: u64, _: &mut TxContext) {
    let value = coin::value(in_coin);
    assert!(amount <= value, ErrorUserInsufficient);
    let coin_balance = in_coin.balance_mut().split(amount);
    game.pool_amount.join(coin_balance);
}

public entry fun removeCoinFromGamePool(_: &Admin, game: &mut Game, amount: u64, ctx: &mut TxContext) {
    assert!(game.pool_amount.value() >= amount, ErrorGameInsufficient);
    let coin = coin::take(&mut game.pool_amount, amount, ctx);
    transfer::public_transfer(coin, ctx.sender());
}

entry fun play(game: &mut Game, random: &Random, guess_num: u8, in_coin: &mut Coin<DUCKFAUCET>, amount: u64, ctx: &mut TxContext) {
    assert!(game.pool_amount.value() >= (amount * 3), ErrorGameInsufficient);
    assert!(in_coin.balance().value() >= amount, ErrorUserInsufficient);

    let mut g = new_generator(random, ctx);
    let win_num = generate_u8_in_range(&mut g, 1, 6);

    if (win_num == guess_num) {
        let reward_coin = coin::take(&mut game.pool_amount, amount, ctx);
        in_coin.join(reward_coin);
    } else {
        addCoinToGamePool(game, in_coin, amount, ctx);
    }
}

代码分解结构

  • 游戏:具有唯一 ID 和用于存储奖池的 pool_amount(余额)的共享对象.
  • 管理员:管理员拥有的用于初始化(初始化)管理池的关键对象.

初始化(初始化):

  • 创建奖池为空的游戏对象并公开共享.
  • 创建管理员对象并将其传输给合约创建者.

加入游戏池 (addCoinToGamePool)

  • 从管理员的 in_coin 中提取指定金额.
  • 使用 assert!确保硬币有足够的价值.
  • 从 in_coin 的余额中拆分金额并将其合并到游戏的 pool_amount 中.

结果:

  • 获胜:如果猜出与掷骰子相符,则从彩池中提取等于下注的奖励并合并到玩家的in_coin中.
  • 失败:如果不正确,投注将从in_coin中扣除,并通过addCointoGamepool添加到池中.
  • Sui
  • Move
3
分享
评论
.

Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.

268帖子383答案
Sui.X.Peera.

赚取你的 1000 Sui 份额

获取声誉积分,并因帮助 Sui 社区成长而获得奖励。

奖励活动五月
我们使用 cookie 确保您在我们的网站上获得最佳体验。
更多信息