package com.snowcattle.game.common.util;
import java.util.Iterator;
import java.util.List;
/**
*
* 一个均匀分布的随机数序列,一般用于游戏中物品的掉落
* 例如
* A 2%
* B 3%
* c %6
* ...
*
* 用法
* 初始化阶段
* UniformRandomChooser<Item> urc = new UniformRandomChooser<Item>;
* urc.addObject(0.1, item1);
* urc.addObject(0.2, item2);
* urc.addObject(0.3, item3);
* urc.addObject(0.4, item4);
* urc.compile();
*
* 使用阶段
* urc.getObject(0.576);(返回item3)
*
* @author jackflit
*
*/
public class UniformRandomChooser<T> {
private List<Entry<T>> objects;
private float maxup;
public UniformRandomChooser(){
objects = new java.util.LinkedList<Entry<T>>();
}
/**
* 添加物品T,出现概率rate
* @param rate
* @param obj
*/
public void addObject(float rate, T obj){
Entry<T> entry = new Entry<T>();
entry.rate = rate;
entry.obj = obj;
objects.add(entry);
}
public void compile(){
float sum = 0;
// 计算sum
Iterator<Entry<T>> iter = objects.iterator();
while(iter.hasNext()){
Entry<T> entry = iter.next();
sum+=entry.rate;
entry.up = sum;
}
// 归一化
iter = objects.iterator();
while(iter.hasNext()){
Entry<T> entry = iter.next();
entry.up = entry.up/sum;
maxup = entry.up;
}
}
/**
* 根据概率返回物品
* rate如果在[0, 1.0]之外会按照边界值处理
* 一般来说,只要物品列表不为空,就不会返回空
*
* @param rate
* @return
*/
public T getObject(float rate){
if(rate < 0){
rate = 0;
}
if(rate > maxup){
rate = maxup;
}
Iterator<Entry<T>> iter = objects.iterator();
while(iter.hasNext()){
Entry<T> entry = iter.next();
if(rate <= entry.up){
return entry.obj;
}
}
return null;
}
private static class Entry<T>{
public float rate; // 原始掉落率
public float up;
public T obj;
}
}