Fork me on GitHub

Elo rating system 模拟

  1 package org.cc.foo_008;
  2 
  3 import java.util.ArrayList;
  4 import java.util.List;
  5 import java.util.Random;
  6 
  7 public class Main_006 {
  8 
  9     public static void main(String[] args) {
 10         
 11         EloRatingSystemDemo e=new EloRatingSystemDemo();
 12         
 13         e.show();
 14         
 15 //        User u=e.gamer.get(new User().level).get(0);
 16 //        
 17 //        for(int i=0;i<999;i++){
 18 //            e.play(u);
 19 //        }
 20 //        
 21 //        e.show();
 22 //        
 23 //        System.out.println(u.rating);
 24 
 25         //大部分情况下总能选出一个或少数几个等级比较高的(或比较低的...) 是这个算法比较神奇还是我的程序有问题呢...
 26         for(int i=0;i<99999;i++){
 27             User u=e.randGetUser();
 28             e.play(u);
 29         }
 30         
 31         e.show();
 32         
 33     }
 34     
 35 }
 36 
 37 class EloRatingSystemDemo {
 38     
 39     public List<List<User>> gamer=new ArrayList<>();
 40     //k值越大,升级就越快,绝大部分都处于越高位置  
 41     public double k=100;
 42     
 43     public EloRatingSystemDemo() {
 44         //十个级别
 45         for(int i=0;i<10;i++){
 46             gamer.add(new ArrayList<>());
 47         }
 48         
 49         //十个玩家
 50         for(int i=0;i<1000;i++){
 51             User u=new User();
 52             gamer.get(u.level).add(u);
 53         }
 54     }
 55     
 56     //为传入的玩家找到一个对手并开玩一局
 57     public void play(User user){
 58         User river=user;
 59         while(river==user){
 60             river=findRival(user);
 61         }
 62         fightAndRating(user,river);
 63     }
 64     
 65     //战斗并且评分(Elo Rating System)
 66     public void fightAndRating(User u1,User u2){
 67         
 68         //暂时移除
 69         gamer.get(u1.level).remove(u1);
 70         gamer.get(u2.level).remove(u2);
 71         
 72         //期望得分
 73         double ea=1.0/(1+Math.pow(10,(u1.rating-u2.rating)/400.0));
 74         double eb=1.0/(1+Math.pow(10,(u2.rating-u1.rating)/400.0));
 75         
 76         //发生战斗...结果未知
 77         int t=new Random().nextInt(3);
 78         
 79         double t2=0;
 80         if(t==0){
 81             //A赢
 82             t2=u1.rating+k*(1-ea);
 83             u1.rating=t2>0?t2:0;
 84             t2=u2.rating+k*(0.5-eb);
 85             u2.rating=t2>0?t2:0;
 86         }else if(t==1){
 87             //B赢
 88             t2=u1.rating+k*(0.5-ea);
 89             u1.rating=t2>0?t2:0;
 90             t2=u2.rating+k*(1-eb);
 91             u2.rating=t2>0?t2:0;
 92         }else if(t==2){
 93             //战平
 94             t2=u1.rating+k*(0-ea);;
 95             u1.rating=t2>0?t2:0;
 96             t2=u2.rating+k*(0-eb);
 97             u2.rating=t2>0?t2:0;
 98         }
 99         
100         //放入
101         int level=(int) (u1.rating/500);
102         level=level<10?level:9;
103         u1.level=level;
104         gamer.get(u1.level).add(u1);
105         
106         level=(int) (u2.rating/500);
107         level=level<10?level:9;
108         u2.level=level;
109         gamer.get(u2.level).add(u2);
110 
111     }
112     
113     //找到一个级别相当(左右偏移,实力最接近)的对手
114     public User findRival(User user){
115         //如果当前级别只有自己一个人的话就偏移,否则的话说明可以找到同级别的玩家
116         int shift=gamer.get(user.level).size()==1?1:0;
117         while(true){
118             
119             boolean exit=true;
120             
121             //优先匹配弱一些的对手
122             if(user.level-shift>=0){
123                 User u=findRival0(user.level-shift);
124                 if(u!=null) return u;
125                 exit=false;
126             }
127             if(user.level+shift<10){
128                 User u=findRival0(user.level+shift);
129                 if(u!=null) return u;
130                 exit=false;
131             }
132             
133             if(exit) return null;
134             
135             shift++;
136         }
137     }
138     
139     //500分为一个级别,找在某个级别的对手
140     private User findRival0(int level){
141         //检测这个级别是否有人
142         List<User> list=gamer.get(level);
143         if(list.isEmpty()) return null;
144         //随机选取一个对手
145         return list.get(new Random().nextInt(list.size()));
146     }
147 
148     //随机获得一个用户
149     public User randGetUser(){
150         while(true){
151             List<User> list=gamer.get(new Random().nextInt(gamer.size()));
152             if(!list.isEmpty()) return list.get(new Random().nextInt(list.size()));
153         }
154     }
155     
156     //打印所有玩家的信息:
157     public void show(){
158         for(int i=0;i<gamer.size();i++){
159             List<User> list=gamer.get(i);
160             System.out.printf("Level %d: ",i+1);
161             for(int j=0;j<list.size();j++){
162                 System.out.printf("%.2f ",list.get(j).rating);
163             }
164             System.out.println();
165         }
166         System.out.println();
167     }
168     
169 }
170 
171 //代表一个玩家,初始分数为1500
172 class User {
173     double rating=1500;
174     int level=(int) (rating/500);
175 }

 

posted @ 2016-09-02 10:36  CC11001100  阅读(472)  评论(0编辑  收藏  举报