テキスト編:p.315「超簡単1桁加算器(Char構造体と静的メソッド、ConsoleKeyInfo構造体とプロパティ)」から
ゲーム開発演習:自弾の発射と上移動、自弾の複数化、敵機の出現
p.315 超簡単1桁加算器(Char構造体と静的メソッド)
・C#のデータ型(p.41)は、内部的には.NET型(p.42)で表現されている
・この.NET型は、構造体として実装されている。
・よって「数値型のデータ型」.Parse(文字列)メソッド(p.45)は、.NET型の構造体のメソッドになっている
例: int.Parse()は、Int32構造体のParse()メソッド
・char型の.NET型であるChar構造体には、文字を扱うのに便利な下記のような静的メソッドが含まれている
・public static bool IsDigit(char 文字)メソッド:文字が10進数の数字かどうかを返す
・public static double GetNumericValue(char 文字)メソッド:文字を10進数の実数に変換して返す(変換できない場合は-1を返す)
※ double.Parse(文字列)と似た動作なので、double.Parse("" + 文字)と同じ動作になる。
しかし、double.Parseは変換できない場合は例外を投げる
p.315 超簡単1桁加算器(ConsoleKeyInfo構造体とプロパティ)
・p.293のbool KeyAvailableプロパティは、Consoleクラスの静的プロパティで、キー入力があったかどうかを返す
・これを受けて、押されたキーの情報を得られるのが、ConsoleKeyInfo構造体。
・この構造体オブジェクトを生成して押されたキーの情報を格納するのが、Consoleクラスの静的メソッドであるReadKey
・public static ConsoleKeyInfo ReadKey(bool 表示){…}
・表示がtrueの場合、押されたキーの文字は表示せず、falseだと表示する
例: ConsoleKeyInfo cki = Console.ReadKey(true); //押されたキーを得る
・ConsoleKeyInfo構造体にあるpublic char KeyCharプロパティを用いると、押されたキーの文字が得られる
p.315 超簡単1桁加算器(ConsoleKeyInfo構造体とプロパティ)
・p.293のbool KeyAvailableプロパティは、Consoleクラスの静的プロパティで、キー入力があったかどうかを返す
・これを受けて、押されたキーの情報を得られるのが、ConsoleKeyInfo構造体。
・この構造体オブジェクトを生成して押されたキーの情報を格納するのが、Consoleクラスの静的メソッドであるReadKey
・public static ConsoleKeyInfo ReadKey(bool 表示){…}
・表示がtrueの場合、押されたキーの文字は表示せず、falseだと表示する
例: ConsoleKeyInfo cki = Console.ReadKey(true); //押されたキーを得る
・ConsoleKeyInfo構造体にあるpublic char KeyCharプロパティを用いると、押されたキーの文字が得られる
p.317 event02.cs
//p.317 event02.cs
using System;
delegate void Handler(char ch); //デリゲートの宣言(引数有、戻り値型無し)
class EventClass { //イベント発生を担うクラス
public event Handler KeyHit; //イベントフィールド
public void OnKeyHit(char ch) { //イベントを発生させるメソッド
if (KeyHit != null) //イベントフィールドがヌルでなければ
KeyHit(ch); //デリゲート経由で呼び出す
}
}
class Show { //イベントで呼び出されるメソッドを持つクラス
int sum = 0;
public void keyshow(char ch) { //イベントで呼び出されるメソッド
if (Char.IsDigit(ch)) { //10進数字か?
int a = (int)char.GetNumericValue(ch); //実数に変換しintにキャスト
sum += a; //合計に足し込む
Console.WriteLine("+ {0}", a); //入力値を表示
Console.WriteLine("= {0}", sum); //合計を表示
} else if (ch == 'c') {
sum = 0; //合計をゼロクリアする
Console.WriteLine("合計がクリアされました");
} else { //10進数字でもクリアでもなければ
return; //何もしないで戻る
}
}
}
class event02 {
public static void Main() {
ConsoleKeyInfo cki; //キー情報構造体
EventClass ec = new EventClass(); //イベント発生を担うクラスのインスタンス生成
Show s = new Show();//イベントで呼び出されるメソッドを持つクラスのインスタンス生成
ec.KeyHit += new Handler(s.keyshow); //デリゲートにメソッドを登録。
while (true) { //無限ループ
if (Console.KeyAvailable) { //何かキーが押されている?
cki = Console.ReadKey(true); //そのキーを得る
if (cki.KeyChar == 'x') { //xキーならば
break; //抜ける=プログラム終了
} else {
ec.OnKeyHit(cki.KeyChar); //キー情報を渡してイベントを発生させる
}
}
}
}
}
アレンジ演習:p.317 event02.cs
・テキストp.319の通り、ラムダ式に書き換えよう
作成例
//アレンジ演習:p.317 event02.cs
using System;
delegate void Handler(char ch); //デリゲートの宣言(引数有、戻り値型無し)
class EventClass { //イベント発生を担うクラス
public event Handler KeyHit; //イベントフィールド
public void OnKeyHit(char ch) { //イベントを発生させるメソッド
if (KeyHit != null) //イベントフィールドがヌルでなければ
KeyHit(ch); //デリゲート経由で呼び出す
}
}
class Show { //イベントで呼び出されるメソッドを持つクラス
int sum = 0;
public void keyshow(char ch) { //イベントで呼び出されるメソッド
if (Char.IsDigit(ch)) { //10進数字か?
int a = (int)char.GetNumericValue(ch); //実数に変換しintにキャスト
sum += a; //合計に足し込む
Console.WriteLine("+ {0}", a); //入力値を表示
Console.WriteLine("= {0}", sum); //合計を表示
} else if (ch == 'c') {
sum = 0; //合計をゼロクリアする
Console.WriteLine("合計がクリアされました");
} else { //10進数字でもクリアでもなければ
return; //何もしないで戻る
}
}
}
class event02 {
public static void Main() {
ConsoleKeyInfo cki; //キー情報構造体
EventClass ec = new EventClass(); //イベント発生を担うクラスのインスタンス生成
Show s = new Show();//イベントで呼び出されるメソッドを持つクラスのインスタンス生成
ec.KeyHit += (c) => s.keyshow(c); //デリゲートにメソッドを登録。
while (true) { //無限ループ
if (Console.KeyAvailable) { //何かキーが押されている?
cki = Console.ReadKey(true); //そのキーを得る
if (cki.KeyChar == 'x') { //xキーならば
break; //抜ける=プログラム終了
} else {
ec.OnKeyHit(cki.KeyChar); //キー情報を渡してイベントを発生させる
}
}
}
}
}
p.320 練習問題 ヒント
・練習問題1は、p.308 lambda02.csをそのまま用いると良い
・練習問題2はevent02.csを基にしてアレンジしよう
① デリゲートの定義はlambda02.csからコピー
② すると、イベントフィールドがnullの場合もreturnが必須になるので、-1を返すとしよう
③ Mainメソッドにおける整数の受け取りを2回にして、その和を表示したら終了とする
④ デリゲートに登録するメソッドを「(x, y) => { return x + y; }」にできるので、keyshowメソッドはShowクラスを含めて不要になる
⑤「10進数字か」のチェックと「実数に変換しintにキャスト」はMainメソッドに移すと良い
作成例
//p.320 練習問題2
using System;
delegate int Handler(int x, int y); //【変更】デリゲートの宣言(引数有、戻り値型有)
class EventClass { //イベント発生を担うクラス
public event Handler KeyHit; //イベントフィールド
public int OnKeyHit(int x, int y) { //【変更】イベントを発生させるメソッド
if (KeyHit != null) { //イベントフィールドがヌルでなければ
return KeyHit(x, y); //【変更】デリゲート経由で呼び出す
} else { //【以下追加】
return -1;
}
}
}
class ex1202 {
public static void Main() {
ConsoleKeyInfo cki; //キー情報構造体
EventClass ec = new EventClass(); //イベント発生を担うクラスのインスタンス生成
ec.KeyHit += (x, y) => { return x + y; }; //【変更】デリゲートに匿名メソッドを登録。
int temp = -1; //【追加】1値目
while (true) { //無限ループ
if (Console.KeyAvailable) { //何かキーが押されている?
cki = Console.ReadKey(true); //そのキーを得る
char ch = cki.KeyChar; //その文字を得る
if (Char.IsDigit(ch)) { //【以下追加・変更】10進数字か?
int a = (int)char.GetNumericValue(ch); //実数に変換しintにキャスト
if (temp == -1) { //1値目?
temp = a;
} else { //2値目?
int sum = ec.OnKeyHit(temp, a); //キー情報を渡してイベントを発生させる
Console.WriteLine("{0} + {1} = {2}", temp, a, sum);
break;
}
}
}
}
}
}