ようこそここは俺のチラシの裏だ。

専門学校卒のぽんこつえんじにあが個人事業主になって書いているただの日記。

【パズドラ】あいまい検索が面白かったので再現ロジックを組んでみた。

(*'▽') 便利なアップデートですね。

https://pad.gungho.jp/member/updates/img/12_4/top.jpg

パズドラ Ver12.4

モンスターBOXで「モンスター名検索」ができるようになります。

と言う事で、モンスターの名称検索が出来るようになりました。

この名称検索ですが、前方一致や部分一致ではなく、かなり柔軟なあいまい検索で実装されており、話題になっています。

曰く、

「キリ」で検索したらゼウスマーキュリー出て来たwww

とか。

「ヤマタケ」で検索したらきちんとヤマトタケル出て来た賢すぎワロタwww

とか。

オーディンオーディンたまドラがきちんと「おでん」でヒットするwww

とか。

なるほど確かに面白い動きをしています。

内部実装の想像

自分で幾つか検索を行って見て、動作結果からこんな感じの仕様かと予想を付けました。

  • 検索指定したワードは飛び飛びでもヒットする。
  • 大文字小文字の区別をしていない。(内部的にどちらかに寄せている)
  • ひらがなカタカナの区別をしていない。(内部的にどちらかに寄せている)
  • 一部キャラは、表示用名称とは別に検索用名称を持っている。


飛び飛びでもヒットする:

これはまぁ解り易いですね。

前述した通り、 「キリ」で検索した時に「ゼウスマーー」がヒットするとか、 「ヤマタケ」で検索した時に「ヤマタケル」がヒットするとか。

つまり、検索したいワードが、不連続でも良いから順番通りに含まれていれば良しと言うロジックです。


検索用名称:

重要なのは四つ目の仕様。

全キャラじゃないけど、検索用ワードを別で持っていると思われる。

この仕様自体はシステム開発ではよくある仕様ですね。

例えば住民データを管理するようなもので、氏名を画面入力値そのままで保持するのとあわせて、検索用に一般化した形で保持しておき、SQLで検索する時はそっちで検索する、みたいな。

或いは、電話番号や郵便番号などで、ハイフン入りのデータとは別にハイフン無しのデータを持っておき、検索する時はそっちを使う、とか。


検索用名称はごく一部っぽい:

思うに、検索用名称が設定されているキャラは、そう多くはないっぽいと言う事。

最初は、漢字の読みを殆ど全キャラ設定してるのかな、と思いましたがどうやらそうでもなさそうです。

例えば、

「転生」で検索すれば転生キャラが普通にヒットするが、

「てんせい」で検索するとヒットしない。

(全ての漢字の読みに対応している訳では無い、と言う事)

「ぎんぺ」で検索すると関銀屏がヒットする。

しかし、関銀屏のフルネームは「桃園の義将姫・関銀屏」なのに「とうえんの」で検索してもヒットしない。 きちんと漢字変換して「桃園」と打てばヒットする。

(恐らく「かんぎんぺい」だけが検索用ワードに設定されていると思われる)

「ぺっぱー」で検索すると、きちんと「Pepper」君がヒットする。

あいまい検索が面白かったので再現ロジックを組んでみた。

と言う事で、面白かったので、パズドラ風あいまい検索の再現ロジックを作ってみました。

こんなかんじの動作

f:id:sugaryo1224:20171121231738j:plain

f:id:sugaryo1224:20171121231802j:plain

f:id:sugaryo1224:20171121231816j:plain

f:id:sugaryo1224:20171121231825j:plain

あくまで、それっぽい動きをしているだけなのと、裏で持っているデータに差異があると思うので、細かい所で違いが出て来ますが、なかなかいい感じの動きが再現できたと思います。
(パズドラの方がやってない処理とかも幾つか加えてますし)

ちなみに、データはこんな感じです。

f:id:sugaryo1224:20171121231924j:plain

飛び飛びの検索ロジック

private static bool Like( string text, string word )
{
    // そもそも文字数が足りないのは検索するまでもない。
    if ( text.Length < word.Length ) return false;
    int index = 0;
    int tail = word.Length - 1;
    foreach ( char c in text )
    {
        if ( c == word[index] )
        {
            if ( tail == index )
            {
                // 検索ワードの終端に到達した場合、あいまい検索成立。
                return true;
            }
            else
            {
                // 検索ワードの終端でない場合、インデックスを進める。
                index++;
            }
        }
    }
    // 最後まで来ちゃったら検索ワードヒットせず。
    return false;
}

GitHub

ソースコード一式C#です)はここに置いておきました。

https://github.com/sugaryo/PZDRAimaiKensaku