メインコンテンツへスキップ
記事一覧に戻る
programming

日本語タイピングゲームの「shi」と「si」問題を解決する

タイピングゲームで「し」を「si」と入力しても正解にならない問題。複数のローマ字パターンに対応したマッチングアルゴリズムと、促音・「ん」の特殊処理を含む実装を解説します。

2026-01-0613 min readAdabana Saki
-
タイピングゲーム日本語入力ローマ字変換TypeScriptアルゴリズムReact

日本語タイピングゲームの「shi」と「si」問題を解決する

「なんで『si』って打ったのに間違いになるの?」

タイピングゲームを作ると必ずぶつかるこの問題。日本語には複数のローマ字入力方法があるのに、多くのタイピングゲームは1パターンしか受け付けません。

この記事では、150以上のローマ字パターンに対応したマッチングアルゴリズムと、促音(っ)や「ん」の特殊処理を含む実装を解説します。

なぜ「shi」だけじゃダメなのか

日本語入力の多様性

日本語のローマ字入力には、複数の流派があります:

ひらがなヘボン式訓令式JIS X 4063
しshisisi
ちchititi
つtsututu
ふfuhuhu
じjizizi

さらにIMEごとの方言もあります(Microsoft IME、Google日本語入力、ATOK...)。

ユーザーの期待

Text

ローマ字変換テーブルの設計

基本構造

ひらがな1文字(または2文字)に対して、複数のローマ字パターンを配列で定義します:

TypeScript

拗音(2文字)

拗音は2文字で1つの音なので、優先的にマッチングします:

TypeScript

外来語対応

最近のタイピングでは外来語も頻出:

TypeScript

部分入力マッチング

なぜ「部分一致」が必要か

タイピングゲームでは、ユーザーは1文字ずつ入力します。「sha」を打つ途中の「s」「sh」の段階でも、まだ正解の可能性があると判定する必要があります。

Text

マッチング関数の実装

TypeScript

促音(っ)の処理

子音の重ね

「っ」は次の文字の子音を重ねることで入力します:

Text

実装

TypeScript

マッチング時の処理

TypeScript

「ん」の文脈依存処理

問題:「n」だけで確定できない場合

「ん」は通常nで入力できますが、次の文字によってはnnが必要です:

Text

ルール

次の文字必要なパターン
子音(k, s, t...)n でOK
母音(a, i, u, e, o)nn または xn が必要
y行(ya, yu, yo)nn または xn が必要
な行(na, ni...)nn または xn が必要

実装

TypeScript

表示用ターゲット文字列の生成

動的なターゲット表示

ユーザーがsを打った時点で、ターゲット表示を動的に更新します:

Text

実装

TypeScript

getFirstRomajiPattern関数

TypeScript

React Hookとの統合

useTypingGameでの使用

TypeScript

文字表示のカラーリング

TypeScript

対戦モードへの対応

バトルモードでも同じローマ字変換ロジックを使用:

TypeScript

パフォーマンス考慮

変換テーブルのサイズ

150パターン以上のテーブルですが、JavaScriptのオブジェクトアクセスはO(1)なので問題ありません。

文字列操作の最適化

TypeScript

まとめ

問題解決策
複数ローマ字パターン配列で複数パターンを定義
部分入力の判定startsWithで前方一致チェック
促音(っ)次の文字の子音を取得して重ねる
「ん」の文脈依存次の文字をチェックして条件分岐
拗音(2文字)2文字パターンを優先してマッチング

この実装により、どんな入力方法のユーザーでも快適にプレイできるタイピングゲームが実現できます。

遊んでみる

実際にタイピングゲームを遊んでみたい方は、こちらからどうぞ:

ソースコード

この記事で紹介したコードの完全版はGitHubで公開しています:

このシリーズの他の記事

このサイトでは、他にもオンライン対戦ゲームの実装記事を公開しています:

参考リンク