zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    浅谈一致性Hash原理及应用
    学习sql中的排列组合,在园子里搜着看于是。。。
    SQL Server DAC——专用管理员连接
    通过phantomjs 进行页面截图
    《javascript算法--对象的比较》
    React-生命周期的相关介绍
    常用的谷歌插件
    webpack的externals的使用
    mac 10.12显示隐藏文件
    “文字”聚合、散出动画-转自奇舞团
  • 原文地址:https://www.cnblogs.com/cc11001100/p/5832537.html
Copyright © 2011-2022 走看看