「ガチャ」のDB設計 – 確率あり

データベース設計 設計例

本記事はDB設計の提案を記載します。
この設計はあくまで一例です。
これを雛形として、ご自分の構築したいシステムに合わせてご利用ください。

概要

スマホのゲームなどでよく見かける「ガチャ」の仕組みです。

レジェンドキャラなどを低確率にしたかったりする場合に確率を含めています。
利用時はコードで抽出してください。(SQLでも頑張ったら抽出できるかもしれません)

設計詳細

ER図

erDiagram Gachas ||--o{ GachaItems: "has many" Gachas { int id PK string name } GachaItems { int id PK int gacha_id string item_name int rate }

使い方

以下のようなロジック(PHP)で取得します。

  1. GachaItemsのリストを取得
  2. 確率の合計値を求める
  3. 合計値-1の乱数を取得
  4. 乱数の示す場所を返す
public function getGachaItems($gachaId)
{
    $data = GachaItem::where('gacha_id', $gachaId)->get(); // 1. GachaItemからデータ取得
    
    // 2. 確率の合計値を求める
    $max = 0;
    foreach ($data as $record) {
        $max += $record['rate'];
    }
    
    // 3. 合計値-1の乱数を取得
    // 0から始まるので合計値から1を引いた数までの乱数を取得
    $rate = mt_rand(0, $max-1);
    
    // 4. 乱数の示す場所を返す
    foreach ($data as $record) {
        $max -= $record['rate'];
        if ($max <= $rate) {
            return $record['id'];
        }
    }
    throw new Exception('ここには来ないはず!');
  }
PHP

手順2の合計を求める部分が毎回入るので、この部分が気になる場合は以下の対応が考えられますが、デメリットもあるため、プロジェクトに合った判断をしてください。

  • 合計値が100などの固定値になるようにする
    • 計算が面倒なので運用コストが上がる
  • Gachasrate_sumのような合計値カラムを追加
    • 合計カラムの更新忘れが心配
  • SQLで求める
    • DB負荷が増える
  • 求めた合計値をキャッシュする
    • 更新時にキャッシュクリア忘れが心配

コメント

タイトルとURLをコピーしました