ExcelマクロVBAサンプル集
オセロを作りながらマクロVBAを学ぼう№7

ExcelマクロVBAの実用サンプル、エクセルVBA集と解説
最終更新日:2017-12-06

オセロを作りながらマクロVBAを学ぼう№7


ExcelマクロVBAでオセロ(リバーシ)を作っていきながらマクロVBAを学ぶ第7回です。


前回までで、黒石白石を交互に打つことができるようになりましたが、まだまた不都合な点があります。

石を打つ場所がない時に、パスが出来ないから先に進まない・・・
全部石が埋まっても、何も変化がない・・・
そもそも、どっちが勝っているのかもわからない・・・


つまり、

・パス確認
・終局確認
・石数取得


今回は、これらの機能を追加していきます。
先に、石数を表示するようにシートを少し変更しておきます。

シートの変更
シート保護の解除をしてください。

マクロVBA参考画像

スクロールエリアを解除します。

マクロVBA参考画像

この「ScrollArea」の値を消去してください。

N2 : 黒石の数を表示するセル、フォントと罫線を設定してください。
N3 : 黒石の数を表示するセル、フォントと罫線を設定してください。
M4 : 「残り」と入力して、、フォントを設定してください。。
N4 : r4dgを設定してください。「=64-N2-N3」

マクロVBA参考画像



パス確認
パスとはどのような状態かを定義します。

手番の石(黒石or白石)がどこにも置けない状態
つまり、盤面の全てのセルで、
プロシージャー「is置ける全方向」の戻り値がFalseの状態

以下を標準モジュールに追加してください。



Sub パス確認()
  Dim myRng As Range
  Dim isPass As Boolean
  With TargetSheet
    isPass = True
    For Each myRng In .Range("盤面")
      If is置ける全方向(myRng, True) Then
        isPass = False
        Exit For
      End If
    Next
    If isPass = True Then
      If .Range("手番石").Font.Color = .Range("先番石").Font.Color Then
        MsgBox "●先手番「" & Sheet1.cmb1.Text & "」" & vbLf & vbLf & "パス"
      Else
        MsgBox "○後手番「" & Sheet1.cmb2.Text & "」" & vbLf & vbLf & "パス"
      End If
      Call 手番交代
      Call 置ける場所表示
      Call 終局確認
    End If
  End With
End Sub

For Each myRng In .Range("盤面")
・・・
Next
これで、盤面の全てのセルを処理するようにして、
一つでもTrueが戻されれば石が置けるということです。
つまり、一つもTrueが返されない場合は、石を置く場所が無いという事です。

isPass
石を置く場所が無くパスの状態を、True
石を置く場所がある状態を、Flase
として使っています。



終局確認
終局とはどういう状態なのかを定義します。

・64マス全てに石が置かれた状態
・黒石白石、どちらも置く場所がない状態

以下を標準モジュールに追加してください。

Sub 終局確認()
  Dim myRng As Range
  Dim isPass As Boolean
  With TargetSheet
    If WorksheetFunction.CountA(.Range("盤面")) = 64 Then
      Call 終局処理
      End
    End If
    isPass = True
    For Each myRng In .Range("盤面")
      If is置ける全方向(myRng, True) Then
        isPass = False
      End If
    Next
    If isPass = True Then
      isPass = True
      Set 置く石 = 相手石
      For Each myRng In .Range("盤面")
        If is置ける全方向(myRng, True) Then
          isPass = False
        End If
      Next
      If isPass = True Then
        Call 終局処理
        End
      End If
    End If
  End With
  Call 共通変数設定
End Sub

Sub 終局処理()
  With TargetSheet
    Select Case True
      Case .Range("先番石").Offset(, 2).Value > .Range("後番石").Offset(, 2).Value
        MsgBox "終局" & vbLf & vbLf & "●先手番「" & Sheet1.cmb1.Text & "」の勝ちです。"
      Case .Range("先番石").Offset(, 2).Value < .Range("後番石").Offset(, 2).Value
        MsgBox "終局" & vbLf & vbLf & "○後手番「" & Sheet1.cmb2.Text & "」の勝ちです。"
      Case Else
        MsgBox "終局" & vbLf & vbLf & "引き分けです。"
    End Select
    .Range("手番石").Clear
    .Range("手番石").Offset(, 1).ClearContents
  End With
End Sub

実際には、
「黒石白石、どちらも置く場所がない状態」というのは、
「64マス全てに石が置かれた状態」この状態も含んでいるので、
「黒石白石、どちらも置く場所がない状態」これだけの判定でもよいのですが、
形式的にも、全て打ち終わった場合の判定を入れておいた方が良いだろうと思って入れています。

全ての石の数の取得は、
WorksheetFunction.CountA
VBA関数以外に、Excelワークシート関数をマクロVBAで使うことが出来ます、ワークシート関数は、VBA関数よりはるかに多くの関数があるので、ぜひ活用したいところです。。ワークシート関数を使う事で、VBAコードを非常に簡潔に記述することが出来る場合が多いものです。
これを使っています。



    For Each myRng In .Range("盤面")
      If is置ける全方向(myRng, True) Then
        isPass = False
      End If
    Next

これで、盤面のどこにも医師が置けない状態を判定できますので、
黒石と白石の両方で検査すれば良いという事です。

終局処理
メッセージと手番石のクリア部分を別のプロシージャーにしてるのは、
2箇所で必要になっているので、
無駄のないように別プロシージャーにしています。
勝敗の判定は、石数取得で設定しているセル数値数値を使っています。
L2セルL3セルに名前定義をしているので、そこから2列右ということで、
Offsetプロパティを使って、右に2列移動して取得しています。
Offsetプロパティは指定されたセル範囲(Rangeオブジェクト)をオフセット(移動)しますオフセット(移動)したセル範囲を表すRangeオブジェクトを返します。Offsetとは「差し引きする」意味ですがOffsetプロパティで取得されるのは元のRange範囲を指定した行数・列数移動したRange範囲になります。


石数取得

石数の取得は、単純に黒石と白石のカウントをするだけです。

Sub 石数取得()
  Dim myRng As Range
  Dim cnt先番 As Long
  Dim cnt後番 As Long
  With TargetSheet
    For Each myRng In .Range("盤面")
      If myRng <> "" Then
        If myRng.Font.Color = .Range("先番石").Font.Color Then
          cnt先番 = cnt先番 + 1
        Else
          cnt後番 = cnt後番 + 1
        End If
      End If
    Next
    .Range("先番石").Offset(, 2) = cnt先番
    .Range("後番石").Offset(, 2) = cnt後番
  End With
End Sub

L2セルL3セルに名前定義をしているので、そこから2列右ということで、
Offsetプロパティを使って、右に2列移動したセルに設定しています。



大分ゲームらしくなってきました。
そろそろ、PC対戦の機能を入れたいところですが、
PC対戦となると、結構複雑になります。
そこで、次回はPC対戦の機能を入れる前に、
気になる細かい部分を変更しておきます。


№8へ続きます。

全体の目次


ここまでのサンプルファイルのダウンロード




同じテーマ「マクロVBAサンプル集」の記事

エクセルでファイル一覧を作成
アメブロの記事本文をVBAでバックアップする№6
数独(ナンプレ)を解くVBAに挑戦№5
数独(ナンプレ)を解くアルゴリズムの要点とパフォーマンスの検証№4
ナンバーリンク(パズル)を解くVBAに挑戦№8
ナンバーリンクを解くVBAのパフォーマンス改善№3
オセロを作りながらマクロVBAを学ぼう№9
他ブックへのリンクエラーを探し解除するマクロ(変更前)
Excelシートの複雑な計算式を解析するVBAの関数構文


新着記事NEW ・・・新着記事一覧を見る

Applicationを省略できるApplicationのメソッド・プロパティ一覧|VBA技術解説(7月22日)
コレクション(Collection)の並べ替え(Sort)に対応するクラス|VBA技術解説(7月20日)
CSVの読み込み方法(ジャグ配列)|VBAサンプル集(7月15日)
その他のExcel機能(グループ化、重複の削除、オートフィル等)|VBA入門(7月14日)
オートフィルタ退避回復クラスを複数シート対応させるVBAクラス|VBA技術解説(7月6日)
オートフィルタを退避回復するVBAクラス|VBA技術解説(7月6日)
IfステートメントとIIF関数とMax関数の速度比較|VBA技術解説(6月23日)
Withステートメントの実行速度と注意点|VBA技術解説(6月6日)
VBA+SeleniumBasicで検索順位チェッカー(改)|VBA技術解説(6月2日)
マクロでShift_JIS文字コードか判定する|VBA技術解説(6月1日)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
3.RangeとCellsの使い方|ExcelマクロVBA入門
4.変数とデータ型(Dim)|ExcelマクロVBA入門
5.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
6.繰り返し処理(For Next)|ExcelマクロVBA入門
7.マクロって何?VBAって何?|ExcelマクロVBA入門
8.ExcelマクロVBAの基礎を学習する方法|エクセルの神髄
9.ひらがな⇔カタカナの変換|エクセル基本操作
10.セルに文字を入れるとは(Range,Value)|VBA入門



  • >
  • >
  • >
  • オセロを作りながらマクロVBAを学ぼう№7

  • このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


    記述には細心の注意をしたつもりですが、
    間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
    なお、掲載のVBAコードは自己責任で使ってください。万一データ破損等の損害が発生しても責任は負いません。




    このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
    本文下部へ