如何确保我的 RNG 号码是唯一的?

How can I make sure my RNG numbers are unique?

我正在尝试使用 RNG class 从列表中 select 2 个随机项目。问题是偶尔我会得到相同的 2 个数字,我希望它们是唯一的。我尝试使用 while 循环来获取另一个数字,如果它与上一个相同,但即使添加一个简单的 while 循环也会导致“超出预付 gas”错误。我有什么不明白的?

//simplified for posting question
var lengthOfList = 10
var numItemsWanted = 2
//Get more rng numbers than I need incase of duplicates
const rng = new RNG<u32>(lenghtOfList, lengthOfList)

for(let i = 0; i < numItemsWanted; i++) {
    var r = rng.next()
    while (r == rng.last()) {
        r = rng.next()
    }
    newList.push(oldList[r])
}

工作:

//simplified for posting question
var lengthOfList = 10
var numItemsWanted = 2
//Get more rng numbers than I need incase of duplicates
const rng = new RNG<u32>(lenghtOfList, lengthOfList)
let r = rng.next()
let last = r + 1
for(let i = 0; i < numItemsWanted; i++) {
    newList.push(oldList[r])
    last = r
    r = rng.next()
    while (r == last) {
        r = rng.next()
    }
}

如果您从 oldList 中删除了一次选择的项目,将无法再次选择它。

另一种方法是洗牌 oldList,然后选择前两项。

这是关于near-sdk-as,NEAR平台上的AssemblyScript智能合约开发包

你可以在这个例子中看到RNG是如何使用的 https://github.com/Learn-NEAR/NCD.L1.sample--lottery/blob/ff6cddaa8cac4d8fe29dd1a19b38a6e3c7045363/src/lottery/assembly/lottery.ts#L12-L13

class Lottery {
  private chance: f64 = 0.20

  play(): bool {
    const rng = new RNG<u32>(1, u32.MAX_VALUE);
    const roll = rng.next();
    logging.log("roll: " + roll.toString());
    return roll <= <u32>(<f64>u32.MAX_VALUE * this.chance);
  }
}

以及这里的构造函数是如何实现的: https://github.com/near/near-sdk-as/blob/f3707a1672d6da6f6d6a75cd645f8cbdacdaf495/sdk-core/assembly/math.ts#L152

第一个参数是缓冲区的长度,其中包含从种子生成的随机数。您可以使用 next() 方法在每次调用时从此缓冲区中获取更多数字

export class RNG<T> {
  constructor(len: u32, public max: u32 = 10_000) {
    let real_len = len * sizeof<T>();
    this.buffer = math.randomBuffer(real_len);
    this._last = this.get(0);
  }

  next(): T {}
}