テキスト編:「アレンジ演習:p.291 clock01.cs」から
ゲーム開発演習:背景画面のスクロール、アイテムの同時スクロール、左右移動 など
アレンジ演習:p.291 clock01.cs
・ストップウォッチにしよう ・実行すると「00:00:00」を表示してカウントを開始するようにしよう ・そのために、現在時刻ではなく、時刻を表す1000万分の1秒刻みのカウンタをDateTime構造体のTicksプロパティ(long型)で得て用いる ・起動時に現在時刻を持つオブジェクトを得たらTicksを確保しておき、最新のTicksとの差を算出する ・この差を1000万倍すると秒になるので、3600で割って時間を、60で割った結果の60の剰余で分を、60の剰余で秒を得ると良い
作成例
//アレンジ演習:p.291 clock01.cs
using System;
class clock01 {
public static void Main() {
int oldsecond = 0; //秒を比較用に保持する変数
Console.CursorVisible = false; //カーソルを非表示に
Console.Title = "時計"; //コンソールタイトル設定
Console.SetWindowSize(12, 3); //コンソールの大きさ設定
Console.BackgroundColor = ConsoleColor.Yellow; //背景色
Console.ForegroundColor = ConsoleColor.Black; //文字色
Console.Clear(); //変更を反映
DateTime st = DateTime.Now; //【追加】開始時の日付時刻オブジェクト
DateTime mt; //日付時刻オブジェクト用
while (true) { //無限ループ
mt = DateTime.Now; //現在日付時刻を得る
int lap = (int)((mt.Ticks - st.Ticks) / 10000000); //【追加】経過秒数を得る
int Hour = lap / 3600; //【追加】時間を得る
int Minute = lap / 60 % 60; //【追加】分を得る
int Second = lap % 60; //【追加】秒を得る
if (Second == oldsecond) { //【変更】秒が変わっていない?
continue; //後続処理をスキップして次へ
} else { //秒が変わっている?
oldsecond = Second; //【変更】新しい秒を取っておく
}
Console.SetCursorPosition(2, 1); //カーソルを前へ移動
Console.Write("{0:00}:{1:00}:{2:00}",
Hour, Minute, Second); //【変更】時分秒を各2桁で表示
if (Console.KeyAvailable) { //何かキーが押された?}
break; //繰返しを抜ける
}
}
}
}
アレンジ演習:p.291 clock01.cs・続き
・ミリ秒までのストップウォッチにしよう ・実行すると「00:00:00.000」を表示してカウントを開始するようにしよう(表示幅を4文字分増やす) ・最新のTicksとの差を1万倍するとミリ秒になるので、3600000で割って時間を、60000で割った結果の60の剰余で分を、 1000で割った結果の60の剰余で秒を、1000の剰余でミリ秒を得ると良い
作成例
//アレンジ演習:p.291 clock01.cs
using System;
class clock01 {
public static void Main() {
int oldmsecond = 0; //【変更】ミリ秒を比較用に保持する変数
Console.CursorVisible = false; //カーソルを非表示に
Console.Title = "時計"; //コンソールタイトル設定
Console.SetWindowSize(16, 3); //【変更】コンソールの大きさ設定
Console.BackgroundColor = ConsoleColor.Yellow; //背景色
Console.ForegroundColor = ConsoleColor.Black; //文字色
Console.Clear(); //変更を反映
DateTime st = DateTime.Now; //開始時の日付時刻オブジェクト
DateTime mt; //日付時刻オブジェクト用
while (true) { //無限ループ
mt = DateTime.Now; //現在日付時刻を得る
int lap = (int)((mt.Ticks - st.Ticks) / 10000); //【変更】経過秒数を得る
int Hour = lap / 3600000; //【変更】時間を得る
int Minute = lap / 60000 % 60; //【変更】分を得る
int Second = lap / 1000 % 60; //【変更】秒を得る
int MSecond = lap % 1000; //【追加】ミリ秒を得る
if (MSecond == oldmsecond) { //【変更】ミリ秒が変わっていない?
continue; //後続処理をスキップして次へ
} else { //秒が変わっている?
oldmsecond = MSecond; //【変更】新しいミリ秒を取っておく
}
Console.SetCursorPosition(2, 1); //カーソルを前へ移動
Console.Write("{0:00}:{1:00}:{2:00}.{3:000}",
Hour, Minute, Second, MSecond); //【変更】時分秒を各2桁で表示
if (Console.KeyAvailable) { //何かキーが押された?}
break; //繰返しを抜ける
}
}
}
}
p.294 練習問題 ヒント
・プロパティによる制限なので、エラー表示は含まなくて良い ・偶数は正の整数なので、構造体に含まれるメンバの型はuintにすると良い ・偶数しか保持できないようにするには、データメンバへの直接アクセスを禁止するしかない ・よって、データメンバはprivateとしよう ・そして、このデータメンバを扱うプロパティはpublicとする ・プロパティのsetにおいて、valueをチェックし、偶数であれば代入する ・プロパティのgetは通常通り
作成例
//p.294 練習問題
using System;
struct MyStruct { //構造体定義
private uint x; //構造体のデータメンバ
public uint X { //プロパティ
get { return x; }
set { if (value % 2 == 0) { x = value; } }
}
}
class struct01 {
public static void Main() {
MyStruct ms = new MyStruct(); //newが必要
ms.X = 10; //構造体のプロパティで代入
Console.WriteLine(ms.X); //構造体のプロパティを呼ぶ
ms.X = 11; //構造体のプロパティで代入(できない)
Console.WriteLine(ms.X); //構造体のプロパティを呼ぶ
}
}
第12章 デリゲートとイベント
p.295 デリゲートとは
・メソッドへの参照を保持しておいて、これを用いてメソッドを呼び出せる仕掛け
・C/C++における「関数へのポインタ」の考え方を洗練したもの
・C#公式リファレンスでは「代理人」と和訳されていることがあるが、ニュアンスが異なる
・主に、イベントなどで用いる
・利用には宣言と生成が必要で、宣言はクラスの外で行う
・宣言書式: delegate メソッドの戻り値型 デリゲート名(メソッドの引数リスト);
・この書式でわかる通り、デリゲートで用いたいメソッドと、戻り値型、引数リストが一致している必要がある
・例: delegate bool md(int w); //このデリゲートで「bool foo(int x){…}」などが扱える
・デリゲートの生成において、扱うメソッド名を指定する
・生成書式: デリゲート名 参照変数 = new デリゲート名(メソッド名);
・例: md work = new md(foo); //fooメソッドを呼び出せるデリゲートを生成しworkとする
・デリゲート経由でメソッドを呼び出すには、参照変数をメソッドの別名にように扱える
・例: bool ans = work(12); // bool ans = foo(12);と同じ動作になる
p.297 delegate01.cs
//p.297 delegate01.cs
using System;
delegate void MyDelegate(); //デリゲートの宣言(戻り値無、引数無))
class delegate01 {
public static void show() { //静的メソッド(Mainから呼出可)
Console.WriteLine("呼ばれました");
}
public static void Main() {
//直接showメソッドを呼び出す
show();
//デリゲートの作成
MyDelegate md = new MyDelegate(show);
//デリゲートを通してshowメソッドを実行
md();
}
}
p.298(別のクラスにあるインスタンスメソッドをデリゲート経由で呼び出す)
・別のクラスにあるインスタンスメソッドをデリゲート経由で呼び出すことができる ・そのクラスのインスタンスを生成して用いると良い ・生成書式: デリゲート名 参照変数 = new デリゲート名(インスタンス名.メソッド名);
作成例
//p.298 delegate02.cs
using System;
delegate void MyDelegate(); //デリゲートの宣言(戻り値無、引数無))
class MyClass {
public void show() { //インスタンスメソッド
Console.WriteLine("呼ばれました");
}
}
class delegate02 {
public static void Main() {
MyClass mc = new MyClass(); //インスタンスを生成
mc.show(); //インスタンスで直接呼出す
MyDelegate m = new MyDelegate(mc.show); //デリゲートを生成
m(); //デリゲート経由で呼出す(インスタンス名は不要)
}
}