第2回 DataGridViewコントロールでマインスイーパ連載:.NETグリッド・コントロール大研究(4/4 ページ)

» 2006年10月21日 00時00分 公開
[遠藤孝信デジタルアドバンテージ]
前のページへ 1|2|3|4       

■セルのクリック処理

 DGVコントロールではセルがクリックされると、そのセルが選択されフォーカスが設定されるが、Gridスイーパではセルがクリックされたら、そのセルを開く(実際には開いたように見せるために色を変更し、Valueプロパティを書き換える)処理が必要だ。

 そこで、セルがクリックされたときに発生するCellClickイベントをハンドリングする。CellClickイベント・ハンドラでは、メソッドのパラメータとしてDataGridViewCellEventArgsオブジェクトが渡されるので、そのColumnIndexプロパティとRowIndexプロパティにより、どの位置のセルがクリックされたかを知ることができる。つまり、クリックされたセル・オブジェクトは、

dgv(e.ColumnIndex, e.RowIndex)

により得ることができる。

 CellClickイベント・ハンドラは次のようになる。ここではクリックされたセルをtryCellメソッドに渡す。

Private Sub dgv_CellClick(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) Handles dgv.CellClick
  ' クリックされたセルをtryCellメソッドに渡す
  tryCell(dgv(e.ColumnIndex, e.RowIndex))
End Sub

DGVコントロールのCellClickイベント・ハンドラ

■キー入力の処理

 DGVコントロールではあらかじめ多くのキーをハンドリングしており*、例えばフォーカスのあるセルを移動するにはカーソル・キーやタブ・キーが使える。

 Gridスイーパでは、[F2]キーでゲームの再スタートを行い、[スペース]キーで現在フォーカスのあるセルを開くようにして、キーボードだけでもゲームができるようにしてみた。

 キーの入力に関しては、KeyDownイベントに対応すればよい。このイベント・ハンドラは次のようになる。e.KeyCodeがDGVコントロールに対して入力されたキーのコードとなる。

Private Sub dgv_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) Handles dgv.KeyDown
  ' [F2]キーで再スタート
  If e.KeyCode = Keys.F2 Then
    initGame()
  End If
  ' [スペース]キーで現在のセルを開く
  If e.KeyCode = Keys.Space Then
    tryCell(dgv.CurrentCell)
  End If
End Sub

DGVコントロールのKeyDownイベント・ハンドラ

 現在フォーカスのあるセルは、DGVコントロールのCurrentCellプロパティによって得られるので、[スペース]キーが入力された場合には、セルのクリック時と同様に、これをtryCellメソッドに渡す。

■セルのオープン

 tryCellメソッドでは、開こうとするセルの値が爆弾(MINE)であれば即ゲームオーバーだが、まだ開かれていないセル(UNOPEN)であれば、openCellメソッドを呼び出してそれを開く。

 これらの処理が終わった後、もしすでに開かれているセルの数(numCellOpened)が爆弾のないセルの数(sx * sy - numMine)と等しければ、爆弾撤去が完了だ。

Sub tryCell(ByVal cell As DataGridViewCell)
  ' ゲームが開始されていなければ何もしない
  If gameStarted = False Then
    Return
  End If

  If CInt(cell.Value) = MINE Then
    gameOver(False) ' 爆弾だったらゲームオーバー
  ElseIf CInt(cell.Value) = UNOPEN Then
    openCell(cell) ' 実際にセルを開く
    showRemain()
    ' 開いたセルと爆弾のないセルが同じ数なら撤去完了
    If numCellOpened = sx * sy - numMine Then
      gameOver(True)
    End If
  End If
End Sub

tryCellメソッド

■セルの実際のオープン

 クリックされたセルを実際に開いて数字(あるいは空文字)に書き換える処理はopenCellメソッドで行っている。マインスイーパでは単にクリックされたセルを開くだけでなく、セルに爆弾がなかったら連鎖的に周りのセルも開かなければならない場合があるので、このメソッドは少しだけ複雑だ。

 openCellメソッドではまず、メソッドのパラメータで指定されたセルに隣接するセル(最高8つ)をgetNeighborsメソッドにより取得する。そして爆弾のあるセルの数を数え、それをセルの値とし、drawNumberCellメソッドにより表示する。

Sub openCell(ByVal cell As DataGridViewCell)
  numCellOpened += 1
  Dim count As Integer = 0

  ' 周りの爆弾の数を数える
  For Each c As DataGridViewCell In getNeighbors(cell)
    If CInt(c.Value) = MINE Then
      count += 1
    End If
  Next

  ' 周りの爆弾の数を表示
  cell.Value = count
  drawNumberCell(cell)

  ' 周りのセルに爆弾がない場合、周りのセルも開く
  If count = 0 Then
    For Each c As DataGridViewCell In getNeighbors(cell)
      If CInt(c.Value) = UNOPEN Then
        openCell(c) ' 再帰呼び出し
      End If
    Next
  End If
End Sub

openCellメソッド

 隣接するセルに爆弾があればセルに数字を書いて処理は終わりだが、もし隣接するセルのいずれにも爆弾がなかったら、それらのセルを開き、さらにそのセルの周りにも爆弾がなかったらそれらを開き……という処理をそういうセルがなくなるまで繰り返さなくてはならない。

 処理は難しいがご覧のようにメソッドの再帰呼び出しを使えばコードは非常に単純に記述できる。隣接するまだ開いていない各セルに対して、さらにopenCellメソッドを呼び出すだけである。


 以上、今回はゲームを作りながらDGVコントロールの非連結モードについて解説してみた。DGVコントロールはデータ連結しなくても手軽に使えるようになっているので、これまで以上にさまざまな用途で活用できるのではないかと思う。

「連載:.NETグリッド・コントロール大研究」のインデックス

連載:.NETグリッド・コントロール大研究

前のページへ 1|2|3|4       

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。