【SUI move】共学营task4游戏解析

本文是对SUI官方举办的最新一期共学营task4的具体分析,有兴趣的伙伴可以看一下:

48d4960f891302a638912cb63e24793.jpg
关于task4任务是这样的:

image.png
我们可以看到,这其实可以写成一个猜正反游戏的形式。最简单的比如两人对猜,猜硬币正反,两人质押相同数量的coin,赢的人可以拿走所有的coin。

好,明确了需求,那么我们需要设计整个游戏。
首先,游戏本身需要一个struct,包含了游戏的各个属性:管理员,当前参与者的下注,以及资金池子总额。这个结构体应该是一个存储在链上且一直存在的对象,因此设置为key和store。

public struct Game has key, store { id: UID, admin: address, // 管理员地址 bets: vector<Bet>, // 当前所有下注 val: Balance<ALEXWAKER_FAUCET_COIN>, // 游戏总资金池 balance类型 }

我们对于“对赌”这个概念其实也可以做一个结构体:这个结构体具有drop能力,即游戏结束应该自动销毁,因此不具备id属性。一个对赌应该包含玩家地址和猜测结果。

public struct Bet has store, drop { player: address, // 玩家地址 guess: bool, // true: 正, false: 反 }

然后,就是四个最核心的函数:deposit、withdraw和play。玩家调用deposit来参与游戏,管理员可以通过withdraw来从奖池中提取佣金或手续费,play则是开始游戏。

public fun deposit(game: &mut Game, player: address, guess: bool, coin: Coin<ALEXWAKER_FAUCET_COIN>, ctx: &mut TxContext) { let mut all_balance = into_balance(coin); //coin转balance balance::join(&mut game.val, all_balance); //balance加入奖池 game.bets.push_back(Bet { player, guess });//该玩家下注加入当前游戏 }

这里有一个很神奇的点。首先我假设你已经完成了task2,有了一个自己的faucet币。这个币本身会有一个objectID。但是,当你每次领faucet的时候,也会生成一个objectID。换句话说,你每次领faucet,都会有本次领取的objectID!我们在这个函数中传入的参数coin:Coin<ALEXWAKER_FAUCET_COIN>应该是某一次领取的objectID,而不是这个币的objectID!
为了使得游戏公平,由于没有写复杂的判断逻辑,因此在让玩家领水的时候,统一领取相同数量的水。
这个deposit函数中有一些很重要的概念:Coin类型和Balance类型。这是在sui move中两类不同的类型,也是非常重要的概念。

Coin<T> 是一种具体的资源,表示一个代币实例。每个 Coin 对象都与一个特定的代币类型 T 相关联。 每个 Coin 都有一个唯一的 Object ID,可以作为独立对象在 Sui 网络中流通。

而Balance

Balance<T> 是一种聚合的余额资源,表示某个账户对某种代币的总余额。 它是一种抽象资源,不是一个独立的对象,不能直接转移或单独操作。

看明白了不?Balance是一种天生适合做奖池的对象。因此我们需要将Coin转化为Balance。

然后就是withdraw函数

public fun withdraw(game: &mut Game, amount: u64, ctx: &mut TxContext) { assert!(ctx.sender() == game.admin);//只有管理员可以取钱 assert!(game.val.value() >= amount);//判断是否取得太多,超过了总奖池 let admin_balance = balance::split(&mut game.val, amount); //分出一定数量的代币转给管理员 let admin_coin = from_balance(admin_balance, ctx); public_transfer(admin_coin, ctx.sender()); }

这个逻辑就与deposit相反,是要把Balance转为Coin,利用函数from_balance可以把Balance转化为Coin,然后调用public_transfer将这些coin发送给管理员账户。这里多提一嘴,ctx往往代表上下文信息,这是一个很抽象的概念,我们一般用ctx查看当前函数的调用者。
最后就是play函数:

public fun play(game: &mut Game, rand: &Random, ctx: &mut TxContext) { assert!(ctx.sender() == game.admin); //只有调用者才能调 let mut gen = random::new_generator(rand, ctx); let _random_number = random::generate_u64(&mut gen); let _result = random::generate_bool(&mut gen); // 找到猜对的玩家 let mut winner_address = @0x0; let mut len = vector::length(&game.bets); while (len > 0) { let bet = &game.bets[len - 1]; if (bet.guess == _result) { winner_address = bet.player; }; len = len - 1; }; // 循环查找当前获胜者 // 分配奖励 let coin_value = game.val.value(); let win_balance = balance::split(&mut game.val, coin_value); let win_coin = from_balance(win_balance, ctx); public_transfer(win_coin, winner_address); // 清空下注记录 // 因为目前只让两个人玩,因此写死两个清空就好 vector::pop_back(&mut game.bets); vector::pop_back(&mut game.bets); }

我们用一个循环遍历vector,找到猜对的人,然后把奖金全部给他。分割奖池需要用split函数,这个函数此一个参数是Balance对象,第二个参数是u64整数。最后两个pop_back,表示把游戏中参与对赌的bet清空,下次咱还可以接着玩!最后,sui官方随机数objectID是0x8,主网和测试网都是这个。
好了,以上就是这个游戏的解析。

欢迎关注:
HOH水分子公众号
HOH水分子X账号
bilibili课程
GitHub仓库

相关知识

【SUI move】共学营task4游戏解析
Move Blocks for Watch & Phone好玩吗 Move Blocks for Watch & Phone玩法简介
Move Birds for Watch & Phone好玩吗 Move Birds for Watch & Phone玩法简介
BlowUp Road Riding Move好玩吗 BlowUp Road Riding Move玩法简介
Move Birds for Watch & Phone什么时候出 公测上线时间预告
Move Blocks for Watch & Phone什么时候出 公测上线时间预告
BlowUp Road Riding Move什么时候出 公测上线时间预告
Move Dices官网在哪下载 最新官方下载安装地址
Move Blocks for Watch & Phone官网在哪下载 最新官方下载安装地址
Move Birds for Watch & Phone官网在哪下载 最新官方下载安装地址

网址: 【SUI move】共学营task4游戏解析 http://www.hyxgl.com/newsview335986.html

推荐资讯