一个ELO Rating的简单Java实现

近期兼职做了个小游戏,有感于暴雪的WOW竞技场排名系统,于是用简单实现了一个ELO Rating来记分。

WOW的排名系统暴雪自称是“ELO Like”,是对ELO Rating做了一些改进的。我们这里先介绍一下标准的ELO Rating。ELO等级分系统是用来计算一个人在双人对决性比赛里的相对的技能等级的一个系统,最早应用于国际象棋和围棋。简单的说,就是把“实力”这种比较“虚”的东西数字化的一种办法。这个系统是由一个物理学教授Arpad Elo创立的,他同时也是一位国际象棋的大师。众所周知,“实力”这个东西是很难判断的,但是实力也是一个客观存在的东西。Elo教授作出了一个假定:一个人的实力在短期内是一定的,并且遵从某一个正态分布函数;长期来看,一个人的实力是缓慢的变化的。并由于国际象棋中很难判别每一步甚至每一局的价值,Elo教授引入了统计学,用统计一段时期内棋手的输赢的办法来衡量该棋手的实力,同时作出第二个假定:某一特定实力范畴里,相互之间的差别一般可预期,不会出现太大意外。比如强手未必每盘都赢另一个比他弱的选手,但是总体来说胜率要高。具体的数学公式这里就不列出来了,有兴趣的朋友去Google搜索下就找到。

 

下面是Java实现的一些片段:

public class SimpleEloRatingSystem {
	
	public static double DEFAULT_ELO_K_FACTOR = 24.0;
	public static String K_FACTOR_STRING="0-2099=32,2100-2399=24,2490-3000=16";

	public final static double WIN = 1.0;
	public final static double DRAW = 0.5;
	public final static double LOSS = 0.0;

	public KFactor [] kFactors = {};

	private SimpleEloRatingSystem () {
				
		if (K_FACTOR_STRING != null) {
			
			StringTokenizer st1 = new StringTokenizer (K_FACTOR_STRING, ",");
			kFactors = new KFactor [st1.countTokens()];
			
			int index = 0;
			while (st1.hasMoreTokens()) {
				String kfr = st1.nextToken();
								
				StringTokenizer st2 = new StringTokenizer (kfr, "=");
				String range = st2.nextToken();
								
				double value = Double.parseDouble (st2.nextToken());
								
				st2 = new StringTokenizer (range, "-");
				int startIndex = Integer.parseInt(st2.nextToken());
				int endIndex   = Integer.parseInt(st2.nextToken());
								
				kFactors [index++] = new KFactor (startIndex, endIndex, value);
			}
		}			
	}
		

	public int getNewRating (int rating, int opponentRating, int resultType) {
		switch (resultType) {
			case Constants.WIN:
				return getNewRating (rating, opponentRating, WIN);
			case Constants.LOSE:
				return getNewRating (rating, opponentRating, LOSS);
			case Constants.DRAW:
				return getNewRating (rating, opponentRating, DRAW);				
		}
		return -1;		
	}
	

	public int getNewRating(int rating, int opponentRating, double score) {
		double kFactor       = getKFactor(rating);
		double expectedScore = getExpectedScore(rating, opponentRating);
		int    newRating     = calculateNewRating(rating, score, expectedScore, kFactor);
		
		return newRating;
	}	
	

	private int calculateNewRating(int oldRating, double score, double expectedScore, double kFactor) {
		return oldRating + (int) (kFactor * (score - expectedScore));
	}
	

	private double getKFactor (int rating) {
		// Return the correct k factor.
		for (int i = 0; i < kFactors.length; i++) 
			if (rating >= kFactors[i].getStartIndex() &&
				rating <= kFactors[i].getEndIndex()) 
			{
				return kFactors[i].value;
			}		
		return DEFAULT_ELO_K_FACTOR;
	}
	

	private double getExpectedScore (int rating, int opponentRating) {
		return 1.0 / (1.0 + Math.pow(10.0, ((double) (opponentRating - rating) / 400.0)));
	}
	

	public class KFactor {
		
		private int startIndex, endIndex;
		private double value;
		
		public KFactor (int startIndex, int endIndex, double value) {
			this.startIndex = startIndex;
			this.endIndex   = endIndex;
			this.value      = value;
		}
		public int getStartIndex () { return startIndex; }
		public int getEndIndex ()   { return endIndex; }
		public double getValue ()      { return value; }
		
		public String toString () { 
			return "kfactor: " + startIndex + " " + endIndex + " " + value;
		}
	}
}
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值