随机生成城堡序列号
我们在之前的课程中已经学习了整数和运算。现在,让我们应用这些知识来生成城堡的序列号。
正如在课程开始时讨论的那样,城堡序列号对城堡的视觉呈现和游戏数据有重大影响。它是关键的,并且在建造城堡时随机分配。
在 sources
文件夹中创建一个新的模块 move_castle::utils
。在这个模块中,包含一个名为 generate_castle_serial_number
的函数。
// sources/utils.move
module move_castle::utils {
public(package) fun generate_castle_serial_number(size: u64, id: &UID): u64 {
}
}
让我们重新审视序列号的设计:
第一个数字是“size”,它是用户输入的参数,我们需要生成一个5位整数。所选算法包括从城堡的 UID 哈希值中获取一个5位整数值(使用取模操作)。
// 对城堡的 UID 进行哈希。
let hash = hash::sha2_256(object::uid_to_bytes(id));
生成的哈希是一个长度为32的 vector<u8>
,将其转换为 u64
整数:
let result_num: u64 = 0;
// 将哈希向量转换为 u64。
while (vector::length(&hash) > 0) {
let element = vector::remove(&mut hash, 0);
result_num = ((result_num << 8) | (element as u64));
};
执行取模操作以仅保留整数的最后5位数字:
// 保留最后5位数字。
result_num = result_num % 100000u64;
最后,将“size”数字连接并返回完整的序列号。整个函数应如下所示:
/// 生成城堡的序列号。
public(package) fun generate_castle_serial_number(size: u64, id: &UID): u64 {
// 对城堡的 UID 进行哈希。
//let mut hash = hash::sha2_256(object::uid_to_bytes(id));
//原教程使用hash::sha2_256但以淘汰,更新至keccak256
let mut hash = hash::keccak256(&object::uid_to_bytes(id));
let mut result_num: u64 = 0;
// 将哈希向量转换为 u64。
while (vector::length(&hash) > 0) {
let element = vector::remove(&mut hash, 0);
result_num = ((result_num << 8) | (element as u64));
};
// 保留最后5位数字。
result_num = result_num % 100000u64;
// 连接 size 数字。
size * 100000u64 + result_num
}
添加一些测试并运行它:
// utils_tests.move
#[test_only]
module move_castle::utils_tests {
use sui::test_scenario::Self;
use move_castle::utils;
use std::debug::print;
#[test]
fun serial_number_test() {
let sender = @0xABC;
let scenario_val = test_scenario::begin(sender);
let scenario = &mut scenario_val;
{
let ctx = test_scenario::ctx(scenario);
let uid = object::new(ctx);
let result = utils::generate_castle_serial_number(0, &mut uid);
print(&result);
assert!(result >= 0, 0);
assert!(result < 100000, 0);
object::delete(uid);
};
test_scenario::end(scenario_val);
}
}