講義メモ オブジェクト指向演習:プロパティの導入とゲーム性の向上&重複の防止 ゲーム開発演習:フォームサイズの固定化とコントールボックスの非表示、背景画像の表示 など オブジェクト指向演習(2) 【ha243 解説編より】プロパティ:再掲載 ・プロパティは特殊なメソッドで、データメンバを安全に扱う仕組みを提供する ・データメンバをpublicにしておくと、外部から想定外の値を代入されたり、想定外の用途に使われてしまう可能性がある  例:身長に負の数。計算で決まるはずのプレイヤーの経験値を直接操作。 ・そこで、重要なデータメンバはprivate(または無指定でprivate扱い)にする ・データメンバの値を得ることをget、値を書き換えることをsetといい、合わせてアクセッサという ・プロパティはgetとsetのどちらかまたは両方を記述して、publicではないデータメンバを扱う仕組みを外部に提供する ・最も基本的な定義例:  private 型 データメンバ名;  public 型 プロパティ名 {   set { データメンバ名 = value; }   get { return データメンバ名; }  } ・このように定義すると、外部から「データメンバ名 = 値;」の代わりに「プロパティ名 = 値;」とすることで、  データメンバに代入できる。 ・この時、プロパティのsetが動作し、値はvalueに渡される。 ・また「Console.WriteLine(プロパティ名 )」などとすることでデータメンバの値を表示できる。 ・この時、プロパティのgetが動作し、データメンバの値がreturnされる。 ・この仕掛けを用いて、setを省略することで、変更不能のデータメンバにできる  private 型 データメンバ名;  public 型 プロパティ名 {   get { return データメンバ名; }  } ・また、この仕掛けを用いて、setに条件を記述できる  private 型 データメンバ名;  public 型 プロパティ名 {   set {    if (value >= 0) {     データメンバ名 = value;    }   }   get { return データメンバ名; }  } RPG演習3 ・MadoshiクラスのHPを返すメソッドをプロパティHPにしよう ・また、魔導士の情報を表示するメソッドにMPの表示を追加しよう 作成例 //オブジェクト指向演習 RPG演習3 using System; class Madoshi { //魔導士を表すクラス(部品) int mp; //MP int hp; //HP Random rnd = new Random(); //乱数用のRandomクラスのインスタンスを生成 public Madoshi () { //コンストラクタ mp = rnd.Next(10); //0~9の間のランダムな整数を得てMPの初期値とする hp = 10 + rnd.Next(10); //10~19の間のランダムな整数を得てHPの初期値とする } public int HP { //【以下変更】HPを返すプロパティ get { return hp; } //getのみなので外部からのhpの書換を禁止 } public void DispInfo() { //魔導士の情報を表示する Console.Write("魔道士(HP={0} MP={1})", hp, mp); //【変更】HPMPを表示(改行しない) } public int Fight() { //魔道士があなたを攻撃し、あなたのダメージ値を返す if (rnd.Next(2) == 1) { //確率1/2で魔法攻撃かどうかを選ぶ int j = rnd.Next(5) + 1; //消費MPは1~5の乱数 DispInfo(); // 魔導士の情報を表示する Console.WriteLine("は消費MP" + j + "の魔法を唱えた!"); if (mp < j) { // MP不足? Console.WriteLine("MPが足りない!"); return 0; // あなたのダメージ=0を返す(攻撃終了) } else { // MP充足? Console.WriteLine("あなたは" + j * 4 + "のダメージを受けた!"); mp -= j; //MP消費 return j * 4; //あなたのダメージ=消費MPの4倍を返す(攻撃終了) } } else { //通常攻撃? int k = rnd.Next(5) + 1; //攻撃力は1~5の乱数 DispInfo(); //魔導士の情報を表示する Console.WriteLine("の攻撃!"); Console.WriteLine("あなたは" + k + "のダメージを受けた!"); return k; //あなたのダメージ=1~5を返す(攻撃終了) } } public void Damage() { //魔道士があなたからダメージをくらう int k = 5 + rnd.Next(5); //あなたの攻撃力は5~9の乱数 Console.WriteLine("あなたの攻撃!"); DispInfo(); //魔導士の情報を表示する(攻撃を受けた後の魔道士のHPを表示) Console.WriteLine("に" + k + "のダメージを与えた!"); hp -= k; //魔道士のHPをダウン } } class minimadou { //ゲーム本体のクラス public static void Main() { //ゲームを進行するメソッド string ans; //入力用 // 戦闘開始 int myhp = 20; // あなたのHP Madoshi m = new Madoshi(); // 魔道士を生成 m.DispInfo(); // 魔道士の情報を表示する Console.WriteLine("が現れた。"); // 戦闘中(あなたが死ぬか,魔道士が死ぬまで繰り返す) while (myhp > 0 && m.HP > 0) { //【変更】あなたのHPがあり、魔導士のHPがある間 Console.Write("残りHPは{0}です。攻撃しますか?(1:はい 0:やめる):", myhp); ans = Console.ReadLine(); // 攻撃するかどうかを得る if (ans == "1") { // はい? m.Damage(); // 魔道士を攻撃する if (m.HP > 0) { //【変更】魔道士は死んでない? myhp -= m.Fight(); // 魔道士の攻撃!あなたのHPをマイナス if (myhp <= 0) { // あなたのHPがもうない? Console.WriteLine("あなたは死にました。"); } } else { // 魔道士のHPがもうない? Console.WriteLine("魔道士を倒した!"); } } else { // やめる? break; // 繰り返し終了 } } } } ゲーム性の向上&重複の防止 ・「0:やめる」を選んだ場合がゲーム終了になるのではなく、終了するか魔導士の攻撃になるかの分岐にすると、ゲーム性が向上する。 ・この分岐の確率をどうするかはゲームデザインの一つになるが、特に必要なければ確率5割で良い。 ・なお、「0:やめる」を選んだ後に、魔導士の攻撃ターンを挟まずに再度選択に進むようなことにならないように注意。 ・このような改良により、同じ処理が2か所できてしまうことが多いので、ロジックを見直して1か所にまとめられるように工夫するとミスの防止や保守性(改良しやすさ)の向上につながる RPG演習3 ・「攻撃しますか?」で「0:やめる」を選んだ場合、確率5割で「逃げられない」か「逃げることができた」のどちらかを表示するようにしよう。 ・そして「逃げられない」を表示した場合、魔導士の攻撃ターンに進もう。 ・「逃げることができた」を表示した場合、繰返し終了としよう。 ・また「あなたのHPがもうない?」のチェックが重複しないように、判断の位置を見直そう ・なお、魔導士の攻撃ターンの重複はそのままでOK(この後の改造に関連するので) 作成例:途中(重複の防止をする前まで) //オブジェクト指向演習 RPG演習4(途中まで) using System; class Madoshi { //魔導士を表すクラス(部品) int mp; //MP int hp; //HP Random rnd = new Random(); //乱数用のRandomクラスのインスタンスを生成 public Madoshi () { //コンストラクタ mp = rnd.Next(10); //0~9の間のランダムな整数を得てMPの初期値とする hp = 10 + rnd.Next(10); //10~19の間のランダムな整数を得てHPの初期値とする } public int HP { //HPを返すプロパティ get { return hp; } //getのみなので外部からのhpの書換を禁止 } public void DispInfo() { //魔導士の情報を表示する Console.Write("魔道士(HP={0} MP={1})", hp, mp); //HPMPを表示(改行しない) } public int Fight() { //魔道士があなたを攻撃し、あなたのダメージ値を返す if (rnd.Next(2) == 1) { //確率1/2で魔法攻撃かどうかを選ぶ int j = rnd.Next(5) + 1; //消費MPは1~5の乱数 DispInfo(); // 魔導士の情報を表示する Console.WriteLine("は消費MP" + j + "の魔法を唱えた!"); if (mp < j) { // MP不足? Console.WriteLine("MPが足りない!"); return 0; // あなたのダメージ=0を返す(攻撃終了) } else { // MP充足? Console.WriteLine("あなたは" + j * 4 + "のダメージを受けた!"); mp -= j; //MP消費 return j * 4; //あなたのダメージ=消費MPの4倍を返す(攻撃終了) } } else { //通常攻撃? int k = rnd.Next(5) + 1; //攻撃力は1~5の乱数 DispInfo(); //魔導士の情報を表示する Console.WriteLine("の攻撃!"); Console.WriteLine("あなたは" + k + "のダメージを受けた!"); return k; //あなたのダメージ=1~5を返す(攻撃終了) } } public void Damage() { //魔道士があなたからダメージをくらう int k = 5 + rnd.Next(5); //あなたの攻撃力は5~9の乱数 Console.WriteLine("あなたの攻撃!"); DispInfo(); //魔導士の情報を表示する(攻撃を受けた後の魔道士のHPを表示) Console.WriteLine("に" + k + "のダメージを与えた!"); hp -= k; //魔道士のHPをダウン } } class minimadou { //ゲーム本体のクラス public static void Main() { //ゲームを進行するメソッド Random rnd = new Random(); //【追加】乱数用のRandomクラスのインスタンスを生成 string ans; //入力用 // 戦闘開始 int myhp = 20; // あなたのHP Madoshi m = new Madoshi(); // 魔道士を生成 m.DispInfo(); // 魔道士の情報を表示する Console.WriteLine("が現れた。"); // 戦闘中(あなたが死ぬか,魔道士が死ぬまで繰り返す) while (myhp > 0 && m.HP > 0) { //あなたのHPがあり、魔導士のHPがある間 Console.Write("残りHPは{0}です。攻撃しますか?(1:はい 0:やめる):", myhp); ans = Console.ReadLine(); // 攻撃するかどうかを得る if (ans == "1") { // はい? m.Damage(); // 魔道士を攻撃する if (m.HP > 0) { //魔道士は死んでない? myhp -= m.Fight(); // 魔道士の攻撃!あなたのHPをマイナス if (myhp <= 0) { // あなたのHPがもうない? Console.WriteLine("あなたは死にました。"); } } else { // 魔道士のHPがもうない? Console.WriteLine("魔道士を倒した!"); } } else { // やめる? if (rnd.Next(2) == 0) { //【以下追加】確率50%で Console.WriteLine("逃げられない!"); myhp -= m.Fight(); // 魔道士の攻撃!あなたのHPをマイナス:重複 if (myhp <= 0) { // あなたのHPがもうない?:以下重複 Console.WriteLine("あなたは死にました。"); } } else { //【追加】 Console.WriteLine("逃げることができた"); //【追加】 break; // 繰り返し終了 } } } } } 作成例 //オブジェクト指向演習 RPG演習4 using System; class Madoshi { //魔導士を表すクラス(部品) int mp; //MP int hp; //HP Random rnd = new Random(); //乱数用のRandomクラスのインスタンスを生成 public Madoshi () { //コンストラクタ mp = rnd.Next(10); //0~9の間のランダムな整数を得てMPの初期値とする hp = 10 + rnd.Next(10); //10~19の間のランダムな整数を得てHPの初期値とする } public int HP { //HPを返すプロパティ get { return hp; } //getのみなので外部からのhpの書換を禁止 } public void DispInfo() { //魔導士の情報を表示する Console.Write("魔道士(HP={0} MP={1})", hp, mp); //HPMPを表示(改行しない) } public int Fight() { //魔道士があなたを攻撃し、あなたのダメージ値を返す if (rnd.Next(2) == 1) { //確率1/2で魔法攻撃かどうかを選ぶ int j = rnd.Next(5) + 1; //消費MPは1~5の乱数 DispInfo(); // 魔導士の情報を表示する Console.WriteLine("は消費MP" + j + "の魔法を唱えた!"); if (mp < j) { // MP不足? Console.WriteLine("MPが足りない!"); return 0; // あなたのダメージ=0を返す(攻撃終了) } else { // MP充足? Console.WriteLine("あなたは" + j * 4 + "のダメージを受けた!"); mp -= j; //MP消費 return j * 4; //あなたのダメージ=消費MPの4倍を返す(攻撃終了) } } else { //通常攻撃? int k = rnd.Next(5) + 1; //攻撃力は1~5の乱数 DispInfo(); //魔導士の情報を表示する Console.WriteLine("の攻撃!"); Console.WriteLine("あなたは" + k + "のダメージを受けた!"); return k; //あなたのダメージ=1~5を返す(攻撃終了) } } public void Damage() { //魔道士があなたからダメージをくらう int k = 5 + rnd.Next(5); //あなたの攻撃力は5~9の乱数 Console.WriteLine("あなたの攻撃!"); DispInfo(); //魔導士の情報を表示する(攻撃を受けた後の魔道士のHPを表示) Console.WriteLine("に" + k + "のダメージを与えた!"); hp -= k; //魔道士のHPをダウン } } class minimadou { //ゲーム本体のクラス public static void Main() { //ゲームを進行するメソッド Random rnd = new Random(); //【追加】乱数用のRandomクラスのインスタンスを生成 string ans; //入力用 // 戦闘開始 int myhp = 20; // あなたのHP Madoshi m = new Madoshi(); // 魔道士を生成 m.DispInfo(); // 魔道士の情報を表示する Console.WriteLine("が現れた。"); // 戦闘中(あなたが死ぬか,魔道士が死ぬまで繰り返す) while (myhp > 0 && m.HP > 0) { //あなたのHPがあり、魔導士のHPがある間 Console.Write("残りHPは{0}です。攻撃しますか?(1:はい 0:やめる):", myhp); ans = Console.ReadLine(); // 攻撃するかどうかを得る if (ans == "1") { // はい? m.Damage(); // 魔道士を攻撃する if (m.HP > 0) { //魔道士は死んでない? myhp -= m.Fight(); // 魔道士の攻撃!あなたのHPをマイナス // if (myhp <= 0) { //【ここから移動】あなたのHPがもうない? // Console.WriteLine("あなたは死にました。"); // } } else { // 魔道士のHPがもうない? Console.WriteLine("魔道士を倒した!"); } } else { // やめる? if (rnd.Next(2) == 0) { //【以下追加】確率50%で Console.WriteLine("逃げられない!"); myhp -= m.Fight(); // 魔道士の攻撃!あなたのHPをマイナス } else { //【追加】 Console.WriteLine("逃げることができた"); //【追加】 break; // 繰り返し終了 } } if (myhp <= 0) { //【ここへ移動】あなたのHPがもうない? Console.WriteLine("あなたは死にました。"); } } } } 「3人の魔導士」に向けて ・魔導士の人数を複数化したい ・まずは「1人の魔導士」として開発し、Madoshiクラスの実装を確認しよう ・Madoshiクラスの改造ポイント  ①魔導士番号のint型インスタンス変数idを追加する  ②コンストラクタにint型引数idを追加し、生成時に魔導士番号を指定できるようにする  ③魔導士の情報を表示するメソッドで魔導士番号も表示しよう RPG演習5 3人の魔導士 ver.0 ・上記の「Madoshiクラスの改造ポイント」を実装し、動作を確認しよう 作成例: //オブジェクト指向演習 RPG演習5 using System; class Madoshi { //魔導士を表すクラス(部品) int mp; //MP int hp; //HP int id; //【追加】魔導士番号 Random rnd = new Random(); //乱数用のRandomクラスのインスタンスを生成 public Madoshi (int id) { //【変更】コンストラクタ mp = rnd.Next(10); //0~9の間のランダムな整数を得てMPの初期値とする hp = 10 + rnd.Next(10); //10~19の間のランダムな整数を得てHPの初期値とする this.id = id; //【追加】生成時に指定した魔導士番号を設定 } public int HP { //HPを返すプロパティ get { return hp; } //getのみなので外部からのhpの書換を禁止 } public void DispInfo() { //魔導士の情報を表示する Console.Write("魔道士{0}(HP={1} MP={2})", id, hp, mp); //【変更】表示(改行しない) } public int Fight() { //魔道士があなたを攻撃し、あなたのダメージ値を返す if (rnd.Next(2) == 1) { //確率1/2で魔法攻撃かどうかを選ぶ int j = rnd.Next(5) + 1; //消費MPは1~5の乱数 DispInfo(); // 魔導士の情報を表示する Console.WriteLine("は消費MP" + j + "の魔法を唱えた!"); if (mp < j) { // MP不足? Console.WriteLine("MPが足りない!"); return 0; // あなたのダメージ=0を返す(攻撃終了) } else { // MP充足? Console.WriteLine("あなたは" + j * 4 + "のダメージを受けた!"); mp -= j; //MP消費 return j * 4; //あなたのダメージ=消費MPの4倍を返す(攻撃終了) } } else { //通常攻撃? int k = rnd.Next(5) + 1; //攻撃力は1~5の乱数 DispInfo(); //魔導士の情報を表示する Console.WriteLine("の攻撃!"); Console.WriteLine("あなたは" + k + "のダメージを受けた!"); return k; //あなたのダメージ=1~5を返す(攻撃終了) } } public void Damage() { //魔道士があなたからダメージをくらう int k = 5 + rnd.Next(5); //あなたの攻撃力は5~9の乱数 Console.WriteLine("あなたの攻撃!"); DispInfo(); //魔導士の情報を表示する(攻撃を受けた後の魔道士のHPを表示) Console.WriteLine("に" + k + "のダメージを与えた!"); hp -= k; //魔道士のHPをダウン } } class minimadou { //ゲーム本体のクラス public static void Main() { //ゲームを進行するメソッド Random rnd = new Random(); //乱数用のRandomクラスのインスタンスを生成 string ans; //入力用 // 戦闘開始 int myhp = 20; // あなたのHP Madoshi m = new Madoshi(1); //【変更】魔道士1を生成 m.DispInfo(); // 魔道士の情報を表示する Console.WriteLine("が現れた。"); // 戦闘中(あなたが死ぬか,魔道士が死ぬまで繰り返す) while (myhp > 0 && m.HP > 0) { //あなたのHPがあり、魔導士のHPがある間 Console.Write("残りHPは{0}です。攻撃しますか?(1:はい 0:やめる):", myhp); ans = Console.ReadLine(); // 攻撃するかどうかを得る if (ans == "1") { // はい? m.Damage(); // 魔道士を攻撃する if (m.HP > 0) { //魔道士は死んでない? myhp -= m.Fight(); // 魔道士の攻撃!あなたのHPをマイナス } else { // 魔道士のHPがもうない? Console.WriteLine("魔道士を倒した!"); } } else { // やめる? if (rnd.Next(2) == 0) { //確率50%で Console.WriteLine("逃げられない!"); myhp -= m.Fight(); // 魔道士の攻撃!あなたのHPをマイナス } else { Console.WriteLine("逃げることができた"); break; // 繰り返し終了 } } if (myhp <= 0) { //あなたのHPがもうない? Console.WriteLine("あなたは死にました。"); } } } } 続「3人の魔導士」に向けて ・インスタンスオブジェクトを複数化して、同じ処理を行わせるので、インスタンスオブジェクトの配列にすると良い 補足:インスタンスオブジェクトの配列について ・初期化と同時に配列を生成する書式と、配列名を要素の数を指定して用意して、各インスタンスを生成する書式がある ・今回は後者を用いよう ① クラス名[] 配列名 = new クラス名[要素数]; ② 配列名[添字] = new クラス名(引数); を、全要素について繰り返す RPG演習6 3人の魔導士 ver.1 ・1人の魔導士のままで、魔導士オブジェクトを長さ1の配列で扱うようにしよう ・配列の生成はMain()メソッドで行う 作成例: //オブジェクト指向演習 RPG演習6 3人の魔導士 ver.1 using System; class Madoshi { //魔導士を表すクラス(部品) int mp; //MP int hp; //HP int id; //魔導士番号 Random rnd = new Random(); //乱数用のRandomクラスのインスタンスを生成 public Madoshi (int id) { //コンストラクタ mp = rnd.Next(10); //0~9の間のランダムな整数を得てMPの初期値とする hp = 10 + rnd.Next(10); //10~19の間のランダムな整数を得てHPの初期値とする this.id = id; //生成時に指定した魔導士番号を設定 } public int HP { //HPを返すプロパティ get { return hp; } //getのみなので外部からのhpの書換を禁止 } public void DispInfo() { //魔導士の情報を表示する Console.Write("魔道士{0}(HP={1} MP={2})", id, hp, mp); //表示(改行しない) } public int Fight() { //魔道士があなたを攻撃し、あなたのダメージ値を返す if (rnd.Next(2) == 1) { //確率1/2で魔法攻撃かどうかを選ぶ int j = rnd.Next(5) + 1; //消費MPは1~5の乱数 DispInfo(); // 魔導士の情報を表示する Console.WriteLine("は消費MP" + j + "の魔法を唱えた!"); if (mp < j) { // MP不足? Console.WriteLine("MPが足りない!"); return 0; // あなたのダメージ=0を返す(攻撃終了) } else { // MP充足? Console.WriteLine("あなたは" + j * 4 + "のダメージを受けた!"); mp -= j; //MP消費 return j * 4; //あなたのダメージ=消費MPの4倍を返す(攻撃終了) } } else { //通常攻撃? int k = rnd.Next(5) + 1; //攻撃力は1~5の乱数 DispInfo(); //魔導士の情報を表示する Console.WriteLine("の攻撃!"); Console.WriteLine("あなたは" + k + "のダメージを受けた!"); return k; //あなたのダメージ=1~5を返す(攻撃終了) } } public void Damage() { //魔道士があなたからダメージをくらう int k = 5 + rnd.Next(5); //あなたの攻撃力は5~9の乱数 Console.WriteLine("あなたの攻撃!"); DispInfo(); //魔導士の情報を表示する(攻撃を受けた後の魔道士のHPを表示) Console.WriteLine("に" + k + "のダメージを与えた!"); hp -= k; //魔道士のHPをダウン } } class minimadou { //ゲーム本体のクラス public static void Main() { //ゲームを進行するメソッド Random rnd = new Random(); //乱数用のRandomクラスのインスタンスを生成 string ans; //入力用 // 戦闘開始 int myhp = 20; // あなたのHP Madoshi[] m = new Madoshi[1]; //【追加】魔導士の配列を生成 m[0] = new Madoshi(1); //【変更】魔道士1を魔導士[0]に生成 m[0].DispInfo(); //【変更】魔道士[0]の情報を表示する Console.WriteLine("が現れた。"); // 戦闘中(あなたが死ぬか,魔道士が死ぬまで繰り返す) while (myhp > 0 && m[0].HP > 0) { //【変更】あなたのHPがあり、魔導士[0]のHPがある間 Console.Write("残りHPは{0}です。攻撃しますか?(1:はい 0:やめる):", myhp); ans = Console.ReadLine(); // 攻撃するかどうかを得る if (ans == "1") { // はい? m[0].Damage(); //【変更】魔道士[0]を攻撃する if (m[0].HP > 0) { //【変更】魔道士[0]は死んでない? myhp -= m[0].Fight(); //【変更】魔道士[0]の攻撃!あなたのHPをマイナス } else { //魔道士のHPがもうない? Console.WriteLine("魔道士を倒した!"); } } else { // やめる? if (rnd.Next(2) == 0) { //確率50%で Console.WriteLine("逃げられない!"); myhp -= m[0].Fight(); //【変更】魔道士[0]の攻撃!あなたのHPをマイナス } else { Console.WriteLine("逃げることができた"); break; // 繰り返し終了 } } if (myhp <= 0) { //あなたのHPがもうない? Console.WriteLine("あなたは死にました。"); } } } } オブジェクト指向演習:次回予告:3人の魔導士の続き(オブジェクト配列、乱数の改良) ゲーム開発演習(2):フォームサイズの固定化とコントロールボックスの非表示、背景画像の表示 など 演習4 フォームの初期位置の指定:再掲載 ・フォームの初期位置を(300, 0)にしよう 作成例 //演習4 フォームの初期位置の指定 using System; //C#標準クラス用 using System.Windows.Forms; //C#が提供するApplication、Formクラス用 using System.Drawing; //Sizeクラス用 class Program { static void Main() { //実行用メソッド(publicはなくてOK) Form f = new Form(); //Formクラスのインスタンスを生成 f.Text = "Game"; //Form名を設定 Size s = new Size(640, 480); //幅と高さの大きさのSizeインスタンスを生成 f.Size = s; //インスタンスプロパティで大きさを設定 f.StartPosition = FormStartPosition.Manual; //「手動設定」を設定 Point p = new Point(300,0); //X座標とY座標のPointインスタンスを生成 f.Location = p; //インスタンスプロパティで初期位置を設定 Application.Run(f); //生成済のインスタンスを実行 } } テーマ5 フォームサイズの固定化とコントロールボックスの非表示 ・特に指定のないフォームはフォームサイズの変更や最大化が可能 ・これは固定サイズで開発したいゲームプログラムの場合、弊害を起こすので、フォームサイズを固定化すると良い ・フォームサイズの固定化には、FormのインスタンスプロパティFormBorderStyleに、FormBorderStyle列挙体のFixedSingle列挙子などを代入すると良い  → https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.forms.formborderstyle ・フォームの最大化を防止するには、コントロールボックスを非表示にすると良い ・コントロールボックスを非表示にするには、FormのインスタンスプロパティControlBoxにfalseを代入すればOK ・ただし、フォームの閉じる「×」も非表示になるので、プログラム内にフォームのクローズ処理を記述していない場合は、タスクバーで右クリックし「ウィンドウを閉じる」を用いること ・そして、フォームサイズを固定化により、フォームの枠の大きさが変わるので、フォームの大きさの指定方法を変更する必要がある ・FixedSingle等を指定した後に、FormのインスタンスプロパティSizeではなく、ClientSizeに幅と高さの大きさのSizeインスタンスを代入すると良い 演習5 フォームサイズの固定化とコントールボックスの非表示 ・フォームのボーダーをFixedSingleにしよう ・コントロールボックスを非表示にしよう ・フォームのSizeではなくCliantSizeを640×480にしよう 作成例 //演習5 フォームサイズの固定化とコントールボックスの非表示 using System; //C#標準クラス用 using System.Windows.Forms; //C#が提供するApplication、Formクラス用 using System.Drawing; //Sizeクラス用 class Program { static void Main() { //実行用メソッド(publicはなくてOK) Form f = new Form(); //Formクラスのインスタンスを生成 f.Text = "Game"; //Form名を設定 //Size s = new Size(640, 480); //【削除】幅と高さの大きさのSizeインスタンスを生成 //f.Size = s; //【削除】インスタンスプロパティで大きさを設定 f.StartPosition = FormStartPosition.Manual; //「手動設定」を設定 Point p = new Point(300,0); //X座標とY座標のPointインスタンスを生成 f.Location = p; //インスタンスプロパティで初期位置を設定 f.FormBorderStyle = FormBorderStyle.FixedSingle; //【追加】フォームサイズの固定化 f.ControlBox = false; //【追加】コントールボックスの非表示 f.ClientSize = new Size(640, 480); //【追加】クライアントサイズの幅と高さを指定 Application.Run(f); //生成済のインスタンスを実行 } } テーマ6 フォーム上の描画の基礎 ・フォームアプリケーションにおいては、プログラム側からの描画だけでなく、システム側からの必要に応じた再描画を行う必要がある ・例えば、フォームの一部が画面の外部になってから内部に戻された場合、システム側で再描画を行う ・C#のフォームアプリケーションはこのことに対応するメソッド protected void OnPaint(PaintEventArgs)メソッドを提供している ・このメソッド内に記述された内容が、システム側からの必要に応じた再描画で自動的に用いられる ・プログラム側からの描画内容をこのメソッド内に記述するには:  ① プログラムのクラスをFormクラスの派生クラスにする  ② protected void OnPaint(PaintEventArgs e)メソッドをオーバライドする  ③ オーバライドの冒頭で、元のメソッドの内容を「base.OnPaint(e);」で呼び出して、基本的な描画処理を行う  ④ ③の後に、プログラム側からの描画内容を記述する 演習6 プログラム側からの描画内容を記述する準備 ・下記の手順。なお、実行結果は(まだ)変わらない ① ProgramクラスをFormクラスの派生クラスにする ② protected void OnPaint(PaintEventArgs e)メソッドのオーバライドメソッドを追記 ③ ②の中に、元のメソッドの内容を呼び出す「base.OnPaint(e);」を記述 作成例 //演習6 プログラム側からの描画内容を記述する準備 using System; //C#標準クラス用 using System.Windows.Forms; //C#が提供するApplication、Formクラス用 using System.Drawing; //Sizeクラス用 class Program : Form { //【変更】Formクラスの派生クラス protected override void OnPaint(PaintEventArgs e) { //【以下追加】描画処理のオーバライド base.OnPaint(e); //元のメソッドの内容を呼び出す } static void Main() { //実行用メソッド(publicはなくてOK) Program f = new Program(); //【変更】自クラスのインスタンスを生成 f.Text = "Game"; //Form名を設定 f.StartPosition = FormStartPosition.Manual; //「手動設定」を設定 Point p = new Point(300,0); //X座標とY座標のPointインスタンスを生成 f.Location = p; //インスタンスプロパティで初期位置を設定 f.FormBorderStyle = FormBorderStyle.FixedSingle; //フォームサイズの固定化 f.ControlBox = false; //コントールボックスの非表示 f.ClientSize = new Size(640, 480); //クライアントサイズの幅と高さを指定 Application.Run(f); //生成済のインスタンスを実行 } } 提出:演習6 プログラム側からの描画内容を記述する準備 ゲーム開発演習:次回予告:メッセージボックス、システム側からの必要に応じた再描画の確認、背景画像の描画