草競馬プログラム C# 2005 5 プログラムの概要 6 頭の馬の内 一着でゴールする馬を予想してテキストボックスに 1 から 6 の数値を入力してスタートボタンをクリックする 馬は 乱数を利用して 右から左に 1 枡宛移動する 一定の時間間隔で乱数を発生させて該当する馬を 1 枡左に移動させるにはタイマーオブジェクトを使用する 1 頭の馬がゴールに達すると 予想が的中したか何うか判定を行い あたり 又は はずれ の表示を行う 今回の課題項目 単純変数の宣言 ( データ型変数名 ;) 配列変数の宣言 ( データ型 [ ] 変数名 = new データ型 [ 要素数 ];) 標準コントロールの利用 (Label Box Button Timer PictureBox Panel) プロパティの利用 ( Visible Left Enabled Name Ticks Success) イベントの利用 (Load Click Tick) メソッドの利用 (Focus Match Contains Next Dispose Exit) オブジェクトの利用 ( 乱数 :Random 正規表現 :Regex 変換 :Convert) 演算子 ( 代入演算子 算術演算子 比較演算子 論理演算子 ) 制御構造構文 ( 条件分岐 ループ処理 制御ステートメント ) 今回の重点項目 変数の適用範囲 ( スコープ : フォームモジュールレベル サブプロシージャレベル ) if 文に依る条件分岐 (if ( ~ ) else ) for 文に依るループ処理 (for( counter=start; condition; increment ) ) foreach 文に依るループ処理 (foreach ( element In group ) break ) 乱数系列の初期化と乱数の発生 (Random Next) 今回の応用項目 一着のタイムを表示する コースを往復にしたり 落馬等の処理を加える -1-
オブジェクト プロパティ一覧 ラベル 2 ラベル 1 ボタン 1 ラベル 3 ボタン 2 テキストボックス ラベル 4 パネル ピクチャー 7 ピクチャー 8 ピクチャー 1 ピクチャー 2 ピクチャー 3 ピクチャー 4 ピクチャー 5 ピクチャー 6 タイマー コントロールの種類 プロパティ プロパティの設定値 フォーム Name keiba 草競馬 FormBorderStyle FixedSingle MaximizeBox False StartPosition CenterScreen ラベル1 Name lbltitle 草競馬プログラム Font MS 明朝, 太字,24 ラベル2 Name lblmessage Red ForeColor White Font MS 明朝, 標準,24 あたり Align MiddleCenter Visible False ラベル3 Name lblexpect 予想 (1~6) Font MS 明朝, 太字,16 ボタン1 Name btnstart Font スタート (MS 明朝, 太字,12) -2-
コントロールの種類 プロパティ プロパティの設定値 ボタン2 Name btnfinish Font 終了 (MS 明朝, 太字,12) テキストボックス Name txtexpect 空白 Font MS 明朝, 太字,18 Align Center MaxLength 1 ImeMode Disable パネル Name pnlground Lime ピクチャーボックス1 Name picjocky1 Image jocky.gif TransParent ピクチャーボックス6 Name picjocky6 Image jocky.gif TransParent ピクチャーボックス7 Name picfence1 Image fence.gif TransParent ピクチャーボックス8 Name picfence2 Image fence.gif TransParent ラベル4 Name lblgoal AutoSize False Black Size.Width 2 空白 タイマー Name tmrrace デザイン時の注意事項 ピクチャボックス 1~8( ジョッキーとフェンス ) 及び ラベル 4( ゴール ) は パネルの中に配置する 特に ピクチャボックス 1~6 は 必ずパネルの中に配置しないと 意図する通りにプログラムが動作しない ピクチャボックス 2~6 は ピクチャボックス 1 を配置し 各プロパティを設定して 完成させてから 此れをコピーし 作成すると良い 猶 此の場合 上記でも記述した様に 必ず パネルの中に貼り付ける様にする 亦 此処では Font に総て MS 明朝を使用して居るが 此の様な場合 フォームの Font を MS 明朝に設定して置くと 此の設定が 其のフォームに属する総てのコントロールに継承される為 各コントロールでは サイズやスタイルを設定する丈で良く成る 此れは コンテナと成るコントロール ( パネルやグループボックス等 ) でも同様で有る -3-
ラベルテキストを表示するコントロール 此のテキストは ユーザーが直接入力したり変更したりする事は出来ない テキストボックステキストの入力や表示を行うコントロール 此のテキストは ユーザーが直接入力したり変更したりする事が出来る キャレットの移動や文字の削除等の入力に必要なを備えて居る ボタンユーザーが選択したコマンド ( 命令 ) や操作を実行するコントロール OK ボタンや実行ボタン等 処理の開始や中断 終了の合図に用いられ 最も良く利用されるコントロールで有る ボタンが押し下げられた様に外観が変わる為 プッシュボタンとも謂う ピクチャボックスビットマップ アイコン メタファイル JPEG ファイル GIF ファイル等の画像を表示するコントロール 従来のバージョン (VB 6.0) の様に 描画メソッドを用いて描画する事や 内部に他のコントロールを配置してコンテナと仕て使用する事はは出来ない パネル他のコントロールをグループ化する為のコンテナと成るコントロールで有る 通常は 別にフォームを細分化する為に使用する 亦 BackgroundImage プロパティを設定すると コントロールの背景にイメージが表示される タイマー一定の時間間隔でイベントが発生する様にするコントロール 一定時間毎にプログラムを実行したい時に使用する 此のコントロールは 実行時には表示されない 算術演算子 比較演算子 論理演算子 1.- 負数 1.== 等しい 1.! 否定 2.* / 乗算と除算 2.!= 等しくない 2.& 論理積 3./ 整数除算 3.< より小さい 3. 論理和 4.% 剰余 4.> より大きい 4.~ 排他的論理和 5.+ - 加算と減算 5.<= 以下 6.>= 以上 算術演算子と論理演算子では 複数の演算子が使用されて居る場合には 頭に付けた番号の順序で演算が行われる ( 上に書かれて居る演算子程優先順位が高い ) -4-
プログラムリスト using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.; using System.Windows.Forms; using System..RegularExpressions; // 追加 namespace keiba public partial class keiba : Form // フォームレベルでグローバルな変数の宣言 private int[ ] jocky = new int[ 6 ]; private int win; private System.Random rnd; public keiba( ) InitializeComponent( ); // フォームが読み込まれた時の処理 private void keiba_load( object sender, EventArgs e ) // タイマーの無効化 tmrrace.enabled = false; // 乱数系列の初期化 rnd = new Random( ( int ) DateTime.Now.Ticks ); // ボタン ( スタート ) がクリックされた時の処理 private void btnstart_click( object sender, EventArgs e ) int i, n; // 予想入力の適否判定 if ( Regex.Match( txtexpect., "^[1-6]" ).Success!= true ) txtexpect. = ""; txtexpect.focus( ); return; n = System.Convert.ToInt32( txtexpect. ); // 各馬の位置の初期化 for ( i = 0; i < 6; i++ ) jocky[ i ] = 0; foreach( Control c in this.pnlground.controls ) if ( c.name.contains( "picjocky" ) ) c.left = 532; ネームスペース ( 名前空間 ) の使用を宣言して居る 此の部分は エディタが 自動的に記述して下れる 此処では 正規表現に依る文字列の比較を行う為 此の名前空間を追加して居る 此処で宣言した変数は同じフォーム内の総てのサブプロシージャで値の参照と設定を行う事が可能 配列変数 ( アレー ) の宣言単純変数 ( スカラー ) の宣言クラスを生成する為のコンストラクタで有る 此の部分は エディタが 自動的に記述して下れる 乱数系列を初期化する為 起動時の時間を乱数の種 ( シード ) と仕て Random オブジェクトのインスタンスを生成する 此処で宣言した変数は宣言したサブプロシージャ内でしか値の参照と設定を行う事が出来ない 此のループ処理ではカウンター i の値を0から5に1 宛変化させて 処理を繰り返し行う パネルに内包されるコントロールの中で 名前に picjocky が含まれるコントロールの Left プロパティを 532 に設定して居る -5-
// 結果表示の消去 ( 不可視 ) lblmessage.visible = false; // 勝利判定の初期化 win = 0; タイマーの Enabled プロパティに設定すると Interval で設定された時間間隔で Tick イベントが発生する様に成る // タイマーの有効化 tmrrace.enabled = true; // タイマーが一定間隔で行う処理 private void tmrrace_tick( object sender, EventArgs e ) int r = rnd.next( 0, 6 ); // 0 から 5 迄の乱数を発生 // 該当する馬のコントロールの取得データ型の変換を行う C# では foreach( Control c in this.pnlground.controls ) データ型の変換は厳密で有る if ( c.name == "picjocky" + System.Convert.ToString( r + 1 ) ) // 乱数の示す馬を1 駒前進此処では2 種類の算術演算子が使 jocky[ r ]++; 用されて居る c.left = 532 - jocky[ r ] * 23; -: 減算 ( 引く ) // 勝ち馬の判定 if ( c.left <= 72 ) win = r + 1; // 勝負が付いた場合の処理 if ( win > 0 ) tmrrace.enabled = false; if ( System.Convert.ToInt32( txtexpect. ) == win ) lblmessage. = " あたり "; else lblmessage. = " はずれ "; lblmessage.visible = true; txtexpect. = ""; txtexpect.focus( ); break; // ボタン ( 終了 ) がクリックされた時の処理 private void btnfinish_click( object sender, EventArgs e ) this.dispose( ); Application.Exit( ); Random オブジェクトの Next メ ソッドで 第 1 引数以上 第 2 引 数未満の整数の乱数を発生 System.Convert オブジェクトは *: 乗算 ( 掛ける ) 優先順位は 数学と同じく乗算が 減算よりも高く 先に計算される 条件判定の If 文が入 れ子に成って居る 此の様な状態をネス ティングと謂う break は ループを強制的に脱出 するステートメントで有る 此処 では 該当する馬丈を処理すれば 後は処理を行う必要が無い アプリケーションを終了する場 合 正しくプログラムをメモリか ら消去して終了する事が望まし い -6-
foreach 文に依るループ処理 グループの各要素に対して一連のステートメントを繰り返し実行するステートメント foreach ( データ型要素 in グループ ) 一連の処理 ; 配列やコレクション ( オブジェクトの集合 ) の各要素の総てに対して 一連のステートメントを繰り返し実行する グループには オブジェクトコレクションや配列 又は 其等を参照するオブジェクト変数を指定し 要素には コレクションや配列から各要素を取り出して格納する変数を指定する 配列やグループのコレクションに要素が 1 つでも存在する場合 foreach ループが始まる 一旦 ループが開始されると グループの最初の要素に対してステートメントが実行される 然して グループの中に要素が有る限り ループ内のステートメントは 各要素に対して実行を続ける 要素が無く成れば ループを終了し ステートメントブロックの次のステートメントに実行が移る ループから強制脱出する方法と仕て ループ内の任意の位置に任意の数の break ステートメントを記述する事が出来る 通常 break ステートメントは 何等かの条件を評価した後で使用する 例えば if ステートメントを評価した後で 制御をステートメントブロックの次のステートメントに直ちに移動する場合に利用される foreach ループは 入れ子構造 ( ネスティング ) に出来る 即ち foreach ループの内部に別の foreach ループを入れる事が出来る 但し 夫々れのループの要素を表わす変数には一意の変数を指定する必要が有る return ステートメントに依るプロシージャ ( メソッド ) の脱出 プロシージャ ( メソッド ) から直ちに抜け呼出元に戻るステートメント return [ 戻り値 ]; 此のステートメントの在るプロシージャを直ちに抜け 制御をプロシージャを呼び出したステートメントの次のステートメントに移す 呼出元に値を返す必要が有る場合は 戻り値を指定する事も出来る プロシージャ ( メソッド ) が void 型の場合は return ステートメントは省略する事が出来る プロシージャ ( メソッド ) から強制脱出する方法と仕て プロシージャ内の任意の位置に任意の数の return ステートメントを記述する事が出来る 通常 return ステートメントは 何等かの条件を評価した後で使用する 例えば if ステートメントを評価した後で 制御を呼出元のプロシージャに直ちに移動する場合に利用される 但し 単純にプロシージャを強制脱出する手段と仕て用いる事も多い -7-
System.Random オブジェクトの Next メソッドに依る乱数の発生 乱数を返すメソッド Object.Next( ) Object.Next( 最大値 ) Object.Next( 最小値, 最大値 ) 最小値以上 最大値未満の整数の乱数を与える Random オブジェクトは 擬似乱数ジェネレータを表わすクラスで有る 擬似乱数は 有限個の数値の中から等しい確率で選び出される 此の数字を選出する為に使用する演算アルゴリズムには限界が有る為 選び出された数字は完全な乱数ではないが 実質的には乱数として充分使用出来る 乱数の生成には 初期値と仕てシード値を使用する 同じシードを繰り返し使用すると 生成される乱数系列も同じに成る 異なる乱数系列を生成するには シード値を時間に依り決定する事が多い 猶 パフォーマンスを向上するには 乱数を生成する為に 新しい Random オブジェクトを作成するのではなく 作成した Random オブジェクトを何回も使用し 多くの乱数を生成する様にする Focus メソッドに依るフォーカスの移動 指定されたコントロール 又は フォームにフォーカスを移すメソッド Object.Focus 指定したオブジェクトにフォーカスを移動する 実行後は 指定したフォーム 又は コントロールがユーザーからの総ての入力を受け取る フォーカスを設定出来るのは 表示されて居るフォーム 又は コントロール丈で有る 亦 フォーム又は コントロールの Enabled プロパティが偽 (False) に設定されて居ると 其のフォーム 又は コントロールにはフォーカスを設定する事は出来ない Visible プロパティに依るオブジェクトの表示 非表示 オブジェクトを表示するか非表示にするかを指定するプロパティ Object.Visible 指定したオブジェクトを表示するか非表示にするかを示すブール式 (True か False) を指定する 起動時にオブジェクトを非表示にするには デザイン時に Visible プロパティを偽 (False) に設定して置く 此のプロパティをコードで設定すると 実行時に特定のイベントに応じて表示する事が出来る Visible プロパティは オブジェクトの有効性を指定する Enabled プロパティと異なり 画面に表示するか何うかを設定するプロパティで有る 勿論 非表示のオブジェクトは Enabled プロパティが偽に設定されたオブジェクトと同様に ユーザーの操作で発生したイベントを認識する事は出来ない -8-
System.Convert オブジェクトの ToInt32 メソッドに依る文字列の数値化 文字列を数値化するメソッド 整数型変数 = System.Convert.ToInt32( 文字列 ) 指定した String 形式の数値を 其れと等価な 32 ビット符号付き整数に変換する 引数の文字列が null 参照の場合は 0 を返すが 引数の文字列の構成が 省略可能な符号と 其れに続く 0 から 9 迄の一連の数字で無い場合は エラーが発生する (FormatException) ToInt32 メソッドには 様々なオーバーロードが有り 様々なデータ型の引数から 其れと等価な 32 ビット符号付き整数に変換する事が出来る 亦 System.Convert クラスには 様々なパブリックメソッドが有り 様々なデータ型の引数から 其れと等価な様々なデータ型に変換する事が出来る C# では 暗黙的にデータ型を変換して下れる事は 殆ど無く 明示的にデータ型を変換する必要が有る為 System.Convert クラスは 重要なクラスで有る 猶 データ型を変換する事をキャスティングと謂う System..RegularExpressions.Regex オブジェクトの Match メッソドに依る正規表現検索 文字列内で 正規表現と一致する対象を検索するメソッド Object.Match( 文字列, 正規表現 ) 指定した文字列内で 正規表現で指定されたパターンと一致する対象を検索する 静的 Match メソッドは 正規表現パターンを指定して Regex オブジェクトを構築し インスタンスメソッド Match を呼び出す操作と同じで有る 此の静的メソッドは Regex オブジェクトを明示的に作成しなくても 正規表現を単独で 1 回丈使用出来る様にする目的で用意されて居る 実際に 指定した文字列が 正規表現で指定されたパターンと一致するか何うかを調べるには Match オブジェクトの Success プロパティを用いて 下記の様に使用する 猶 下記の式は 一致して居る場合は真 (true) を返し 一致しない場合は偽 (false) を返す Regex.Match( 文字列, 正規表現 ).Success String オブジェクトの Contains メッソドに依る文字列検索 指定した文字列がオブジェクト内に存在するか何うかを示す値を返すメソッド Object.Contains( 文字列 ) 現在のカルチャを使用して 単語 ( 大文字と小文字を区別し カルチャに依存した ) 検索を実行する 引数に指定した文字列が オブジェクトの文字列内に存在する場合は true 其れ以外の場合は false を返す 猶 引数に指定した文字列が 空の文字列 ( ヌルストリング ) の場合も true を返す -9-
座標系 オブジェクトのサイズ変更 移動 描画等のグラフィックス操作では 描画領域の座標系 又は コンテナの座標系が使用されて居る 座標系は グラフィカル効果を調整する場合丈で無く フォーム 及び コントロールの表示位置をアプリケーションで定義する場合にも使用される 座標系は 画面上 フォーム上 及び パネルや Graphics オブジェクト等のコンテナ上の位置を定義する為の 2 次元グリッドで有る 此のグリッド上の位置は (x, y) の様な形式で指定する 上記 x の値は X 軸方向の位置を表し 特に指定しない限り 左端が 0 で有る 亦 y の値は Y 軸方向の位置を表し 特に指定しない限り 上端が 0 で有る 下図は フォームの座標系の例で有る X 軸 (x) Y 軸 (y) Visual Basic の座標系には 次の様な規則が適用される コントロールの移動 又は サイズ変更を行う場合は 其のコントロールのコンテナの座標系を使用する フォーム上にオブジェクトを直接描画する場合は 其のフォームがコンテナと成る パネルやグループボックス内にコントロールを描画する場合は 其のパネルやグループボックスがコンテナに成る 画面の左上隅の座標は常に (0, 0) で有る コンテナの座標系でも 特に指定しない限り コンテナの左上隅の座標が (0, 0) と成る Visual Basic 6.0 では フォームやコントロールの座標が twip で表されて居たが Visual Basic.NET 以降では 座標はピクセルで表される 猶 アップグレード時には フォームやコントロールの Height プロパティと Width プロパティは 自動的にピクセルに変換される 猶 従来の twip をピクセルに変換する VB6.TwipsToPixelsX 関数と VB6.TwipsToPixelsY 関数が用意されて居るが 暫定的な物と思われ Visual Basic 6.0 から移植する場合でも ピクセルを使用して書き直した方が良いと思われる 亦 Visual Basic 6.0 では ScaleMode プロパティを使用して異なる座標系を定義する事が出来たが Visual Basic.NET 以降では ScaleMode と其れに関連するプロパティやメソッド (Scale ScaleHeight ScaleLeft ScaleTop ScaleWidth ScaleX ScaleY) は サポートされて居ない 此等をコードで実行時に操作して居る場合は コンパイルエラーを発生する -10-