プログラムの概要
赤と青の2者が順番にサイコロを振り、出た目の数だけ駒を 進めて行き、停止したマス目を自分の色に塗り潰して、自分 の陣地に出来ると謂う、所有る陣取りゲームを作成する。 マス目は最初に其のマスに停止した方の陣地となり、既に孰 れかの色に塗り潰されて居るマスに、後から別の駒が停止し ても、陣地の占領者が変わる事は無い。 総てのマス目が孰れかの色に塗り潰されゝばゲームは終了 し、最終的に多くのマスを塗り潰した方が勝ちと成る。 □ 単純・配列変数の宣言(Private、Static、Dim) □ 標準コントロールの利用(Panel、PictureBox、Label、Button、Timer) □ コントロール配列の利用(Control 型のオブジェクト配列変数にコントロールを格納) □ プロパティの値の取得と設定(BackColor、Name、Text、Width、Height、Location 等) □ イベントの利用(Load、Click、Tick) □ メソッドの利用(Equals、Add) □ ステートメントの利用(Call、Exit Sub)□ サブプロシージャーの作成と呼出(Private Sub プロシージャ名、Call) □ 組込関数の利用(SubString、Int、Val、Rnd、Cstr、MsgBox)
□ 演算子(代入演算子、比較演算子、結合演算子)
□ 制御構造構文(条件分岐 If ~ Then、Select Case、ループ処理 For ~ Next)
占領双六ゲーム
VB 2005 ⑨ 今回の課題項目 □ 変数の適用範囲(Private、Static、Dim) □ コントロール配列の利用(Control 型のオブジェクト配列変数にコントロールを格納) □ 埋め込み画像の利用(リソースの利用)□ Select Case 文による条件分岐(Select Case ~ Case … End Select) 今回の重点項目
□ マス毎に点数を付け、高得点を競うゲームにする。 □ 先に9地点占領するとゲームが終了する様にする。 □ 色々なルールを考えて観る。
■ オブジェクト・プロパティ一覧 ■ コントロールの種類 プロパティ プロパティの設定値 フォーム Name sugoroku BackColor White FormBorderStyle FixedSingle Icon saikoro.ico MaximizeBox False StartPosition CenterScreen Text 占領双六ゲーム♪ パネル1 Name pnlMasu00 BackColor Aqua(任意の色に設定しても良い) … パネル16 Name pnlMasu15 BackColor Aqua(任意の色に設定しても良い) ピクチャーボックス1 Name picDice Image 1.gif(ローカルリソースでインポート) Size 32, 39 ピクチャーボックス2 Name picRed Image picred.gif(ローカルリソースでインポート) Size 37, 37 ピクチャーボックス3 Name picBlue Image picblue.gif(ローカルリソースでインポート) Size 37, 37 ラベル ピクチャーボックス1 タイマー2 コマンドボタン タイマー1 左上を起点に 時計廻りに配置 パネル1 ~ パネル16 ピクチャーボックス3 ピクチャーボックス2
コントロールの種類 プロパティ プロパティの設定値 ラベル Name lblDisp AutoSize False BackColor Black ForeColor White Text、Font 1(MS明朝, 太字, 12) TextAlign MiddleCenter ボタン Name btnDice BackColor Blue ForeColor White Text、Font ぽちっと♪(任意) タイマー1 Name tmrDice Interval 200 タイマー2 Name tmrGo Interval 500 ラベル テキストを表示するコントロール。此のテキストは、ユーザーが直接入力したり変更したりす る事は出来ない。 ボタン ユーザーが選択したコマンド(命令)や操作を実行するコントロール。OKボタンや実行ボタ ン等、処理の開始や中断・終了の合図に用いられ、最も良く利用されるコントロールです。 パネル 他のコントロールをグループ化する為のコンテナと成るコントロールで有る。通常は、機能別 にフォームを細分化する為に使用する。亦、BackgroundImage プロパティを設定すると、コ ントロールの背景にイメージが表示される。 タイマー 一定の時間間隔でイベントが発生する様にするコントロール。一定時間毎にプログラムを実行 したい時に使用する。此のコントロールは、実行時には表示されない。 ビットマップ、アイコン、メタファイル、JPEGファイル、GIFファイル等の画像を表示 するコントロール。従来のバージョン(VB 6.0)の様に、描画メソッドを用いて描画する事 や、内部に他のコントロールを配置してコンテナと仕て使用する事はは出来ない。 デザイン時の注意 パネルは、左上隅を起点にに最初のパネル(pnlMasu00)を配置して、以下時計廻りに15個のパ ネル(pnlMasu01~pnlMasu15)を配置する。
■ 画像ファイルを実行ファイルに埋め込む ■ ソリューションエクスプローラで『総てのファイルを表示』をクリックし(左図)、『My Project』を展 開してResouces.resx をダブルクリックする(右図)。 下図の様に、RESX タブが表示されるので、『リソースの追加』→『新しいイメージ』と進み、『GIF イ メージ』をクリックする、 下図のダイアログボックスでは、リソース識別名(此処では、Dice1から Dice6とする)を入力し、『追 加』ボタンをクリックする。 WEB ブラウザ等の関連付けられたアプリケーションが起動し、該当ファイル(上記では、Dice1.gif) を表示しようとするが、何も表示されないので、アプリケーションを閉じる。 追加したリソース(例えば、Dice1)のプロパティで、Persistence プロパティを、『.resx に埋め込まれ ました』に変更する。
追加したリソースを右クリックして、ポップアップメニューを表示し、『ファイルからインポート』を クリックする。 ファイルを指定するダイアログボックスが表示されるので、対応する画像を選択し、『開く』ボタンを クリックする。 上記の手順で、必要な画像ファイル(此処では、1.gif から6.gif)を、リソースに取り込む。 ※ 猶、RESX タブに、画像ファイル等を直接ドラッグ&ドロップするか、又は、プロジェクト内の Resouces フォルダに、画像ファイル等を直接コピーして、ポップアップメニューから『プロジェク トに含める』をクリックして、リソースを取り込む事も出来る。 (上図では、表示方法を『一覧での表示』と仕て居る。)
■ プログラムリスト ■
Public Class sugoroku
' フォームレベルでグローバルな変数の宣言
Private Dice As Byte ' 賽子の目数 Private MasuCnt As Byte ' 占領桝総数
Private Turn As Byte ' 手番(0:赤、1:青) Private PMasu(1) As Byte ' 現在桝目位置
Private BaseColor As Color ' 桝目背景色
Private pnlMasu(15) As Panel ' 桝目を表わす Panel オブジェクト Private picKoma(1) As Control ' 駒を表わす PictureBox オブジェクト
' フォームが読み込まれた時の処理
Private Sub sugoroku_Load( ByVal sender As Object, ByVal e As System.EventArgs ) _ Handles Me.Load Dim C As Control Dim N As Byte ' 桝目の元の背景色の取得 BaseColor = pnlMasu00.BackColor ' コントロールの Object 配列化 For Each C In Me.Controls
If C.Name Like "pnlMasu*" Then N = Val( C.Name.Substring( 7 ) ) pnlMasu( N ) = C
ElseIf C.Name.Equals( "picRed" ) Then picKoma( 0 ) = C
ElseIf C.Name.Equals( "picBlue" ) Then picKoma( 1 ) = C End If Next ' ゲームの初期化 Call gameinit( ) End Sub ' 駒を表示するジェネラルプロシージャ
Private Sub KomaDisp( ByVal T As Byte ) Dim X, Y As Integer
X = (pnlMasu( Pmasu(T)).Width - picKoma(T).Width) / 2 Y = (pnlMasu( Pmasu(T)).Height - picKoma(T).Height) / 2 X = X + (T = 0) * X / 2 - (T > 0) * X / 2
picKoma( T ).Location = New Point( X, Y )
pnlMasu( Pmasu( T ) ).Controls.Add( picKoma( T ) ) End Sub 此処でPrivate 宣言した変数は同 じフォームモジュール内の総ての サブプロシージャで値の参照と設 定を行う事が出来る。 色を格納する変数にはColor オブ ジェクト型を使用する。 Call は、Sub プロシージャ等に制 御を渡すステートメントで有る。 此処で宣言した変数は宣言したサ ブプロシージャ内でしか値の参照 と設定を行う事が出来ない。 Visual Basic.NET 以降ではコン トロール配列が使用出来ない為、 コントロールを配列変数に格納。 オブジェクトの比較には、比較演 算子(=)では無く、Equals メソ ッドを使用する。。 駒を枡の中央に配置する様に横方 向と縦方向の座標を求めた後、駒 が同じ枡に停止した時の為に、横 方向の位置を外らして居る。 コントロールの Left プロパティ とTop プロパティは、Location プ ロパティで纏めて設定出来る。 コンテナの Controls コレクショ ンに Add メソッドでコントロー ルをコンテナ化する事が出来る。
' ゲームの初期化を行うジェネラルプロシージャ Private Sub GameInit( )
Dim I As Byte
' 各枡の背景色を元の色に設定 For I = 0 To 15
pnlMasu( I ).BackColor = BaseColor Next I
' 変数や駒の位置等の初期化 Turn = 0
MasuCnt = 0
Pmasu( 0 ) = 0 : Call KomaDisp( 0 ) Pmasu( 1 ) = 8 : Call KomaDisp( 1 ) lblDisp.Text = "赤の番♪"
btnDice.Enabled = True End Sub
' ボタン(ぽちっと♪)がクリックされた時の処理
Private Sub btnDice_Click( ByVal sender As Object, ByVal e As System.EventArgs ) _ Handles btnDice.Click
' トグル形式で tmrDice の Enabled プロパティを変更 If tmrDice.Enabled = False Then
tmrDice.Enabled = True Else tmrDice.Enabled = False tmrGo.Enabled = True End If End Sub ' タイマー(賽子を振る)が一定間隔で行う処理
Private Sub tmrDice_Tick( ByVal sender As Object, ByVal e As System.EventArgs ) _ Handles tmrDice.Tick Dim S As String ' 乱数で賽子の目を設定 Dice = Int( Rnd( ) * 6 + 1 ) lblDisp.Text = CStr( Dice ) ' リソース識別名の設定 S = "Dice" & CStr( Dice ) ' 賽子の画像を表示 picDice.Image = My.Resources.ResourceManager.GetObject( S ) End Sub 此処で宣言した変数は宣言したサ ブプロシージャ内でしか値の参照 と設定を行う事が出来ない。 此のループ処理ではカウンターI の値を0 から 15 に 1 宛変化させ て、Next 迄の処理を繰り返し行 う。 引数を指定してSub プロシージャ の呼び出す。此れは、ローカルな 変数値等を他のプロシージャに引 き渡す時に利用する。 Enabled プロパティが、True の場 合は False に、False の場合は True にと謂う様に循環する動作 をトグルと謂い、プログラムでは 良く利用される。 Rnd 関数を用いて1から6迄の乱 数を発生させて整数化し、其れを ラベルに表示して居る。 埋め込まれたリソースを実行時に 読み込む為の公式で有る。
' タイマー(駒を進める)が一定間隔で行う処理
Private Sub tmrGo_Tick( ByVal sender As System.Object, ByVal e As System.EventArgs ) _ Handles tmrGo.Tick
Static GoCnt As Byte Static RedCnt As Byte Dim C As Color
btnDice.Enabled = False GoCnt += 1
Pmasu( Turn ) += 1
If Pmasu( Turn ) = 16 Then Pmasu( Turn ) = 0 Call KomaDisp( Turn )
If Dice = GoCnt Then tmrGo.Enabled = False GoCnt = 0
' 駒が占領されて居ない枡に停止した場合
If pnlMasu(Pmasu(Turn)).BackColor.Equals(BaseColor) Then
If Turn = 0 Then C = Color.Red : RedCnt += 1 Else C = Color.Blue pnlMasu(Pmasu(Turn)).BackColor = C MasuCnt += 1 ' ゲーム終了 If MasuCnt = 16 Then If RedCnt > 8 Then MsgBox( "赤の勝ち!!", , "ゲーム終了♪" ) ElseIf RedCnt = 8 Then
MsgBox( "引き分け!!", , "ゲーム終了♪" ) Else MsgBox( "青の勝ち!!", , "ゲーム終了♪" ) End If RedCnt = 0 Call GameInit( ) Exit Sub End If End If
Select Case Turn Case 0 Turn = 1 lblDisp.Text = "青の番♪" Case 1 Turn = 0 lblDisp.Text = "赤の番♪" End Select btnDice.Enabled = True End If End Sub End Class 最高値を超えた場合に最初に戻る 様な動作をトグルと謂い、プログ ラムでは良く利用される。 変数の値を1増やす事をインクリ メントと謂い、プログラムでは良 く利用される。 Static ステートメントで宣言した 変数は、Sub プロシージャを抜け ても、プログラムが実行されて居 る間を通して保持される。 インクリメントは A=A+1 と謂う 事で有るが、使用頻度が高い為に A+=1 と謂う簡略形も使用可。 条件判定に、比較演算子を使用し て居る。 A > B : AはBより大きい ElseIf 節は、最初の条件を満たさ 無い場合で、更に条件分岐する必 要の有る時に用いる。評価する変 数が同一の場合には Select Case 文を使用する事も出来る。 Exit Sub ステートメントは、以降 のコードを実行せずに、直ちに Sub プロシージャを抜ける命令で 有る。 変数の取り得る値が0か1で、0 なら1に、1なら0にトグル形式 で変更するには、論理演算子 Xor を用いてA=A Xor 1 と謂う様に記 述する事も出来る。
Substring メソッドに依る文字列の操作 部分文字列を取得するメソッド Object.Substring(開始位置, 文字数) Object で表わされる文字列の開始位置から指定した文字数丈切り出した文字列を返す。 引数の開始位置には、開始位置のインデックスを指定し、省略する事は出来ない。 引数の文字数には、切り取る文字数を指定し、省略可能で有る。 引数の開始位置は、0から始まるインデックスで指定する。亦、引数の文字数を省略した場合は、イン デックス以降の末尾迄の総ての文字列が切り出される。 Equals メソッドに依るオブジェクトの比較 2個のオブジェクトが同一か比較するメソッド Object.Equals(オブジェクト) 2個のオブジェクトが同一で有ればTrue を、同一でなければ False を返す。 引数のオブジェクトには、比較するオブジェクトを指定し、省略する事は出来ない。 オブジェクトの比較は、プリミティブな型の値を比較する = 演算子で比較する事は出来ない。其処で オブジェクトの比較には、Is 演算子か Equals メソッドを用いる。
猶、String 型は、実際には、オブジェクト型で有るが、使用頻度が高い為、Visual Basic では、プリミ ティブな型の様に、= 演算子で比較する事が出来る。 Add メソッドに依るコントロールのコンテナ化 コントロールコレクションにコントロールを追加するメソッド Object.Controls.Add(コントロール) コントロールコレクションにコントロールを追加し、コンテナ化(内包)する。 引数のコントロールには、コレクションに追加するコントロールを指定し、省略する事は出来ない。 Object は、フォーム、パネル、グループボックス等のコンテナに成る事の出来るコントロールで有る必 要が有る。コンテナに成る事の出来るコントロールとは、他のコントロールを内包する事の出来るコン トロールの事を謂う。 猶、追加されるコントロールが、既に他のコントロールの子コントロールで有る場合、別のコントロー ルに追加される前に、現在の親コントロールのコレクションから削除される。 機 能 書 式 解 説 機 能 書 式 解 説 機 能 書 式 解 説
変数の宣言と適用範囲(スコープ) モジュールレベルで総てのサブプロシージャで参照出来る変数の宣言 Private 変数名 As 型 モジュールの全般(General)の宣言部(Declarations)に記述する。 標準モジュール、フォームモジュールの孰れでも宣言出来る。 プロシージャレベルでのみ参照出来る変数の宣言① Dim 変数名 As 型 通常、プロシージャの最初の部分に記述する。 実行カーソルがサブプロシージャを抜けると記憶内容は抹消される。 モジュールレベルでの宣言にも使用出来るが、混同を避ける為に、使い分ける事が望ましい。 プロシージャレベルでのみ参照出来る変数の宣言② Static 変数名 As 型 通常、プロシージャの最初の部分に記述する。 実行カーソルがサブプロシージャを抜けても記憶内容は保持し続ける。 アプリケーションレベルで総てのモジュールで参照出来る変数の宣言 Public 変数名 As 型 標準モジュールの全般(General)の宣言部(Declarations)に記述する。 機 能 書 式 解 説 機 能 書 式 解 説 機 能 書 式 解 説 書 式 解 説 機 能 型の種類と範囲 Byte(バイト型) : 0 ~ 255 Integer(整数型) : -32,768 ~ 32,767 Long(長整数型) : -2,147,483,648~ 2,147,483,647 Single(単精度実数型) : -3.402823E38~3.402823E38 Double(倍精度実数型) : -4.94065645841247E-324~4.94065645841247E-324 Currncy(通貨型) : -922,337,203,685,477.5808~922,337,203,685,477.5807 String(文字列型) : 0~2GB Boolean(ブール型) : 真(True)または偽(False) Date(日付型) : 100 年 1 月 1 日~9999 年 12 月 31 日 Variant(バリアント型) : 総ての型に対応
.NET Framework 対応 ■ 文字列の部分一致
従来の記述法
If C.Name Like "pnlMasu*" Then .NET Framework の記述法
If C.Name.StartsWith("pnlMasu") Then
.NET Framework では、文字列の部分一致の検証には、String クラスの様々なメソッドを使用するが 出来る。 前方一致の場合は、上記の StartsWith メソッド、後方一致の場合は、EndsWith メソッド、部分一致 の場合は、Contains メソッドが提供されて居る。 猶、.NET Framework には、種々のパターン(例えば、メールアドレスや電話番号等)に合致するか検 証するには、Regex クラスが提供されて居る。 此の正規表現を簡易に行う事が出来るのが、Like 演算子で有り、Basic 固有の演算子では有るが、有用 な演算子で有り、Visual Basic でプログラミングして居る場合、特に書き直す必要は無い。 ■ 文字列の数値化 従来の記述法 N = Val(C.Name.Substring(7)) .NET Framework の記述法 N = Byte.Parse(C.Name.Substring(7))
.NET Framework では、文字列を数値化するには、変換後のデータ型を表すクラスの Parse メソッド を使用する。 但し、Val 関数は、文字列を先頭から評価して行き、数値と仕て評価出来る処迄を数値化して返し、数 値と仕て評価出来ない場合は0 を返すと謂う柔軟性が有るが、Parse メソッドでは、文字列が、変換後 のデータ型と合致しない場合は、例外(エラー)が発生する。 其の為、入力された文字列を数値化する場合等では、入力された文字列が、変換後のデータ型と合致す るか検証する為、TryParse メソッドを使用する必要が有る。 但し、上記では、コントロール名を正しく付けて居れば、8 文字目(インデックスは 7)以降は、必ず 整数値なので、変換後のデータ型と合致するかの検証は、必要が無い。
猶、上記では、変数N が、Byte 型なので、Byte クラスの Parse を使用して居るが、変換後のデータ型 を表すクラス(例えば、変数N が、Double 型なら、Double クラス)の Parse を使用する。
■ 乱数の発生
従来の記述法
Dice = Int(Rnd() * 6 + 1) .NET Framework の記述法 Dice = New Random().Next(1, 7)
.NET Framework では、乱数を発生させるには、Rnd 関数ではなく、Random オブジェクトの Next メソッドを使用する。 クラスをインスタンスを変数に割り当てず、上記の様に、生成したインスタンスで、其の儘、メソッド を実行する事も出来る。 上記では、1 以上 7 未満の整数値(Integer 型)が返される。猶、Rnd 関数の様に、0.0 以上 1.0 未満の 実数値(Double 型)を返す NextDouble メソッドも提供されて居る。 ■ リソースの利用 Basic 固有の記述法
picDice.Image = My.Resources.ResourceManager.GetObject("Dice" & CStr(Dice)) .NET Framework の記述法
Dim R As System.Resources.ResourceManager = _
New System.Resources.ResourceManager("sugoroku.Resources", GetType(sugoroku).Assembly) picDice.Image = R.GetObject("Dice" & CStr(Dice))
上記は、孰れも、.NET Framework の記述法で有るが、My は、Basic 固有の機能で、頻繁に使用する メソッドやプロパティやイベントに解り易いアクセス方法を提供して居る。
併し、C#等でも使用出来る、.NET Framuwork の一般的な記述法で記述すると、下記の記述法と成る。 此の場合、Next メソッドが、共有メソッド(Shared Method)でない為、先ず、ResourceManager ク ラスのインスタンスを生成する必要が有る。 ■ タイマーの始動・停止 従来の記述法 tmrDice.Enabled = False tmrDice.Enabled = True .NET Framework の記述法 tmrDice.Stop() tmrDice.Start()
.NET Framework では、タイマーの始動・停止には、Start メソッドや Stop メソッドを使用するも出 来る(孰れも、結果は同じで有る)。