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

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

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


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


いよいよ今回は、黒石白石を交互に打てるようにします。
もちろん、相手の石を挟んでいる場所は、自分の石に取り替えます。
さて、いよいよゲームらしくなっていきます。

追加する機能は、
・ダブルクリックされた位置に手番の石を置く。
 (もちろん、置ける場所限定です。)
・相手の石を挟んでいたら、その相手の石を手番の石に取り替える。
・手番を交代します。
 (黒→白→黒→白・・・))


既に前回までに、
ダブルクリックされた位置に石が置けるかどうかの判定と、石を置くプロシージャーが完成しています。
これらを上手く利用します。
ほんの少しだけの変更で機能を実現します。


シートモジュール
前回までは、
ダブルクリックのイベントプロシージャーでは、石を置けるかどうかのメッセージを表示していました。
このメッセージ表示を石を置く処理に変更します。
標準モジュールに、「次手着手」というSubプロシージャーを作りますので、
イベントプロシージャー内のでは、これをCallするように変更します。
出に作成した、Worksheet_BeforeDoubleClickを変更します。



Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
  Unprotect
  Set TarggetSheet = Sheet1
  Call 次手着手(Target)
  Cancel = True
  Protect
End Sub



標準モジュール
既に作成済の
is置ける全方向
is置ける1方向
この2つのプロシージャーを変更します。
石を置いたり、相手の石をひっくり返す機能を追加します。

Function is置ける全方向(ByVal Target As Range, _
            ByVal isTry As Boolean) As Boolean
  Dim i As Long
  Dim j As Long
  '既に石が置いてある場合は置けない
  If Target.Value <> "" Then
    is置ける全方向 = False
    Exit Function
  End If
  '8方向を順に判定
  For i = -1 To 1
    For j = -1 To 1
      If is置ける1方向(Target, i, j, isTry) Then
        is置ける全方向 = True
      End If
    Next
  Next
End Function

Function is置ける1方向(ByVal Target As Range, _
      ByVal i As Long, _
      ByVal j As Long, _
      ByVal isTry As Boolean) As Boolean
  Dim r As Long
  Dim c As Long
  Dim is置く石 As Boolean
  Dim is相手石 As Boolean
  Dim myRng As Range
  '石を置くセルの行列位置
  r = Target.Row
  c = Target.Column
  Set myRng = Nothing
  With TarggetSheet
    '空白or置く石と同じ石が出てくるまで判定
    Do
      r = r + i
      c = c + j
      '空白(石が置かれていない
      If .Cells(r, c) = "" Then
        Exit Do
      End If
      '自分の石が置かれている
      If .Cells(r, c).Font.Color = 置く石.Font.Color Then
        is置く石 = True
        Exit Do
      End If
      '相手の石が置かれている
      If .Cells(r, c).Font.Color <> 置く石.Font.Color Then
        is相手石 = True
        If myRng Is Nothing Then
          Set myRng = .Cells(r, c)
        Else
          Set myRng = Union(myRng, .Cells(r, c))
        End If
      End If
    Loop
  End With
  '自分の石が置かれていて終了した時、それまでに相手の石があるか
  If is置く石 = True And is相手石 = True Then
    is置ける1方向 = True
    If Not isTry Then
      Call 石を置く(Target, 置く石)
      Call 石を置く(myRng, 置く石)
    End If
  End If
End Function

赤太字の部分が追加箇所です。
isTry
これは、
石が置けるかどうかの判定だけしたい場合は、True
石を置いて相手の石をひっくり返す場合は、Flase
呼び出すときの引数の指定で、判定だけ・石を置く
両方の機能を持たせられるようにしています。

Unionメソッドは、複数のRangeを結合して一つのRangeにします。
UnionメソッドはApplicationのメソッドです。複数のセル範囲を集め、1つのRangeオブジェクとして参照することができます。つまり、Unionメソッドは複数のRangeオブジェクトを連結して1つのRangeオブジェクトにします。
これを使っている理由は、
相手の石が見つかる度に石を取り換えるのではなく、
最後にまとめて石を取り換えるようにするためです。
Target ・・・ 新たに石を置くセル
myRng ・・・ 相手の石のセル(複数セル)


新規プロシージャーとして、以下を追加します。



Sub 次手着手(ByVal Target As Range)
  Call 共通変数設定
  If is置ける全方向(Target, False) Then
    Call 手番交代
    Call 置ける場所表示
  End If
End Sub

Sub 手番交代()
  With TarggetSheet
    If 置く石.Font.Color = .Range("先番石").Font.Color Then
      Set 置く石 = .Range("後番石")
      Set 相手石 = .Range("先番石")
    Else
      Set 置く石 = .Range("先番石")
      Set 相手石 = .Range("後番石")
    End If
    置く石.Copy Destination:=.Range("手番石")
  End With
End Sub

次手着手
マクロ作成中では、マクロをリセットすることが度々あります。
最初に共通変数設定をCallしているのは、
この場合に、Public変数が消えているので、それを想定しての処理となります。
is置ける全方向
この中で、石が置ける場合は石を置いて、相手の石も取り替えていますので、
Trueで返ってきた場合は(石が置ける)、手番の交代と新たに石を置ける場所の表示をしています。

手番交代
先番(黒石)と後番(白石)を取り換えています。


結構少ない変更と追加で実現できています。
必要なプロシージャーを効率的に作っておくことで、少ない変更と追加で機能拡張かできるようになります。


今回で、石を置いて相手の石をひっくり返す処理が出来ました。
とりあえず、少しは遊べるようになりました。
ただし、黒白どちらも自分で置かなければなりまん。
人対PCの機能は、まだしばらく先になります。

実際にやってみると、あれれ、と思う事が多々あります。
石を打つ場所がない時に、パスが出来ないから先に進まない・・・
全部石が埋まっても、何も変化がない・・・
そもそも、どっちが勝っているのかもわからない・・・
次回は、これらの対策をした機能を追加していきます。


№7へ続きます。
VBAでオセロ(リバーシ)を作っていきながらVBAを学ぶ第7回です。前回までで、黒石白石を交互に打つことができるようになりましたが、まだまた不都合な点があります。石を打つ場所がない時に、パスが出来ないから先に進まない… 全部石が埋まっても、何も変化がない… そもそも、どっちが勝っているのかもわからない… つまり、

全体の目次
はじめに
ExcelマクロVBAでオセロ(リバーシ)を作っていきながら、マクロVBAを学んで行きましょう。目的は、マクロVBAの学習であり、思考を整理しVBAでプログラミングする学習です。従って、強いソフトを作ることが目的ではありませんので、最近流行のAIなんちゃら…なんていうのは考えるつもりはありません。
№1.シートの用意と標準モジュールの挿入
ExcelマクロVBAでオセロ(リバーシ)を作っていきながらマクロVBAを学ぶ第1回です。まずはシートを用意しなければなりません、このシートの作り方で、その後の手間が随分と変わってきますので、しっかりと作ります。とはいえ、まずは一般的な感じで作ってみます、今後必要に応じて追加・変更していきます。
№2.ブックを開いたときの処理と初期配置
ExcelマクロVBAでオセロ(リバーシ)を作っていきながらマクロVBAを学ぶ第2回です。前回でシートの準備と標準モジュールを挿入しましたので、今回からは、マクロVBAをどんどん書き足していきます。まずは、イベントプロシージャーを作っていきます。
№3.自分の石を置ける場所の判定の整理
ExcelマクロVBAでオセロ(リバーシ)を作っていきながらマクロVBAを学ぶ第3回です。いよいよ自分の石を置いて、相手の石をひっくり返す処理に進むのですが、その前に、そもそも自分の石を置ける場所はどこなのか…。クリックしたセルは、自分の石を置いて良いセルなのかの判定が必要です。
№4.自分の石を置ける場所の判定の実装
ExcelマクロVBAでオセロ(リバーシ)を作っていきながらマクロVBAを学ぶ第4回です。石を置ける場所の定義を、前回は文章で書きました、今回は、それをもとにマクロVBAのプログラミングをしていきます。考え方は決定しているので、後はVBAに翻訳(コーディング)していくだけです。
№5.シート機能を拡張して今後の準備
ExcelマクロVBAでオセロ(リバーシ)を作っていきながらマクロVBAを学ぶ第5回です。前回で石を置ける場所の判定が完成しましたので、これからは、ゲームとしての機能を一つずつ追加していきます。まずは、石を置ける場所の色を変更してわかりやすくしてみます。
№6.黒石白石を交互に打って相手の石をひっくり返す
ExcelマクロVBAでオセロ(リバーシ)を作っていきながらマクロVBAを学ぶ第6回です。いよいよ今回は、黒石白石を交互に打てるようにします。もちろん、相手の石を挟んでいる場所は、自分の石に取り替えます。
№7.パス確認、終局確認、石数取得
VBAでオセロ(リバーシ)を作っていきながらVBAを学ぶ第7回です。前回までで、黒石白石を交互に打つことができるようになりましたが、まだまた不都合な点があります。石を打つ場所がない時に、パスが出来ないから先に進まない… 全部石が埋まっても、何も変化がない… そもそも、どっちが勝っているのかもわからない… つまり、
№8.石を置ける場所の表示とアニメーション
ExcelマクロVBAでオセロ(リバーシ)を作っていきながらマクロVBAを学ぶ第8回です。前回までで大分ゲームらしくなってきました。そろそろ、PC対戦の機能を入れたいところですが、今回は、はPC対戦の機能を入れる前に、気になる細かい部分を変更しておきます。
№9.PC対戦の実装
ExcelマクロVBAでオセロ(リバーシ)を作っていきながらマクロVBAを学ぶ第9回です。前回までで人が打つのであれば不自由のない機能が実装できたと思います。さて、ここからはPC対戦の機能を入れていきます。
№10.置く場所に重みを付けて少しだけ強く
ExcelマクロVBAでオセロ(リバーシ)を作っていきながらマクロVBAを学ぶ第10回です。前回は、PCが自動で打つ機能を実装しました。強さはともかく、とにかくPCが勝手に売ってくれるようになりました。
№11.相手の応手を評価してさらに強く
VBAでオセロ(リバーシ)を作っていきながらVBAを学ぶ第11回です。前回の石を置く場所に重みを付けることで、超々初心者なら勝てるかもしれないというレベルにはなりました。ですが、ある程度オセロをやった事のある人なら、まあ負けることはないでしょう 今回は、自分の打つ場所ではなく、
№12.PC対PCの対戦で強さを確認
ExcelマクロVBAでオセロ(リバーシ)を作っていきながらマクロVBAを学ぶ第12回です。前回は、相手の応手を判定して、自分の置く場所を決められるようにしました。オセロソフトとしては、そこそこの強さになりました。
№13.パラメーターと重みを調整してさらに強く
ExcelマクロVBAでオセロ(リバーシ)を作っていきながらマクロVBAを学ぶ第12回です。前回は、PC1からPC5までの5段階の状態で、総当り対戦で強さを判定しましたが、PC5が最も強い事が確認出来ました。それでもPC5では、まだまだ、ある程度オセロをやった事のある人には勝てないレベルです。
№14.やはり「待った」が欲しい
ExcelマクロVBAでオセロ(リバーシ)を作っていきながらマクロVBAを学ぶ第14回です。前回で、6段階の強さのPCオセロが完成しました、一番強いPC6でも、まだまだそれほどの強さとは言えませんが、初心者の人なら苦戦するでしょうし、私も油断すれば負けてしまうくらいの強さにはなっています。
№15.棋譜で対局を再現
ExcelマクロVBAでオセロ(リバーシ)を作っていきながらマクロVBAを学ぶ第15回です。棋譜が扱えるようになり、「待った」の実装も出来ました。棋譜が扱えるようになったので、今回は、対局を再現できるようにします。
№16.これまでを振り返りつつ全体のまとめ
ExcelマクロVBAでオセロ(リバーシ)を作っていきながらマクロVBAを学ぶ第16回です。15回に渡って、オセロ作成をしてきました、マクロVBAコードはかなりの量になっています。今回は最終回として、これまでを振り返ってみます。


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




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

ユーザーに絶対に停止させたくない場合のVBA設定|VBA技術解説(4月1日)
CharactersプロパティとCharactersオブジェクト|VBA技術解説(3月31日)
指数近似/対数近似/累乗近似(掲載順位とCTR)|エクセル関数超技(3月31日)
練習問題32(連続数値部分を取り出し記号で連結)|VBA練習問題(3月24日)
連続数値部分を取り出し記号で連結|エクセル関数超技(3月24日)
数式バーの高さを数式の行数で自動設定|VBAサンプル集(3月21日)
LET関数(数式で変数を使う)|エクセル入門(3月21日)
スピルに対応したXSPLITユーザー定義関数(文字区切り)|VBAサンプル集(3月15日)
XMATCH関数(範囲から値を検索し一致する相対位置)|エクセル入門(3月14日)
XLOOKUP関数(範囲を検索し一致する対応項目を返す)|エクセル入門(3月14日)


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

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




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


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



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