在遊戲開發過程中,經常會遇到生成一波帶權重的隨機怪物或是掉落List中物品帶權重的情況,總結下我的算法以及實現方法。
直接上代碼
using System.Collections.Generic;
using System;
public class RandomHelper
{
/// <summary>
/// 算法:
/// 1.每個元素權重+1命名爲w,防止爲0情況。
/// 2.計算出總權重n。
/// 3.每個元素權重w加上從0到(n-1)的一個隨機數(即總權重以內的隨機數),得到新的權重排序值s。
/// 4.根據得到新的權重排序值s進行排序,取前面s最大幾個。
/// </summary>
/// <param name="list">原始列表</param>
/// <param name="count">隨機抽取條數</param>
/// <returns></returns>
public static List<T> GetRandomList<T>(List<T> list, int count) where T : NormalStageConfig.NormalStageObject.SpawnInitialItem
{
if (list == null || list.Count <= count || count <= 0)
{
return list;
}
//計算權重總和
int totalWeights = 0;
for (int i = 0; i < list.Count; i++)
{
totalWeights += list[i].weight + 1; //權重+1,防止爲0情況。
}
//隨機賦值權重
System.Random ran = new System.Random (GetRandomSeed()); //GetRandomSeed()防止快速頻繁調用導致隨機一樣的問題
List<KeyValuePair<int, int>> wlist = new List<KeyValuePair<int, int>>(); //第一個int爲list下標索引、第一個int爲權重排序值
for (int i = 0; i < list.Count; i++)
{
int w = (list[i].weight + 1) + ran.Next(0, totalWeights); // (權重+1) + 從0到(總權重-1)的隨機數
wlist.Add(new KeyValuePair<int, int>(i, w));
}
//排序
wlist.Sort(
delegate(KeyValuePair<int, int> kvp1, KeyValuePair<int, int> kvp2)
{
return kvp2.Value - kvp1.Value;
});
//根據實際情況取排在最前面的幾個
List<T> newList = new List<T>();
for (int i = 0; i < count; i++)
{
T entiy = list[wlist[i].Key];
newList.Add(entiy);
}
//隨機法則
return newList;
}
/// <summary>
/// 隨機種子值
/// </summary>
/// <returns></returns>
private static int GetRandomSeed()
{
byte[] bytes = new byte[4];
System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
rng.GetBytes(bytes);
return BitConverter.ToInt32(bytes, 0);
}
}
/// <summary>
/// 權重對象
/// </summary>
public class RandomObject
{
/// <summary>
/// 權重
/// </summary>
public int Weight { set; get; }
}
用法思路:寫一箇中轉的類繼承自原類,將原類中的N條數據隨機取出加到新類型的list中即可