我正在使用带有合格字词的地图进行我正在开发的刽子手游戏。地图中的整数存储选择单词的时间,因此在开始时地图如下所示:
alabanza 0
esperanza 0
comunal 0
aprender 0
....
经过一些游戏后,地图会像这样
alabanza 3
esperanza 4
comunal 3
aprender 1
....
我想随机选择下一个单词,但选择较少的单词会被选中的概率更大。
我读过Java - Choose a random value from a HashMap but one with the highest integer assigned,但情况相反。
我还以为我可以使用带有重复单词的列表(单词出现在列表中的次数越多,选择的概率就越多)但我只能设法达到这个目的:
int numberOfWords=wordList.size(); //The Map
List<String> repeatedWords=new ArrayList<>();
for (Map.Entry<String,Integer> entry : wordList.entrySet()) {
for (int i = 0; i < numberOfWords-entry.getValue(); i++) {
repeatedWords.add(entry.getKey());
}
}
Collections.shuffle(repeatedWords); //Should it be get(Random)?
String chosenWord=repeatedWords.get(0);
我认为当选择的单词数量等于单词数量时,这会失败。
最后,一旦他们有不同的数字,每个单词的概率就会出现问题。我已经改变了观点,所以我首先设置了1000的概率(可能是任何数字),每次我选择一个单词时,我减少一定数量的概率(比方说,20%),所以我使用:
wordList.put(chosen,(int)(wordList.get(chosen)*0.8)+1);
之后我选择Lajos Arpad或Ahmad Shahwan给出的食谱。 如果游戏要玩很多次,那么所有概率都倾向于1,但这不是我的情况。
感谢所有回答的人。
答案 0 :(得分:0)
我不会提供准确的代码,但基本的想法。
迭代wordList.values()
以找到最大权重M
和权重总和S
。
现在让每个单词w
都有可能(如概率,但不必总和为1)来选择M + 1 - wordList.get(w)
,所以一个单词的重量为{{} 1}}比具有权重1
的单词更有可能被选择M
倍。
可能性总和为M
(这就是我们需要(M + 1) * wordList.size() - S
的原因)。在0和此总和之间选择一个随机数S
。
迭代R
,总结可能性。当总和通过wordList.entrySet()
时,这就是你想要的单词。
答案 1 :(得分:0)
您的地图值是您的权重。
您需要选择一个低于权重总和的整数。
您可以选择每个String条目及其权重。当权重和通过随机整数时,你就在THE String。
这会给你:
public static void main(String ... args){
Map<String, Integer> wordList = new HashMap<>();
wordList.put("foo", 4);
wordList.put("foo2", 2);
wordList.put("foo3", 7);
System.out.println(randomWithWeight(wordList));
}
public static String randomWithWeight(Map<String, Integer> weightedWordList) {
int sum = weightedWordList.values().stream().collect(Collectors.summingInt(Integer::intValue));
int random = new Random().nextInt(sum);
int i = 0;
for (Map.Entry<String, Integer> e : weightedWordList.entrySet()){
i += e.getValue();
if (i > random){
return e.getKey();
}
}
return null;
}
答案 2 :(得分:0)
试试这个:
import java.util.Map;
import java.util.HashMap;
import java.util.Random;
public class MyClass {
public static void main(String args[]) {
Map<String, Integer> wordList = new HashMap<>();
wordList.put("alabanza", 3);
wordList.put("esperanza", 4);
wordList.put("comunal", 3);
wordList.put("aprender", 1);
Map<String, Integer> results = new HashMap<>(4);
for (int i = 0; i < 100; i++) {
String name = randomize(wordList);
Integer old = results.getOrDefault(name, 0);
results.put(name, old + 1);
}
for (Map.Entry<String, Integer> e : results.entrySet()) {
System.out.println(e.getKey() + "\t" + e.getValue());
}
}
private static String randomize(Map<String, Integer> wordList) {
final Integer sum = wordList.values().stream().reduce(Integer::sum).orElse(0);
final int grandSum = (wordList.size() - 1) * sum;
final int random = new Random().nextInt(grandSum + 1);
int index = 0;
for (Map.Entry<String, Integer> e: wordList.entrySet()) {
index += (sum - e.getValue());
if (index >= random) {
return e.getKey();
}
}
return null;
}
}
Out out是超过100次试验选择名称的时间:
aprender 37
alabanza 25
comunal 23
esperanza 15
您可以自己尝试here。
答案 3 :(得分:0)
为简单起见,我们假设您有一个名为occurrences
的数组,其中包含int
个元素(您可以轻松将其转换为数据结构)。
现在,让我们找到最大值:
int max = 0;
for (int i = 0; i < occurrences.length; i++) {
if (max < occurrences[i]) max = occurrences[i];
}
让它递增:
max++;
现在,让我们为{0}作为值的项目赋予max
的权重,对于发生过一次的项目的权重max - 1
,等等(没有项目将由于我们增加max
),因此权重为0:
int totalWeight = 0;
for (int j = 0; j < occurrences.length; j++) {
totalWeight += max - occurrences[j];
}
请注意,所有物品都有其重量。现在,让我们假设您有一个名为r
的随机整数,其中 0&lt; r&lt; = totalWeight :
int resultIndex = -1;
for (int k = 0; (resultIndex < 0) && k < occurrences.length; k++) {
if (r <= max - occurrences[k]) resultIndex = k;
else r -= max - occurrences[k];
}
,结果为occurrences[resultIndex]