帖子
分享您的知识。
在 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 random
e 为此提供了该模块.
您将创建一个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
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.

- MiniBob... SUI+31
1
- 0xduckmove... SUI+27
2
- HaGiang... SUI+26
3
- ... SUIharry phan+21
- ... SUIMarlKey+20
- ... SUI
- ... SUIVens.sui+15
- ... SUICarlkawIy+12
- ... SUI
- ... SUIkryptoschain+10