C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++で学ぶEloレーティングアルゴリズムの仕組みと実装方法

Eloレーティングアルゴリズムは、チェスやeスポーツなどの対戦型競技においてプレイヤーをランク付けするために広く使われているレーティング手法です。プレイヤーのレーティングは、試合ごとのパフォーマンス(勝敗)に応じて変動します。

レーティング移動の基本的な考え方

ここでは、異なるレーティングを持つ2人のプレイヤーが対戦するケースを考えます。

Player1 vs Player2

前提として、Player1のレーティングがPlayer2より高いとします。

試合に勝敗がつくと、一定のポイントが敗者から勝者へ移動します。しかし、その移動量は固定ではなく、どちらのプレイヤーが勝ったかによって変わるのが特徴です。

  • レーティングの高いPlayer1が勝った場合 → 移動するポイントは少ない(想定通りの結果のため)
  • レーティングの低いPlayer2が勝った場合 → 移動するポイントは多い(番狂わせのため大きく評価される)

レーティング更新の計算式

移動するポイント量は、次の式で求められます。

Player1の場合:
新レーティング = 旧レーティング + K × (勝敗値 − P1)

Player2の場合:
新レーティング = 旧レーティング + K × (勝敗値 − P2)

各記号の意味は以下の通りです。

  • K(ratingConstant):レーティング定数。運営団体やゲームコミュニティが決めます(例:32、100など)
  • P1:Player1の期待勝率
    P2:Player2の期待勝率
  • 勝敗値:勝った場合は1、負けた場合は0

期待勝率P1・P2は、両者のレーティング差から次のように計算されます。

P1 = 1 / (1 + 10((Rating2 − Rating1) / 400))
P2 = 1 − P1

この式により、レーティングが高いプレイヤーほど高い勝率が事前に見積もられ、番狂わせが起きたときほど大きなポイントが動く仕組みになっています。

具体例で理解するEloレーティング

入力:rating1 = 782、rating2 = 1432、ratingConstant = 100、Player1の勝利

出力:rating1 ≒ 784、rating2 ≒ 1430

計算過程:

Player1が勝利したため、Player1の勝敗値は1、Player2は0となります。

Player1の期待勝率は約0.98(98%)なので、

Player1:新レーティング = 782 + 100 × (1 − 0.98) = 782 + 2 = 784

Player2:新レーティング = 1432 + 100 × (0 − 0.02) = 1432 − 2 = 1430

このように、格上のPlayer1が勝ったため、わずか2ポイントしか移動しません。逆に格下のPlayer2が勝っていた場合は、はるかに多くのポイントが移動することになります。

C++による実装例

それでは、Eloレーティングアルゴリズムの動作を示すC++プログラムを見てみましょう。

#include <bits/stdc++.h>
using namespace std;

// Eloレーティングに基づいて両者のレーティングを更新する関数
void updateRatingUsingELoRating(float rating1, float rating2, int ratingConstant, bool player1SuccessProb) {

    float P1, P2;
    // レーティング差から期待勝率を計算
    if(rating1 > rating2){
        P1 = (1.0 / (1.0 + pow(10.0, ((rating1 - rating2) / 400.0)) ) );
        P2 = 1 - P1;
    }
    else {
        P2 = (1.0 / (1.0 + pow(10.0, ((rating2 - rating1) / 400.0)) ) );
        P1 = 1 - P2;
    }

    // 勝敗に応じてレーティングを更新
    if (player1SuccessProb == 1) {
        rating1 = rating1 + ratingConstant * (1 - P1);
        rating2 = rating2 + ratingConstant * (0 - P2);
    }
    else {
        rating1 = rating1 + ratingConstant * (0 - P1);
        rating2 = rating2 + ratingConstant * (1 - P2);
    }

    cout<<"Ratings After the game\n";
    cout<<"Player 1 : "<<rating1<<"\t Player 2 : "<<rating2;
}

int main()
{
    float rating1 = 782, rating2 = 1432;
    int ratingConstant = 100;
    bool player1SuccessProb = 1; // 1ならPlayer1の勝利
    cout<<"Ratings before the game: \n";
    cout<<"Player 1 : "<<rating1<<"\t Player 2 : "<<rating2<<endl;
    if(player1SuccessProb)
        cout<<"Player 1 wins the game!\n";
    else
        cout<<"Player 2 wins the game!\n";
    updateRatingUsingELoRating(rating1, rating2, ratingConstant, player1SuccessProb);

    return 0;
}

実行結果

Ratings before the game:
Player 1 : 782      Player 2 : 1432
Player 1 wins the game!
Ratings After the game
Player 1 : 784.316 Player 2 : 1429.68

コードの解説

  • まず、両プレイヤーのレーティング差を400で割った値をもとに、10のべき乗を使って期待勝率P1・P2を算出します。
  • 次に、実際の勝敗(1または0)と期待勝率との差にK(ここでは100)を掛け合わせ、レーティングを更新します。
  • 実行結果を見ると、格上のPlayer1が勝ったため、レーティングは782 → 約784とわずかに上昇し、Player2は1432 → 約1430とわずかに低下しています。

なお、元のコードにはPlayer2が勝った場合の分岐でrating2を更新すべき箇所に誤りがあるため、ここでは修正した版を掲載しています。

まとめ

Eloレーティングアルゴリズムは、「実力が近い相手に勝てば多くのポイントを得られ、格下に勝っても得られるポイントは少ない」という直感的に納得感のある仕組みを実現した手法です。期待勝率の計算とレーティング更新というシンプルな数式だけで構成されているため、C++でも容易に実装でき、オンラインゲームのマッチメイキングや競技の順位付けなど、幅広い分野で活用されています。

  1. C++で学ぶ最適ページ置換アルゴリズム(OPT)の実装方法 ― ヒット数とミス数の求め方

    ページ参照列とフレーム数が与えられたとき、最適ページ置換アルゴリズム(Optimal Page Replacement Algorithm)を用いてメモリブロックにページを割り当てた場合のヒット数とミス数を求めるのが本記事の目的です。 最適ページ置換アルゴリズムとは? ページ置換アルゴリズムとは、「どのメモリページを入れ替えるか」を決定するアルゴリズムのことです。その中でも最適ページ置換アルゴリズムは、「今後最も長い間参照されないページ」を置き換え対象として選ぶ方式です。 理論上は最もミス(ページフォールト)が少ない理想的なアルゴリズムですが、将来のページ参照を正確に予測することは現実には不可

  2. C++のベルマン・フォード法とは?仕組み・手順・実装例を徹底解説

    ベルマン・フォード法(Bellman-Ford Algorithm)は、動的計画法に基づくアルゴリズムの一つで、指定した始点からグラフ内のすべての頂点への最短経路を求めるために使用されます。このアルゴリズムは反復的なアプローチを採用しており、最短経路の候補を繰り返し更新しながら答えを導き出します。重み付きグラフに対して適用できる点が大きな特徴です。 このアルゴリズムは1955年にアルフォンソ・シンベル(Alphonso Shimbel)によって提案されました。その後、1956年と1958年にリチャード・ベルマン(Richard Bellman)とレスター・フォード(Lester Ford)に