using System; using System.Collections.Generic; using System.Linq; using EventCubeMelt; using UnityEngine; using Random = UnityEngine.Random; namespace EventCubeMelt.Utils { public static class SlotsGenerator { // 已废弃 public static List GenerateSlots(int num,List rates, List data,List rand) { var r = Random.value; // [0,1) // // 随机一次或者两层 int count; // if (rates.Count < 2) { rates.Add(0.4f); } var r1 = rates[0]; var r2 = rates[1]; if (r < r1 ) count = 1; // 5% else if (r < r2) count = 2; // 10% else count = 0; // 85% var list = PickPositions(count,data,rand ); ELog($"GenerateSlots -> {r} ,r1 = {r1} ,r2 = {r2} count = {count} {string.Join(",",rand)} => {string.Join(",",list)}"); return list; } public static List GenerateSlots2(int num, List rates, List data, List rand,List collectIds) { if (collectIds is not { Count: > 0 } ) return data; if (rand is not { Count: > 0 }) return data; var ls = new List(); for (var i = 0; i < num; i++) { var index = RandomSel(rates); if (index < 0 || index >= collectIds.Count) continue; var value = collectIds[index]; // var has = rand.Any(item => item.id == value) ; // ls.Add(has ? value : RandomRand(rand)); var randIndex = Random.Range(0,rand.Count); ls.Add(rand.Contains(value) ? value : rand[randIndex]); } var list = PickPositionVer2(data,ls ); // ELog($"GenerateSlots2 -> {r} ,r1 = {r1} ,r2 = {r2} count = {count} {string.Join(",",rand)} => {string.Join(",",list)}"); return list; } // private static int RandomRand(List<(int id,int weight)> rand) // { // // 计算总权重 // // 计算总权重 // int totalWeight = 0; // foreach (var item in rand) // { // if (item.weight < 0) // continue; // totalWeight += item.weight; // } // // if (totalWeight == 0) // return 101; // // // 在 Unity 环境中生成随机数 // int r = Random.Range(0, totalWeight); // // 遍历查找 // int cumWeight = 0; // foreach (var item in rand) // { // cumWeight += item.weight; // if (r < cumWeight) // { // return item.id; // } // } // // return 101; // // } private static int RandomSel(List probabilities) { var randomValue = Random.value; var cumulative = 0f; for (int i = 0; i < probabilities.Count; i++) { cumulative += probabilities[i]; if (randomValue < cumulative) { return i; } } return -1; } private static List PickPositionVer2(List data, List rand) { var result = new List(data); // 如果没有随机数,直接返回 if (rand == null || rand.Count == 0) { return result; } var count = rand.Count; // 收集非零位置 var nonZeroPositions = new List(); for (var i = 0; i < data.Count; i++) { if (data[i] != 0) { nonZeroPositions.Add(i); } } var actualCount = Math.Min(count, nonZeroPositions.Count); // 随机选择位置 // Random random = new Random(); var selectedPositions = new List(); // 部分洗牌:只洗需要选择的部分 for (var i = 0; i < actualCount; i++) { var randomIndex = Random.Range(i, nonZeroPositions.Count); // 交换位置 (nonZeroPositions[i], nonZeroPositions[randomIndex]) = (nonZeroPositions[randomIndex], nonZeroPositions[i]); selectedPositions.Add(nonZeroPositions[i]); } // 随机也洗牌 rand.ShuffleInPlace(); // 使用rand中的值替换 for (var i = 0; i < selectedPositions.Count; i++) { var position = selectedPositions[i]; var randIndex = i % rand.Count; // 循环使用rand中的值 result[position] = rand[randIndex]; } return result; } private static List PickPositions(int count ,List data,List rand) { // 如果没有随机数,直接返回 if (rand == null || rand.Count == 0 || count == 0) { // return result; return data; } var result = new List(data); // 收集非零位置 var nonZeroPositions = new List(); for (var i = 0; i < data.Count; i++) { if (data[i] != 0) { nonZeroPositions.Add(i); } } var actualCount = Math.Min(count, nonZeroPositions.Count); // 随机选择位置 // Random random = new Random(); var selectedPositions = new List(); // 部分洗牌:只洗需要选择的部分 for (var i = 0; i < actualCount; i++) { var randomIndex = Random.Range(i, nonZeroPositions.Count); // 交换位置 (nonZeroPositions[i], nonZeroPositions[randomIndex]) = (nonZeroPositions[randomIndex], nonZeroPositions[i]); selectedPositions.Add(nonZeroPositions[i]); } // 随机也洗牌 rand.ShuffleInPlace(); // 使用rand中的值替换 for (var i = 0; i < selectedPositions.Count; i++) { var position = selectedPositions[i]; var randIndex = i % rand.Count; // 循环使用rand中的值 result[position] = rand[randIndex]; } return result; } // 就地洗牌;O(n),无偏。默认用 Random.Shared(.NET 6+) public static void ShuffleInPlace(this IList list) { if (list == null) throw new ArgumentNullException(nameof(list)); var n = list.Count; for (int i = n - 1; i > 0; i--) { int j = Random.Range(0, i + 1); if (j != i) (list[i], list[j]) = (list[j], list[i]); // 交换 } } // 返回打乱后的副本(不修改原集合) public static List Shuffled(this IEnumerable source) { if (source == null) throw new ArgumentNullException(nameof(source)); var list = new List(source); list.ShuffleInPlace(); return list; } #region LOG private static void ELog(string message) { #if UNITY_EDITOR if (!EventCubeMeltLogPolicy.EnableELog) return; Debug.Log($" SlotsGenerator => {message} "); #endif } #endregion } }