今回は [ 算数ドリルを作ろう その4 ] の続きです。
説明の中でよく分からない所がでてきたら、とりあえずプログラムを入力して
実行結果を確認してみましょう。
そして説明が難しく思えたら、そのまま先に進むのも一つの手です。
分からない所でずっと止まっているのも苦痛ですから。
でも、ときどき前のページに戻って読み返すのも効果的ですよ。
必要なユーザーインターフェース部分はできたので、これからは内部処理です。
まずは問題の作成をしましょう。
問題は何度も出題することになるので専用のメソッドを作ります。
前準備として、問題を呼び出すための Form1_Load を用意しましょう。
フォームの何もないところでダブルクリックすると、自動で作られます。
Form1_Load はこのフォームが作られたとき1度だけ実行されます。
問題を出題するメソッド MondaiSakusei を作ります。
とりあえず計算タイプは足し算にします。
問題の作成には乱数を使います。
1桁の計算なので、 rand.Next(1, 10) を使い1から9を発生させます。
乱数を忘れてしまったときは次を参照してください。
[ ハイ&ローゲームを作ろう その7 ]
メソッド MondaiSakusei が正しく作動するか確認するため
Form1_Load の中で呼び出します。
それでは実行してみましょう。
ちゃんと問題が表示されました。
問題を表示している部分の(43 行目)
MondaiLbl.Text = noA + " + " + nob + " = "
ダブルクォーテーション内の + と = の左右にはスペースを入れてます。
これは単純に見た目を良くするためにしていることです。
次は答え合わせです。
こちらもメソッドを作ります。
何度もくり返す処理をメソッドとする使い方が一般的ですが
いくつかの処理を1つのメソッドにまとめることで、プログラムを
見やすくするという使い方もあります。
変数 noC を作り、ここに計算の答えを入れておきます。
この変数と入力値を比較することで、答え合わせができる訳です。
AppendText には \r\n(改行コード)を必要に応じて含ませるようにします。
改行コードがなければ続けて表示されます。
改行したいところに入れましょう。
入力処理 InBox_KeyPress の中に、出題と答え合わせのメソッドを追加しました。
これで( 出題 → 入力 → 答え合わせ → 出題 )というループになります。
テストとして出力していたものはコメントにします。(30 行目)
実行してみましょう。
問題の作成と答え合わせができたので、メインとなる処理はできました。
と言いたい所ですが、まだまだなんです。
実行して、答えに文字を入力してみて下さい。
文字を入力すると見慣れないメッセージが表示されます。
「 例外はハンドルされていません 」
これは簡単に言ってしまえばエラーが発生したのです。
処理の中に、間違った手順があることを示しています。
以前にもエラーの話はしましたが、それはビルド中に発生するエラーでした。
今回は実行中に発生したエラーなので、少し対応が変わります。
エラーに関する情報は、だいたい次のところを見るといいでしょう。
エラーの状況をしっかりと把握してから対応を考えます。
不具合がありそうな所を IDE が教えてくれます。(よく分からない場合もあります)
呼び出し履歴を見ると、入力処理 InBox_KeyPress の中から呼ばれた
答え合わせ Kotaeawase で止まったことが分かります。
これらの情報から 52 行目の
If ( noC == Int64.Parse ( InBox.Text ) )
ここで数値と文字列を比較したので例外が発生したことが分かります。
タイプの違うものを比較できないのです。
さて、原因が特定できたのでプログラムの修正をします。
その前に、いまはデバッグ中なのでこれを停止します。
停止ボタンをクリックしましょう。
なおデバッグ中とは、処理の状況やエラーの原因を探るためのモードです。
さて、数値だけを入力して欲しいのに、文字を入力されてエラーになってしまう
この状況をどうしますか?
この場合はエラーを出さないようにするのがベストです。
つまり、数値のみ入力を受け付けるようにします。
これなら文字列と比較すること自体がなくなります。
エラーが発生してから対応する方法もありますが、プログラムが難しくなります。
できるだけエラーを発生させないのが良いでしょう。
新しく追加した行は、むずかしいのでそのまま覚えてもかまいません。
数値のみ受け付けたいときに、この処理を追加すればいいのです。
一応、簡単に説明すると
文字コード0よりも小さく、9よりも大きく、さらに、バックスペース以外の時は
入力されたものを無効にしています。
( e.KeyChar < '0' || e.KeyChar > '9' )
この部分だけ文字コード表で見てみると次の範囲になります。
&& ( e.KeyChar != '\b' )
これはバックスペース以外のときを条件に追加しています。
e.Handled = true
これはいま入力されたことを無効にする処理です。
実行してみましょう。
まずは数値が入力できるか確認します。
そして入力した数値をバックスペースで消せることも確認しましょう。
次は文字の入力です。
プログラムが正常に動いているなら、文字の入力はできなくなっています。
数値のみ受け付けるようになって、これで完成と思ったことでしょう。
まだダメなんです。
実行して数値を入力せず、そのまま Enter キーを押してみてください。
エラーが発生しますね。
基本的に Enter キーの情報は、入力を決定するためのものなので
無視することはできません。
Enter キーが押されると答え合わせの処理が呼ばれますが
このとき入力データが「 何も無い 」このような状態を Null(ヌル)といいますが
これと変数 noC の比較をしてもエラーとなるのです。
これを回避するために入力データが Null の場合は除外するように
プログラムを変更します。
&& InBox.Text != ""
これで Null を除外します。
”(ダブルコーテーション)を2つ続けて書くと Null になります。
文字列用の変数を初期化するときにも使えます。(37 行目で使ってますね)
実行してみて下さい。
空打ち(なにも入力せず Enter を押す)してもエラーになりません。