Unity猜字母游戏:如何从列表按指定比例(如30%)选取元素?
猜字母游戏:按比例抽取正确字母的实现方案
问题背景
我正在开发一款猜字母游戏,玩家猜测目标词中的字母,猜中即可获得对应分数。目前已按分值划分4组字母列表:
//List of letters: private string[] fivePointsLetters = { "q", "w", "ď", "x", "ň", "ú", "g", "ä", "ô", "ó" }; private List<string> fourPointsLetters = new List<string> { "f", "ů", "š", "č", "ž", "ý", "ch", "í", "ú", "é", "á", "ý" }; private List<string> threePointsLetters = new List<string> { "ř", "h", "é", "b", "c", "ě", "j", "z", "á", "k", "f", "v", "r", "y" }; private List<string> twoPointsLetters = new List<string> { "a", "e", "i", "o", "u", "d", "n", "t", "v", "s", "l", "k", "r", "p", "í", "m" };
原本逻辑是随机选取4个2分字母、3个3分字母、2个4分字母和1个5分字母,凑成10个候选字母供玩家选择,但会出现候选字母中没有目标词正确字母的问题。现在计划从目标词拆分出的正确字母列表中选取30%的字母加入候选池,保证10个候选里约3个正确字母,需要实现按指定比例抽取元素的逻辑。
原随机选字母示例代码:
for (int i = 0; i < button2b_value.Count; i++) { List<string> filteredStrings = twoPointsLetters.Except(usedLetters).Except(button2b_value).ToList(); if (filteredStrings.Count == 0) { Debug.LogWarning("No possible 2 point letters in list"); } else { int index = UnityEngine.Random.Range(0, filteredStrings.Count); view.RPC("Set2ButtonsValuesRPC", RpcTarget.All, filteredStrings[index], i); } }
实现步骤与代码示例
1. 预处理正确字母列表
将目标词拆分为单个字母并去重,避免重复抽取同一正确字母:
// 假设targetWord是你的目标词字符串 List<string> correctLetters = targetWord.Select(c => c.ToString()).Distinct().ToList();
2. 计算需抽取的正确字母数量
按30%比例计算,同时处理边界情况(至少1个,不超过正确字母总数):
// 按30%比例计算数量,四舍五入取整 int requiredCorrectCount = Mathf.RoundToInt(correctLetters.Count * 0.3f); // 确保数量合法:至少1个,且不超过正确字母总数 requiredCorrectCount = Math.Clamp(requiredCorrectCount, 1, correctLetters.Count);
3. 随机抽取指定数量的正确字母
通过临时列表避免修改原正确字母列表,随机选取后移除已选元素防止重复:
List<string> selectedCorrectLetters = new List<string>(); List<string> tempCorrectList = new List<string>(correctLetters); // 复制原列表用于抽取 for (int i = 0; i < requiredCorrectCount; i++) { if (tempCorrectList.Count == 0) break; int randomIndex = UnityEngine.Random.Range(0, tempCorrectList.Count); selectedCorrectLetters.Add(tempCorrectList[randomIndex]); tempCorrectList.RemoveAt(randomIndex); // 移除已选字母,避免重复抽取 }
4. 调整候选字母池的补充数量
原本计划的各分值字母数量,需要减去已选中的正确字母中对应分值的数量:
// 原计划的各分值字母需求 int needTwoPoints = 4; int needThreePoints = 3; int needFourPoints = 2; int needFivePoints = 1; // 遍历已选正确字母,调整各分值的需求数量 foreach (string letter in selectedCorrectLetters) { if (twoPointsLetters.Contains(letter)) needTwoPoints--; else if (threePointsLetters.Contains(letter)) needThreePoints--; else if (fourPointsLetters.Contains(letter)) needFourPoints--; else if (fivePointsLetters.Contains(letter)) needFivePoints--; } // 确保需求数量不为负数 needTwoPoints = Math.Max(0, needTwoPoints); needThreePoints = Math.Max(0, needThreePoints); needFourPoints = Math.Max(0, needFourPoints); needFivePoints = Math.Max(0, needFivePoints);
5. 补充非正确字母到候选池
参考原有随机选字母逻辑,从各分值组中排除已选正确字母和已用字母,补充剩余数量的字母:
// 补充2分字母 for (int i = 0; i < needTwoPoints; i++) { List<string> filtered = twoPointsLetters.Except(usedLetters).Except(selectedCorrectLetters).ToList(); if (filtered.Count == 0) { Debug.LogWarning("No available 2-point letters left"); break; } int index = UnityEngine.Random.Range(0, filtered.Count); string selected = filtered[index]; view.RPC("Set2ButtonsValuesRPC", RpcTarget.All, selected, i); usedLetters.Add(selected); } // 补充3分字母 for (int i = 0; i < needThreePoints; i++) { List<string> filtered = threePointsLetters.Except(usedLetters).Except(selectedCorrectLetters).ToList(); if (filtered.Count == 0) { Debug.LogWarning("No available 3-point letters left"); break; } int index = UnityEngine.Random.Range(0, filtered.Count); string selected = filtered[index]; view.RPC("Set3ButtonsValuesRPC", RpcTarget.All, selected, i); usedLetters.Add(selected); } // 补充4分字母 for (int i = 0; i < needFourPoints; i++) { List<string> filtered = fourPointsLetters.Except(usedLetters).Except(selectedCorrectLetters).ToList(); if (filtered.Count == 0) { Debug.LogWarning("No available 4-point letters left"); break; } int index = UnityEngine.Random.Range(0, filtered.Count); string selected = filtered[index]; view.RPC("Set4ButtonsValuesRPC", RpcTarget.All, selected, i); usedLetters.Add(selected); } // 补充5分字母 for (int i = 0; i < needFivePoints; i++) { List<string> filtered = fivePointsLetters.Except(usedLetters).Except(selectedCorrectLetters).ToList(); if (filtered.Count == 0) { Debug.LogWarning("No available 5-point letters left"); break; } int index = UnityEngine.Random.Range(0, filtered.Count); string selected = filtered[index]; view.RPC("Set5ButtonsValuesRPC", RpcTarget.All, selected, i); usedLetters.Add(selected); }
6. 将选中的正确字母加入候选池
把抽取的正确字母设置到候选按钮上(需根据你的按钮管理逻辑调整,这里假设存在空按钮可填充):
// 假设buttonList是所有候选按钮的列表,找到未设置的按钮并填充正确字母 foreach (string correctLetter in selectedCorrectLetters) { int emptyButtonIndex = buttonList.FindIndex(btn => string.IsNullOrEmpty(btn.text)); if (emptyButtonIndex != -1) { view.RPC("SetButtonValueRPC", RpcTarget.All, correctLetter, emptyButtonIndex); usedLetters.Add(correctLetter); } }
内容的提问来源于stack exchange,提问作者V1lko
相关产品推荐
相关产品推荐

