基本ゲームは無課金勢
ゲームは好きで課金さえすれば無双できるのはわかっているけど、
いつサ終するかわからないデータにお金かけるくらいなら、
ドッグラン行ったり・水槽買ったり・餌用コオロギ買ったりするほうが、
有意義と思ってしまうくらいゲームへの優先度が年々下がってきてる。。。
やっぱりガチャ回したくね?
無課金でもアホほどガチャ回したい(ガチャガチャきゅ~と・ふぃぎゅ@メイト
そんな気持ちにお答えして、自分の好きな条件でいっぱい回せるガチャを作ってみた。
過去にガチャの話してたので、ソレの簡単実装って位置付け
そう言えば、この業界入って死ぬほど残業させられていた頃、
すもももももも(アニメ)で知った MOSAIC.WAV の
【キミは何テラバイト?】と【Magical Hacker ☆ くるくるリスク】を、
頭おかしくなるほど聞いてたお陰で立派なプログラマーになれました!
みんなも頭おかしくなるくらいレッツ、リッスン!!
とりあえず簡易ガチャ(キャラ設定がアホほど長いやつ)
// キャラ一覧
/**
* ■排出率
* SSR:なんかとっても凄いキャラ1 → 0.30%(リスト内の出現数 / リストの総数)
* SSR:なんかとっても凄いキャラ2 → 0.30%
* SSR:なんかとっても凄いキャラ3 → 0.30%
* SSR:なんかとっても凄いキャラ4 → 0.30%
* SSR:なんかとっても凄いキャラ5 → 0.30%
* SR:とっても凄いキャラ1 → 1.52%
* SR:とっても凄いキャラ2 → 1.52%
* SR:とっても凄いキャラ3 → 1.52%
* SR:とっても凄いキャラ4 → 1.52%
* SR:とっても凄いキャラ5 → 1.52%
* R:凄いキャラ1 → 3.03%
* R:凄いキャラ2 → 3.03%
* R:凄いキャラ3 → 3.03%
* R:凄いキャラ4 → 3.03%
* R:凄いキャラ5 → 3.03%
* R:凄いキャラ6 → 3.03%
* R:凄いキャラ7 → 3.03%
* R:凄いキャラ8 → 3.03%
* R:凄いキャラ9 → 3.03%
* R:凄いキャラ10 → 3.03%
* N:ただのキャラ1 → 6.06%
* N:ただのキャラ2 → 6.06%
* N:ただのキャラ3 → 6.06%
* N:ただのキャラ4 → 6.06%
* N:ただのキャラ5 → 6.06%
* N:ただのキャラ6 → 6.06%
* N:ただのキャラ7 → 6.06%
* N:ただのキャラ8 → 6.06%
* N:ただのキャラ9 → 6.06%
* N:ただのキャラ10 → 6.06%
*/
const charList = ["SSR:なんかとっても凄いキャラ1"
, "SSR:なんかとっても凄いキャラ2"
, "SSR:なんかとっても凄いキャラ3"
, "SSR:なんかとっても凄いキャラ4"
, "SSR:なんかとっても凄いキャラ5"
, "SR:とっても凄いキャラ1"
, "SR:とっても凄いキャラ1"
, "SR:とっても凄いキャラ1"
, "SR:とっても凄いキャラ1"
, "SR:とっても凄いキャラ1"
, "SR:とっても凄いキャラ2"
, "SR:とっても凄いキャラ2"
, "SR:とっても凄いキャラ2"
, "SR:とっても凄いキャラ2"
, "SR:とっても凄いキャラ2"
, "SR:とっても凄いキャラ3"
, "SR:とっても凄いキャラ3"
, "SR:とっても凄いキャラ3"
, "SR:とっても凄いキャラ3"
, "SR:とっても凄いキャラ3"
, "SR:とっても凄いキャラ4"
, "SR:とっても凄いキャラ4"
, "SR:とっても凄いキャラ4"
, "SR:とっても凄いキャラ4"
, "SR:とっても凄いキャラ4"
, "SR:とっても凄いキャラ5"
, "SR:とっても凄いキャラ5"
, "SR:とっても凄いキャラ5"
, "SR:とっても凄いキャラ5"
, "SR:とっても凄いキャラ5"
, "R:凄いキャラ1"
, "R:凄いキャラ1"
, "R:凄いキャラ1"
, "R:凄いキャラ1"
, "R:凄いキャラ1"
, "R:凄いキャラ1"
, "R:凄いキャラ1"
, "R:凄いキャラ1"
, "R:凄いキャラ1"
, "R:凄いキャラ1"
, "R:凄いキャラ2"
, "R:凄いキャラ2"
, "R:凄いキャラ2"
, "R:凄いキャラ2"
, "R:凄いキャラ2"
, "R:凄いキャラ2"
, "R:凄いキャラ2"
, "R:凄いキャラ2"
, "R:凄いキャラ2"
, "R:凄いキャラ2"
, "R:凄いキャラ3"
, "R:凄いキャラ3"
, "R:凄いキャラ3"
, "R:凄いキャラ3"
, "R:凄いキャラ3"
, "R:凄いキャラ3"
, "R:凄いキャラ3"
, "R:凄いキャラ3"
, "R:凄いキャラ3"
, "R:凄いキャラ3"
, "R:凄いキャラ4"
, "R:凄いキャラ4"
, "R:凄いキャラ4"
, "R:凄いキャラ4"
, "R:凄いキャラ4"
, "R:凄いキャラ4"
, "R:凄いキャラ4"
, "R:凄いキャラ4"
, "R:凄いキャラ4"
, "R:凄いキャラ4"
, "R:凄いキャラ5"
, "R:凄いキャラ5"
, "R:凄いキャラ5"
, "R:凄いキャラ5"
, "R:凄いキャラ5"
, "R:凄いキャラ5"
, "R:凄いキャラ5"
, "R:凄いキャラ5"
, "R:凄いキャラ5"
, "R:凄いキャラ5"
, "R:凄いキャラ6"
, "R:凄いキャラ6"
, "R:凄いキャラ6"
, "R:凄いキャラ6"
, "R:凄いキャラ6"
, "R:凄いキャラ6"
, "R:凄いキャラ6"
, "R:凄いキャラ6"
, "R:凄いキャラ6"
, "R:凄いキャラ6"
, "R:凄いキャラ7"
, "R:凄いキャラ7"
, "R:凄いキャラ7"
, "R:凄いキャラ7"
, "R:凄いキャラ7"
, "R:凄いキャラ7"
, "R:凄いキャラ7"
, "R:凄いキャラ7"
, "R:凄いキャラ7"
, "R:凄いキャラ7"
, "R:凄いキャラ8"
, "R:凄いキャラ8"
, "R:凄いキャラ8"
, "R:凄いキャラ8"
, "R:凄いキャラ8"
, "R:凄いキャラ8"
, "R:凄いキャラ8"
, "R:凄いキャラ8"
, "R:凄いキャラ8"
, "R:凄いキャラ8"
, "R:凄いキャラ9"
, "R:凄いキャラ9"
, "R:凄いキャラ9"
, "R:凄いキャラ9"
, "R:凄いキャラ9"
, "R:凄いキャラ9"
, "R:凄いキャラ9"
, "R:凄いキャラ9"
, "R:凄いキャラ9"
, "R:凄いキャラ9"
, "R:凄いキャラ10"
, "R:凄いキャラ10"
, "R:凄いキャラ10"
, "R:凄いキャラ10"
, "R:凄いキャラ10"
, "R:凄いキャラ10"
, "R:凄いキャラ10"
, "R:凄いキャラ10"
, "R:凄いキャラ10"
, "R:凄いキャラ10"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ1"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ2"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ3"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ4"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ5"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ6"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ7"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ8"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ9"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
, "N:ただのキャラ10"
];
function gacha() {
console.log(charList[Math.floor(Math.random() * charList.length)]);
}
module.exports = {
gacha
};
試しに10連を3回、回してみた
結果的には以下になりました。
■4回出た
N:ただのキャラ1
■2回出た
N:ただのキャラ2
N:ただのキャラ7
■3回出た
N:ただのキャラ3
N:ただのキャラ4
N:ただのキャラ6
■1回出た
N:ただのキャラ8
N:ただのキャラ9
R:凄いキャラ1
R:凄いキャラ3
R:凄いキャラ5
R:凄いキャラ8
R:凄いキャラ9
R:凄いキャラ10
SR:とっても凄いキャラ2
SR:とっても凄いキャラ3
SR:とっても凄いキャラ4
SR:とっても凄いキャラ5
SSR:なんかとっても凄いキャラ3
大体10回のうちの半分がNで、2~3がR、1~2がSRで、SSRが20回転しないうちに出たので、
割と良心的なガチャなんじゃないかなと(ほぼ運だけど
ただコレだと、ガチャで出てくるキャラのデータがアホほど多くなって可読性に欠けるため、もう少し仕組みを考えてみる。
ランク毎のキャラ一覧生成してから割り出すやつ
// ランク一覧
const rankList = [
{
rank: "SSR",
weight: 1,
},
{
rank: "SR",
weight: 5,
},
{
rank: "R",
weight: 10,
},
{
rank: "N",
weight: 20,
}
];
// キャラ一覧
const charList = {
"SSR": ["なんかとっても凄いキャラ1"
, "なんかとっても凄いキャラ2"
, "なんかとっても凄いキャラ3"
, "なんかとっても凄いキャラ4"
, "なんかとっても凄いキャラ5"],
"SR": ["とっても凄いキャラ1"
, "とっても凄いキャラ2"
, "とっても凄いキャラ3"
, "とっても凄いキャラ4"
, "とっても凄いキャラ5"],
"R": ["凄いキャラ1"
, "凄いキャラ2"
, "凄いキャラ3"
, "凄いキャラ4"
, "凄いキャラ5"
, "凄いキャラ6"
, "凄いキャラ7"
, "凄いキャラ8"
, "凄いキャラ9"
, "凄いキャラ10"],
"N": ["ただのキャラ1"
, "ただのキャラ2"
, "ただのキャラ3"
, "ただのキャラ4"
, "ただのキャラ5"
, "ただのキャラ6"
, "ただのキャラ7"
, "ただのキャラ8"
, "ただのキャラ9"
, "ただのキャラ10"
],
};
function gacha() {
const chList = rankList.map(rank=> {
const cList = [];
for(let i = 0; i < rank.weight; i++)
cList.push(...charList[rank.rank].map(ch => `${rank.rank}:${ch}`));
return cList;
}).flat();
console.log(chList[Math.floor(Math.random() * chList.length)]);
}
module.exports = {
gacha
};
かいせつ
ランク情報に重みを付けて、
ランクに紐づくキャラリストを検索用のListに重み分追加していき、
ソレを最後に抽出してるって感じです。
→SSR:なんかとっても凄いキャラ1はList上に1しか無いけど、N:ただのキャラ1はListに20いる感じ
ロジック内でデータを生成しているためキャラ情報分のコード量はだいぶ減ったかと。
使ってるデータ的には最初に書いたロジックと同じ【ような】データとなっている。
※キャラのインデックスが違うだけで、中身をソートしたら同じデータとなる
おまけ
SSR/SRのキャラをもっと絞りたいってなったら、ソレ以外のランクの重みを増やせば全体数が上がって、ジャブジャブ課金させることが出来るね(ニッコリ
※クソ運営という批判がバンバン来て低評価の嵐になりそうだけど。。。
ちなみに排出率を調べたい用の関数も残しておきますね
function rate() {
const totalChar = rankList.map(rank => charList[rank.rank].length * rank.weight).reduce((total, val) => total + val, 0);
console.log(`総キャラ数:${totalChar}`);
rankList.forEach(rank => console.log(`${rank.rank}:${(rank.weight / totalChar * 100).toFixed(2)}%`));
}
// こんな感じで出力
// 総キャラ数:330
// SSR:0.30%
// SR:1.52%
// R:3.03%
// N:6.06%