Bạn có thể sử dụng một thuật toán mà tôi gọi là RNG Xác suất phân tán .
Nó trông như thế này:
public class Item {}
public class ExampleBucket
{
private List<Item> bucket = new List<Item>();
public void Add (Item item, int count)
{
for (int i = 0; i < count; i++)
{
bucket.Add(item);
}
}
public Item GetRandom (Random rng)
{
var index = rng.Next(0, bucket.Count);
return bucket[index];
}
}
Bạn có thể khởi tạo như thế này:
private void InitBucket()
{
var itemA = new Item();
var itemB = new Item();
var itemC = new Item();
var bucket = new ExampleBucket();
bucket.Add(itemA, 1);
bucket.Add(itemB, 2);
bucket.Add(itemC, 3);
}
Bạn có thể nhận được các mục bằng cách gọi GetRandom(Random)
vào ExampleBucket
ví dụ của bạn .
Làm thế nào nó hoạt động?
Chúng tôi có một danh sách có tên bucket
trong ExampleBucket
lớp. Trước hết nó là trống rỗng. Bằng Add(Item, int)
phương thức gọi , bạn thêm một lượng Item
s cụ thể vào bucket
danh sách.
Vào cuối InitBucket()
phương thức của chúng tôi , bucket
danh sách sẽ như thế này:
itemA // 1 x itemA
itemB // 2 x itemB
itemB
itemC // 3 x itemC
itemC
itemC
Sau đó, chúng tôi chỉ đơn giản là tạo ra một số ngẫu nhiên giữa 0
và bucket.Count
, và trả lại hàng mà tương ứng với chỉ số trong bucket
danh sách.
Xác suất nhận được một mục cụ thể từ một danh sách là Item Count / Total Count
. Bạn càng có nhiều mặt hàng của một loại cụ thể trong danh sách, càng có nhiều cơ hội mặt hàng đó được chọn.
Vì vậy, trong trường hợp này;
Probability of getting itemA = 1 / (1+2+3)
Probability of getting itemB = 2 / (1+2+3)
Probability of getting itemC = 3 / (1+2+3)
Khi bạn chạy GetRandom()
100000 lần (bài kiểm tra ở đây trong Fiddle ), bạn có thể thấy các giá trị khá gần với kết quả hoàn hảo:
A count = 16690 | Expected = 16666
B count = 33519 | Expected = 33333
C count = 49791 | Expected = 50000
Điều tôi thích nhất trong thuật toán này là, bạn không cần chỉ định tổng số mục. Bạn chỉ có thể thêm bất kỳ mục nào bất cứ lúc nào bạn muốn và đừng lo lắng về phần còn lại.
Ví dụ: nếu bạn muốn tăng cơ hội nhận itemA
từ danh sách, bạn chỉ cần gọi
bucket.Add (itemA, theAmountYouWant);
và bạn không cần phải làm gì khác.