概要
スマホのゲームなどでよく見かける「ガチャ」の仕組みです。
ガチャの中身をグレード毎に分けて登録し、グレードのみに確率があるものです。
恐らく一番実用的なのではないでしょうか。
例えばグレードと確率がレジェンド3%、レア17%、コモン80%のような確率にしたい。
そして、それぞれのグレードには複数種類のアイテムがあり、グレード内は同一確率で良い。
といった具合です。
設計詳細
ガチャ、グレード、中身の3テーブルがあります。
グレードに確率があり、中身は等しい確率で出るので確率は存在しないイメージです。
同じレア度でも新旧のアイテムなどで確率を変更したい場合は、新アイテムと旧アイテムのグレードで分けるといった使い方になります。
ER図
erDiagram
Gachas ||--o{ GachaGrades: "has many"
GachaGrades ||--o{ GachaItems : "has many"
Items ||--o{ GachaItems : "has many"
Gachas {
int id PK
string name
}
GachaGrades {
int id PK
int gacha_id FK
string name
int rate
}
GachaItems {
int id PK
int gacha_grade_id FK
int item_id FK
}
Items {
int id PK
string name
}
使い方
PHPのLaravelでの取得例を記載してみます。
1. グレードの決定
まずガチャのグレードを決めます。
グレードIDを取得します。
public function getGrade($gachaId)
{
$grades = GachaGrade::where('gacha_id', $gachaId)->get(); // GachaGradesからデータ取得
// 確率の合計値を求める
$max = 0;
foreach ($grades as $record) {
$max += $record['rate'];
}
// $gradesが配列の場合は以下でもOK
// $max = array_sum(array_column('rate'));
// 0から始まるので合計値から1を引いた数までの乱数を取得
$rate = mt_rand(0, $max-1);
// 乱数がどこに当たるか調べていく
foreach ($data as $record) {
$max -= $record['rate'];
if ($max <= $rate) {
return $record['id'];
}
}
throw new Exception('ここには来ないはず!');
}
2. 指定したグレードのアイテムを取得
次に、決定したガチャグレードのアイテムからランダムで取得します。
public function getItem($gradeId)
{
// 指定グレードのアイテムを全て取得
return GachaItem::where('gacha_grade_id', $gradeId)
->inRandomOrder() // ORDER BY RANDOM()
->first(); // LIMIT 1
}
ランダムで取得の方法は色々あるので、DB・Webサーバーなどどこに負荷をかけるかを考えながら実装してみてください。
コメント