前回は盤面にバブルを配置するところまでを説明しました。
エクセル de バブルブレーカー(Excel de Bubble Breaker)のダウンロードはこちらから
今回は盤面のバブルを選択した時に背景の色を変更するプログラムを作ります。
まず今回付け加えるコードを書きそれを説明していきます。
赤文字が今回加えたコードです。
1行目 Option Explicit
2行目
3行目 Private Sub CommandButton1_Click()
4行目
5行目 Call 盤面初期化
6行目
7行目 End Sub
8行目
9行目
10行目 Private Sub Worksheet_SelectionChange(ByVal Target As Range)
11行目
12行目 Call checkBreak(Target)
13行目
14行目 End Sub
「Worksheet_selectionChange」とはワークシートで選択範囲を変更したときに実行されるというものです。
今回は盤面のセルをクリックすると実行されます。
というわけで盤面にあるセルをクリックすると「checkBreak(Target)」が実行されます。
引数として選択されている範囲 Range オブジェクトが渡されます。
続いてモジュールです。
1行目 Option Explicit
2行目
3行目 Public sht設定シート As Worksheet
4行目 Public sht盤面シート As Worksheet
5行目 Public rng盤面 As Range
6行目
7行目 Private rng開始位置 As Range
8行目 Private str開始位置 As String
9行目 Private int盤面縦 As Integer
10行目 Private int盤面横 As Integer
11行目 Private int開始位置縦 As Integer
12行目 Private int開始位置横 As Integer
13行目 Private rngバブル色範囲 As Range
14行目 Private lngバブル色(1 To 5) As Long
15行目 Private lng通常背景色 As Long
16行目 Private lng選択背景色 As Long
17行目
18行目 Private Type typPlayField
19行目 lngBackColor As Long
20行目 lngBubbleColor As Long
21行目 End Type
22行目
23行目 Private arrPlayField(1 To 30, 1 To 200) As typPlayField '30は上限値。200は横。自由に設定すればよい
同様に12行目の「int開始位置横」には盤面内で選択されたセルの横の値が入ります。
18行目~23行目までは使い方だけ簡単に説明します。
使い方は arrPlayField(x, y).lngBackColor = 「Long型の何か」
arrPlayField(x, y).lngBubbleColor = 「Long型の何か」
のように使えます。
今回の場合は盤面内のセルの背景の色とバブルの色に使ってますので、
コードを見ながら使い方をつかんで下さい。
Private Sub 設定値取得()
Dim i As Integer
Set sht設定シート = Application.Worksheets("Sheet1") '将来シート名が変わったときここだけを変更する。
Set sht盤面シート = Application.Worksheets("Sheet1") '将来シート名が変わったときここだけを変更する。
↓↓(省略)
int開始位置縦 = rng開始位置.Row
int開始位置横 = rng開始位置.Column
End Sub
Subプロシージャ、設定値取得の1番下に2行追加します。
「int開始位置縦 = rng開始位置.Row」 は盤面の開始位置のセルの縦を取得し
最初の宣言で付け加えた「int開始位置縦」に代入しています。
同様に「int開始位置横」には盤面の開始位置のセルの横を取得したものを代入しています。
■前回のコード■
Public Sub 盤面初期化()
↓↓(省略)
With rng盤面
↓↓(省略)
With .Borders(xlEdgeRight)
.LineStyle = xlContinuous
.Weight = xlMedium
.Color = RGB(0, 0, 0)
End With
.Value = "●"
.Interior.Color = lng通常背景色
End With
'ランダムに色をつける
With rng盤面
For i = 1 To int盤面縦
For j = 1 To int盤面横
.Cells(i, j).Font.Color = lngバブル色(Int(Rnd() * 5) + 1)
Next j
Next i
End With
End Sub
■今回のコード■
↓↓(省略)
With rng盤面
↓↓(省略)
With .Borders(xlEdgeRight)
.LineStyle = xlContinuous
.Weight = xlMedium
.Color = RGB(0, 0, 0)
End With
.Value = "●"
1行目 For i = 1 To int盤面縦
2行目 For j = 1 To int盤面横
3行目 arrPlayField(i, j).lngBackColor = lng通常背景色 '背景色を設定する
4行目 .Cells(i, j).Interior.Color = arrPlayField(i, j).lngBackColor
5行目 arrPlayField(i, j).lngBubbleColor = lngバブル色(Int(Rnd() * 5) + 1)
6行目 .Cells(i, j).Font.Color = arrPlayField(i, j).lngBubbleColor
7行目 Next j
8行目 Next i
End With
End Sub
では、今回変えた部分について説明します。
1行目 1から「int盤面縦」の範囲での繰り返しです。
2行目 1から「int盤面横」の範囲での繰り返しです。
3行目~4行目
通常時の背景の色を配列arrPlayField(i, j).lngBackColorに代入しています。
繰り返しが終了するときには「arrPlayField(1,1).lngBackColor」から「arrPlayField(int盤面縦,int盤面横).lngBackColor」のすべてに背景の色が代入されます。
先ほど「arrPlayField(1,1)」から「arrPlayField(int盤面縦,int盤面横)」に入れた背景色を
「Cells(1,1).Interior.Color」から「Cells(int盤面縦, int盤面横).Interior.Color」に再び入れます。
この2つの処理で盤面のすべてのセルに背景の色がつきました。
5行目~6行目
3行目~4行目とほぼ同じです。
「 lngバブル色(Int(Rnd() * 5) + 1)」を「arrPlayField(i, j).lngBubbleColor」に代入しています。
「lngバブル色(Int(Rnd() * 5) + 1)」は前回にやりました。5色の中からランダムにバブルに色をつけていく処理でしたね。
つまり「arrPlayField(1,1).lngBubbleColor」から「arrPlayField(int盤面縦,int盤面横).lngBubbleColor」に
それぞれランダムに5つの色が入っています。
先ほど「arrPlayField(i, j).lngBubbleColor」を「Cell(i, j).Font.Color」に入れていきます。
Cellにはあらかじめ"●"が入っているのでそれぞれの"●"に色がついていきます。
デバッグしながら実際の動きをみるとどの行がどの処理をしているのかわかりやすいと思います。
ここからが盤面がクリックされた時の処理内容です。
では早速コードを見てみましょう。
1行目 Public Function checkBreak(ByRef Target As Range) As Boolean
2行目 Dim intV As Integer
3行目 Dim intH As Integer
4行目
5行目 intV = Target.Row - int開始位置縦 + 1
6行目 intH = Target.Column - int開始位置横 + 1
7行目 checkBreak = checkBreakSub(intV, intH)
8行目
9行目 End Function
1行目 今回の最初に書いた「chekBreak」プロシージャの呼び出しです。
2行目~3行目 プロシージャ内で使う変数の宣言です。
5行目 intVに盤面内での縦の位置を代入しています。
「Target.Row」は選択したセルの縦の位置です。「int開始位置縦」は盤面の開始位置でしたね。
最後の+1は一番上の行を1にする為です。もし「Target.Row - int開始位置縦」だけだと
一番上の列が選択されると「intVは0になってしまいます。
0ではわかりにくいですし、今回は1になるようにプログラムしてきているので、+1します。
6行目 同様に盤面内での横の位置を「intH」に代入しています。
7行目 checkBreakSubをintVとintHを引数として呼び出しています。
checkBreakSubプロシージャの内容
1行目 Private Function checkBreakSub(intV As Integer, intH As Integer) As Boolean
2行目 Dim lngCurrentColor As Long
3行目 Dim i As Integer
4行目 Dim j As Integer
5行目
6行目 lngCurrentColor = arrPlayField(intV, intH).lngBubbleColor
7行目
8行目 i = intV - 1
9行目 j = intH
10行目 If i >= LBound(arrPlayField, 1) Then
11行目 If arrPlayField(i, j).lngBubbleColor = lngCurrentColor Then
12行目 Call changeBackColor(lngCurrentColor, intV, intH)
13行目 End If
14行目 End If
15行目
16行目 i = intV
17行目 j = intH - 1
18行目 If j >= LBound(arrPlayField, 2) Then
19行目 If arrPlayField(i, j).lngBubbleColor = lngCurrentColor Then
20行目 Call changeBackColor(lngCurrentColor, intV, intH)
21行目 End If
22行目 End If
23行目
24行目 i = intV + 1
25行目 j = intH
26行目 If i <= UBound(arrPlayField, 1) Then
27行目 If arrPlayField(i, j).lngBubbleColor = lngCurrentColor Then
28行目 Call changeBackColor(lngCurrentColor, intV, intH)
29行目 End If
30行目 End If
31行目
32行目 i = intV
33行目 j = intH + 1
34行目 If j <= UBound(arrPlayField, 1) Then
35行目 If arrPlayField(i, j).lngBubbleColor = lngCurrentColor Then
36行目 Call changeBackColor(lngCurrentColor, intV, intH)
37行目 End If
38行目 End If
39行目 End Function
1行目 Functionプロシージャの宣言
6行目 選択されたセルのバブルの色の値を「lngCurrentColor」に代入しています。
8行目~9行目 選択したセルの縦(intV)から1引いた数をi に代入
選択したセルの横(intH)をj に代入。つまり(i, j)は選択したセルの一つ上のセルを表します。
10行目 LBound()関数は配列の最小値を求めます。第二引数の1は次元を表します。
つまり10行目の意味はi が選択したセル一つ上のセルの縦が盤面の一番上の行以内であれば、となります。
11行目 選択されたセルのバブルの色が一つ上のセルのバブルの色と同じならば、という意味です。
12行目 引数lngCurrentColor,intV,intHでchangeBackColorプロシージャを呼び出しています。
16行目~22行目
8行目~14行目までとほぼ同じです。
横「intH」から1を引いて一つ左のセルを見ています。
Lbound()関数の第二引数は2で二次元目をさします。
つまり盤面のj が一番左の列以内であれば、となります。
24行目~30行目
縦「intV」に1を足して一つ下のセルを見ています。
UBound()関数はLBound()とは逆に最大値を求めます。
つまり盤面のi が一番下の行以内であれば、となります。
32行目~39行目
横「intH」に1を足して一つ右のセルを見ています。
このcheckBreakSubプロシージャの役割は?
選択したセルの上下左右に同じ色のバブルがあるかどうかを判定しています。
あればchangeBackColorを呼び出す、なければそのまま終了です。
次はchangeBackColorプロシージャの説明です。
うーん、ずいぶん長くなってますが、、、実際のプログラムです。
今回の最重要点である再帰呼び出しが使われているのでしっかりと見てみて下さい。
1行目 Private Function changeBackColor(lngCurrentColor As Long, intI As Integer, intJ As Integer)
2行目 Dim i As Integer
3行目 Dim j As Integer
4行目
5行目 arrPlayField(intI, intJ).lngBackColor = lng選択背景色
6行目 rng盤面(intI, intJ).Interior.Color = lng選択背景色
7行目
8行目 i = intI - 1
9行目 j = intJ
10行目 If i >= LBound(arrPlayField, 1) Then
11行目 If arrPlayField(i, j).lngBackColor <> lng選択背景色 Then
12行目 If arrPlayField(i, j).lngBubbleColor = lngCurrentColor Then
13行目 Call changeBackColor(lngCurrentColor, i, j)
14行目 End If
15行目 End If
16行目 End If
17行目
18行目 i = intI
19行目 j = intJ - 1
20行目 If j >= LBound(arrPlayField, 2) Then
21行目 If arrPlayField(i, j).lngBackColor <> lng選択背景色 Then
22行目 If arrPlayField(i, j).lngBubbleColor = lngCurrentColor Then
23行目 Call changeBackColor(lngCurrentColor, i, j)
24行目 End If
25行目 End If
26行目 End If
27行目
28行目 i = intI + 1
29行目 j = intJ
30行目 If i <= UBound(arrPlayField, 1) Then
31行目 If arrPlayField(i, j).lngBackColor <> lng選択背景色 Then
32行目 If arrPlayField(i, j).lngBubbleColor = lngCurrentColor Then
33行目 Call changeBackColor(lngCurrentColor, i, j)
34行目 End If
35行目 End If
36行目 End If
37行目
38行目 i = intI
39行目 j = intJ + 1
40行目 If j <= UBound(arrPlayField, 2) Then
41行目 If arrPlayField(i, j).lngBackColor <> lng選択背景色 Then
42行目 If arrPlayField(i, j).lngBubbleColor = lngCurrentColor Then
43行目 Call changeBackColor(lngCurrentColor, i, j)
44行目 End If
45行目 End If
46行目 End If
47行目 End Function
1行目 Functionプロシージャの宣言です。
2行目~3行目 このプロシージャで使用する変数の宣言です。
5行目 「arrPlayField(intI, intJ).lngBackColor」に選択時の背景色を代入しています。
6行目 選択したセルの背景色を選択背景色にしています。
8行目~10行目
checkBreakSubプロシージャの8行目から10行目の説明参照
11行目 選択したセルの背景色と一つ上の背景色が同じならば、If文以下を実行する
12行目 選択したセルのバブルの色と一つ上のバブルの色が同じならは、If文以下を実行する
13行目 changeBackColor、引数(lngCurrentColor,i,j)を呼び出す。
あれれ??確か今はchangeBackColorプロシージャの中のはず!!そうです。これが再帰呼び出しです。
プロシージャの中でそのプロシージャ自身を呼び出すことができます。
今回のように同じような処理が何度も続く場合は非常に便利ですが、処理が複雑になるので使わない方がいいこともあります。
13行目の場合だと選択したセルと一つ上のセルの背景色が異なりバブルの色の値が同じならば
処理がchangeBackColorプロシージャの最初に戻ります。
5行目で一つ上のセルの色の値を選択背景色にし6行目でセルの選択背景色を変更します。
18行目~26行目は左を28行目~36行目は下を38行目~46行目は右をそれぞれ見に行き
再帰処理が呼び出される条件を満たしていれば先頭にもどり5行目から6行目でセルの背景を変更します。
どうでしょう?少し長くなりましたが理解できたでしょうか?
わからなければバブルの色を全部同じ色や二色位にして、デバッグをしながら見てみると分かりやすいでしょう。
次回は、配列を使っていないバージョンのソースとなぜ配列を使うのかを簡単に説明します。
<< 第35回目 「エクセル de バブルブレーカー(Excel de Bubble Breaker)その7」 | | 第37回目 「エクセル de バブルブレーカー(Excel de Bubble Breaker)その9」 >>
>> HOME >> コラム >> 第36回目 「エクセル de バブルブレーカー(Excel de Bubble Breaker)その8」

コラムの全インデックス
アーカイブ