こんにちは!ジェイです。
前回まででCTypeEngineクラスのローマ字入力の内部処理を説明しました。
サンプルプロジェクトはこちらから
内容は
・ひらがなからローマ字の文章を生成する(MakeInputStr)
・ひらがなからローマ字の入力候補を生成する(MakeSeachStr)
・入力した文字を元に正誤判定をしてその後に対応した処理をする
だいぶ長い説明になってますが、内容としては以上です。
今回はかな入力で同じ内容を説明していきますが、ローマ字入力に比べて判定が1文字ずつで済む分のでシンプルで理解しやすいです。
それでは、さっそく作っていきましょう!
ひらがなから濁点と半濁点を分解して入力文章を作る
ローマ字入力では、辞書から検索して対応するアルファベットを入れて変換する作業があって大変でしたが、かな入力ではひらがなの濁点と半濁点を分解するだけなので簡単です。
まずは、検索するための辞書になる2次元配列Stについてみてみます。
>|C#|
private string[,] DecStr = new string[,]
{
{"が","か","゛"},
{"ぎ","き","゛"},
{"ぐ","く","゛"},
{"げ","け","゛"},
{"ご","こ","゛"},
{"ざ","さ","゛"},
{"じ","し","゛"},
{"ず","す","゛"},
{"ぜ","せ","゛"},
{"ぞ","そ","゛"},
{"だ","た","゛"},
{"ぢ","ち","゛"},
{"づ","つ","゛"},
{"で","て","゛"},
{"ど","と","゛"},
{"ば","は","゛"},
{"び","ひ","゛"},
{"ぶ","ふ","゛"},
{"べ","へ","゛"},
{"ぼ","ほ","゛"},
{"ぱ","は","゜"},
{"ぴ","ひ","゜"},
{"ぷ","ふ","゜"},
{"ぺ","へ","゜"},
{"ぽ","ほ","゜"},
{"ヴ","ウ","゛"},
{"ガ","カ","゛"},
{"ギ","キ","゛"},
{"グ","ク","゛"},
{"ゲ","ケ","゛"},
{"ゴ","コ","゛"},
{"ザ","サ","゛"},
{"ジ","シ","゛"},
{"ズ","ス","゛"},
{"ぜ","セ","゛"},
{"ゾ","ソ","゛"},
{"ダ","タ","゛"},
{"ヂ","チ","゛"},
{"ヅ","ツ","゛"},
{"デ","テ","゛"},
{"ド","ト","゛"},
{"バ","ハ","゛"},
{"ビ","ヒ","゛"},
{"ブ","フ","゛"},
{"ベ","ヘ","゛"},
{"ボ","ホ","゛"},
{"パ","ハ","゜"},
{"ピ","ヒ","゜"},
{"プ","フ","゜"},
{"ペ","ヘ","゜"},
{"ポ","ホ","゜"},
};
||<
string型の二次元配列DecStrの[0,0]には濁点または半濁点のひらがなの文字が入っていて、ループ分を用いて検索しこれと同じ文字を発見した時に[0,1]と[0,2]にある文字を分解してstrに保存します。
例
が→か+゛
もし検索しても辞書になかったらそのままひらがなを1文字代入するという処理を繰り返して、ひらがなの文章を1行すべて分解します。
>|C#|
public class CKanaTypeEngine : CTypeEngine
{
const int ST_COL = 227;
const int ST_ROW = 3;
string[,] St = new string[ST_COL, ST_ROW];
public override string MakeInputText(string input_textk)
{
string str = string.Empty;
for (int i = 0; i < input_textk.Length; ++i)
{
bool update = false;
for (int j = 0; j < DecStr.GetLength(0); ++j)
{
if (DecStr[j, 0] == input_textk[i].ToString())
{
update = true;
str += DecStr[j, 1] + DecStr[j, 2];
break;
}
}
if (!update)
{
str += input_textk[i];
}
}
NowInputText = str;
return str;
}
}
||<
MakeInputStrの処理は以上ですべてです。
ローマ字入力
に比べると複雑な処理がいらないしコードの量もとても少ないですよね。
ひらがなから入力判定用の文字を作る(MakeSearchStr)
こちらもローマ字入力の時と同じように、入力時に判定するための検索文字を保存しておく処理を行います。
単純にSt[i,0]に入っている1文字とひらがなの文章の1文字を比較してから、もし同じ文字があったら、シフト押してない時の1文字のSt[i,1]とシフト押している時の1文字のSt[i,2]を検索文字配列SearchStrsにそれぞれ保存しておきます。
St[i,1]だけに文字が入っている場合はシフトなしの時のみ正解判定になって、St[i,2]にも文字が入っている場合は、シフトを押していてもどちらでも正解判定になります。
>|C#|
public override List<string> MakeSearchStr(string input_textk, int str_posk)
{
SearchStrs[0] = string.Empty;
SearchStrs[1] = string.Empty;
string str_buf = MakeInputText(input_textk).Substring(str_posk, 1);
for (int i = 0; i < ST_COL; ++i)
{
if (str_buf == St[i, 0])
{
SearchStrs[0] = St[i, 1];
SearchStrs[1] = St[i, 2];
break;
}
}
return SearchStrs.ToList();
}
||<
これだけで入力判定用検索文字を保存できました!
1つだけ注意する点は先ほど説明したMakeInputStr()を読んで濁点と半濁点を分解する処理をしてから入力判定用検索文字の保存を行っていることです。
キー入力から正誤判定をしてそれぞれに対応した処理をする
これもローマ字入力に比べて非常に単純でGetKeyString()にkeyとShiftを渡して2つ分の情報を1つにしてtemp_strに格納します。
それと先ほどMakeSearchStrで保存しておいた検索用の文字が格納されてるSerachStrs配列の要素のどちらかと同じであったら、正解でTextPosが引数で渡されたinput_textkの要素数と同じになったら、タイピング文章が打ち終わったことになるので、終了処理を行います。
MakeInputStr()は1つの文章につき1回呼んで、MakeSearchStr()は1文字正解して打ち終わるごとに処理を実行します。ミスをした時にはフラグを立てるだけなので難しいことはないです!
>|C#|
protected override bool InputJudge(string[] input_textk, string key, bool shift)
{
string temp_str = GetKeyString(key, shift);
if (temp_str == null) return false;
// 一致判定
if (SearchStrs[0] == temp_str || SearchStrs[1] == temp_str)
{
TypeMissFlag = false;
// 一文終了
if (++StrPosK >= NowInputText.Length)
{
InputPos = 0;
StrPosK = 0; // 入力文(かな)ポジション
// 全文終了
if (input_textk.Length <= ++TextPos)
{
TextPos = 0;
return true;
}
// 次のかな文章を作成してInputTextに代入
NowInputText = MakeInputText(input_textk[TextPos]);
if (NowInputText == null)
{
Debug.Log("NowInputText is null");
return false;
}
}
MakeSearchStr(input_textk[TextPos], StrPosK);
InputPos = StrPosK;
}
else // ミス時
{
TypeMissFlag = true;
}
return false;
}
||<
まとめ
・ひらがなから濁点と半濁点を分解した文章を生成する(MakeInputStr)
・ひらがなからシフトなしの時の正解文字とシフトありの時の正解文字を入力候補として保存する(MakeSeachStr)
・入力した文字を元に正誤判定をしてその後に対応した処理をする
ローマ字入力とまったく同じ関数名で同じ役割の処理なのに関わらず、中身の処理を見てみるとまるで別物なのがわかります。
それを、すべての基底クラスであるCTypeEngineクラスのメソッドをオーバーライドして中身を全部入れ替えて、ローマ字入力とかな入力に対応できるのは素晴らしいですよね!
これでローマ字入力だけでなく、かな入力と両方に対応したタイピングゲームを作る知識を最低限ではありますが説明しました。
ただ今回のサンプルは説明のために無理にクラスの外に出してしまったために、よくない点がいくつかあるのに気づいた人もいるでしょう。
次回でそれらを修正した上で、完全版のプロジェクトを配布するとともにすべての機能の説明をして最後の講座にする予定です。それではまた次回会いましょう~!