MOVE共学营TASK4教程 完成游戏的上链部署上链网络:主网(mainnet)需求完成链游相关知识的学习完成随机数的学习,游戏必须包含随机数完成存和取游戏资金池完成如何存储Coin在合约的学习,游戏必须能存取[task2]发行的F
🧑💻作者:gracecampo
Faucet Coin
,用task2
的 Faucet Coin
作为游戏输赢的资产github id
的元素链游(Blockchain Games)是指利用区块链技术开发的网络游戏。与传统游戏不同,链游通常具有以下特点:
资产所有权:玩家可以真正拥有游戏内的数字资产(如角色、道具、皮肤等),这些资产通常以NFT(非同质化代币)的形式存在于区块链上。
去中心化:游戏的某些或全部逻辑运行在区块链上,确保游戏规则的透明和公平。
可交易性:玩家可以在区块链上自由交易他们的游戏资产,这为玩家提供了新的经济激励。
互操作性:某些链游允许玩家在不同的游戏中使用相同的资产,这种特性通常被称为“跨游戏互操作性”。
在 Sui 区块链上,你可以使用 sui::random 模块来生成安全的随机数。这个模块提供了多种生成随机数的方法,确保了随机数的不可预测性和不可操控性。以下是一些关键功能:
创建随机生成器:
public fun new_generator(r: &random::Random, ctx: &mut tx_context::TxContext): random::RandomGenerator
生成随机数:
参考官方库:sui::random模块
以下是官方库中的函数:
生成一个 u8 类型的随机数:
public fun generate_u8(g: &mut random::RandomGenerator): u8
生成一个范围内的 u32 类型随机数:
public fun generate_u32_in_range(g: &mut random::RandomGenerator, min: u32, max: u32): u32
使用示例: 你可以在 Move 语言中使用这些功能来实现一个简单的掷骰子功能:
public entry fun roll_dice(r: &Random, ctx: &mut TxContext): Dice {
let mut generator = new_generator(r, ctx);
//生成1范围在1-6的随机数
Dice { value: random::generate_u8_in_range(&mut generator, 1, 6) }
}
这些功能确保了在 Sui 上生成的随机数是安全的,并且可以用于各种应用场景,如游戏、抽奖等。
public struct Game has key {
id: UID,
balance: Balance<FAUCET_COIN>,
game_name:vector<u8>
}
public struct Admin has key {
id: UID,
}
fun init(ctx: &mut TxContext) {
let game = Game {
id: object::new(ctx),
balance: balance::zero(),
game_name:b"GRACECAMPO GAME"
};
transfer::share_object(game);
let admin = Admin {id: object::new(ctx)};
transfer::transfer(admin, ctx.sender());
}
public entry fun deposit(game: &mut Game, coin: &mut Coin<FAUCET_COIN>, amount: u64, ctx: &mut TxContext) {
assert!(coin.value() >= amount, EUserInsufficientBalance);
let split_balance = coin::balance_mut(coin).split(amount);
game.balance.join(split_balance);
}
public entry fun withdraw(game: &mut Game, _: &Admin, amount: u64, ctx: &mut TxContext) {
assert!(game.balance.value() >= amount, EGameInsufficientBalance);
let cash = coin::take(&mut game.balance, amount, ctx);
transfer::public_transfer(cash, ctx.sender());
}
public entry fun play(game: &mut Game, rnd: &Random, guess: bool, coin: &mut Coin<FAUCET_COIN>, amount: u64, ctx: &mut TxContext) {
assert!(game.balance.value() >= amount, EGameInsufficientBalance);
assert!(coin.value() >= amount, EUserInsufficientBalance);
//创建随机数生成器
let mut gen = random::new_generator(rnd, ctx);
//根据随机数生成器生成布尔值
let flag = random::generate_bool(&mut gen);
//判断是否猜对,如果猜对将奖励发送到玩家账户
if (flag == guess) {
let reward = coin::take(&mut game.balance, amount, ctx);
coin.join(reward);
}else
//如果猜错,将赌注存入奖池
Self::deposit(game, coin, amount,ctx)
}
}
module task4::game{
use sui::coin::{Self, Coin};
use sui::balance::{Self, Balance};
use sui::random::{Self, Random};
use task2::faucet_coin::FAUCET_COIN;
const EUserInsufficientBalance: u64 = 1000;
const EGameInsufficientBalance: u64 = 1001;
public struct Game has key {
id: UID,
balance: Balance<FAUCET_COIN>,
game_name:vector<u8>
}
public struct Admin has key {
id: UID,
}
fun init(ctx: &mut TxContext) {
let game = Game {
id: object::new(ctx),
balance: balance::zero(),
game_name:b"GRACECAMPO GAME"
};
transfer::share_object(game);
let admin = Admin {id: object::new(ctx)};
transfer::transfer(admin, ctx.sender());
}
public entry fun deposit(game: &mut Game, coin: &mut Coin<FAUCET_COIN>, amount: u64, ctx: &mut TxContext) {
assert!(coin.value() >= amount, EUserInsufficientBalance);
let split_balance = coin::balance_mut(coin).split(amount);
game.balance.join(split_balance);
}
public entry fun withdraw(game: &mut Game, _: &Admin, amount: u64, ctx: &mut TxContext) {
assert!(game.balance.value() >= amount, EGameInsufficientBalance);
let cash = coin::take(&mut game.balance, amount, ctx);
transfer::public_transfer(cash, ctx.sender());
}
public entry fun Play(game: &mut Game, rnd: &Random, guess: bool, coin: &mut Coin<FAUCET_COIN>, amount: u64, ctx: &mut TxContext) {
assert!(game.balance.value() >= amount, EGameInsufficientBalance);
assert!(coin.value() >= amount, EUserInsufficientBalance);
let mut gen = random::new_generator(rnd, ctx);
let flag = random::generate_bool(&mut gen);
// 如果获胜
if (flag == guess) {
let reward = coin::take(&mut game.balance, amount, ctx);
coin.join(reward);
}else {
Self::deposit(game, coin, amount,ctx)
}
}
}
发布合约后,需要你记录
此合约函数都声明了entry,允许在区块浏览器进行函数调用。
packageId替换为你发布的包对象id
访问地址:https://suivision.xyz/package/packageId?tab=Code
1.导入coin模块 需要在move.toml中引入之前发布的coin包 例如:
[dependencies]
Sui = { git = "https://gitee.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/testnet" }
task2 = { local = "../task2" } #引入你之前task2发布的coin包
task2是我的包名,你需要根据自己的包名做修改
Move.lock 记录了你的包发布的信息,此文件不能删除或者修改
2.理解管理员结构体
我们创建了一个admin结构体,赋予它key能力,用于在调用withdraw函数,控制只能拥有这个对象的地址进行调用,在实践中一定注意这点。
📹 课程B站账号
💻 Github仓库 https://github.com/move-cn/letsmove
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!