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

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

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


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


棋譜が扱えるようになり、「待った」の実装も出来ました。
棋譜が扱えるようになったので、今回は、対局を再現できるようにします。
1手1手進められるように、1手1手戻せるようにします。


シートにボタンを追加
下図のように、ボタンを追加します。

マクロVBA画像

オブジェクト名は、
棋譜再現 : btn11
戻る : btn12
進む : btn13
としました。



ボタンクリックのイベントプロシージャー
以下をシートモジュールに追加します。



Private Sub btn11_Click()
  Unprotect
  StopMsg = False
  Set TargetSheet = Sheet1
  Call 棋譜再現
  Protect
End Sub

Private Sub btn12_Click()
  Unprotect
  StopMsg = False
  Set TargetSheet = Sheet1
  Call 棋譜戻る
  Protect
End Sub

Private Sub btn13_Click()
  Unprotect
  StopMsg = False
  Set TargetSheet = Sheet1
  Call 棋譜進む
  Protect
End Sub

イベントプロシージャー内での記述は少なくして、
処理の中核は、標準モジュールに記載します。
イベントプロシージャー内では、エラー時のデバッグ等で使い勝手が良くないので、
なるべく、標準モジュールに書いた方が効率がよいです。



棋譜から対局を再現
以下を、標準モジュールにに追加します。

Sub 棋譜再現()
  With TargetSheet
    If Not StopMsg Then
      If WorksheetFunction.CountA(.Range("盤面")) > 4 And .Range("手番石") <> "" Then
        If MsgBox("対局途中です。" & vbLf & vbLf & _
              "棋譜を再現してもよろしいですか?", _
              vbYesNo, "確認") = vbNo Then
          Exit Sub
        End If
      End If
    End If
    isPCvsPC = False
    .Range("先番石").Copy Destination:=.Range("手番石")
    .Range("手番石").Offset(, 1) = "の番です。"
    .Range("盤面").ClearContents
    Call 共通変数設定
    Call 石を置く(.Range("盤面").Cells(4, 5), 置く石)
    Call 石を置く(.Range("盤面").Cells(5, 4), 置く石)
    Call 石を置く(.Range("盤面").Cells(4, 4), 相手石)
    Call 石を置く(.Range("盤面").Cells(5, 5), 相手石)
    Worksheets("棋譜").Range("D1") = 1
  End With
End Sub

Sub 棋譜進む()
  Dim i As Long
  Dim j As Long
  Dim myRng As Range
  isPCvsPC = False
  With Worksheets("棋譜")
    If .Range("D1") = "" Then
      Exit Sub
    End If
    i = .Range("D1") + 1
    If .Cells(i, 1) = "" Then
      MsgBox "棋譜はここまでです。"
      Exit Sub
    End If
    If .Cells(i, 3) = "黒" Then
      Set 置く石 = TargetSheet.Range("先番石")
    Else
      Set 置く石 = TargetSheet.Range("後番石")
    End If
    Set myRng = 棋譜ToRange(.Cells(i, 2))
'    Call 石を置く(myRng, 置く石)
'    For j = 4 To .Cells(i, .Columns.Count).End(xlToLeft).Column
'      Set myRng = 棋譜ToRange(.Cells(i, j))
'      Call 石を置く(myRng, 置く石)
'    Next
    Call is置ける全方向(myRng, False)
    .Range("D1") = i
  End With
  Call 手番交代
End Sub

Sub 棋譜戻る()
  Dim i As Long
  Dim j As Long
  Dim myRng As Range
  isPCvsPC = False
  With Worksheets("棋譜")
    If .Range("D1") = "" Then
      Exit Sub
    End If
    i = .Range("D1")
    If i = 1 Then
      Exit Sub
    End If
    If .Cells(i, 3) = "黒" Then
      Set 置く石 = TargetSheet.Range("後番石")
    Else
      Set 置く石 = TargetSheet.Range("先番石")
    End If
    Set myRng = 棋譜ToRange(.Cells(i, 2))
    myRng = ""
    For j = 4 To .Cells(i, .Columns.Count).End(xlToLeft).Column
      Set myRng = 棋譜ToRange(.Cells(i, j))
      Call 石を置く(myRng, 置く石)
    Next
    .Range("D1") = i - 1
  End With
  Call 手番交代
End Sub

Function 棋譜ToRange(ByVal str As String) As Range
  Dim s1 As String
  Dim s2 As String
  Dim rng As Range
  Dim i As Long
  Dim j As Long
  Set rng = TargetSheet.Range("盤面").Offset(-1, -1).Resize(9, 9)
  s1 = Left(str, 1)
  s2 = Right(str, 1)
  For j = 2 To 9
    If rng.Cells(1, j) = s1 Then
      Exit For
    End If
  Next
  For i = 2 To 9
    If rng.Cells(i, 1) = s2 Then
      Exit For
    End If
  Next
  Set 棋譜ToRange = TargetSheet.Range("盤面").Cells(i - 1, j - 1)
End Function

棋譜再現
ここは、「対戦開始」とほぼ同様で、初期配置までを行っています。

棋譜進む
「進む」ボタンで1手進めます。
棋譜ToRangeで、棋譜の記号をセル(Range)に変換して、
そこに石を置いています。
棋譜シートの、"D1"セルに再現している手数位置を入れて、これでコントロールしています。


'    Call 石を置く(myRng, 置く石)
'    For j = 4 To .Cells(i, .Columns.Count).End(xlToLeft).Column
'      Set myRng = 棋譜ToRange(.Cells(i, j))
'      Call 石を置く(myRng, 置く石)
'    Next
    Call is置ける全方向(myRng, False)
この部分は、
Call is置ける全方向(myRng, False)
これは、通常の対戦時に石を置く時に使っているものをそのまま使っています。
これを使う事で、石を置けば相手の石をひっくり返してくれます。
コメントアウトしている部分は、
Call is置ける全方向(myRng, False)
これの代わりに、棋譜にあるとおりに石を置いて、相手の石をひっくり返すのも棋譜通りに行う場合です。
今回は、通常対戦とおりに、石を置いくことで相手の石もひっくり返しています。
オセロの棋譜がどこかにあったしたら、それを使う事を考慮すれば、
今回のように、棋譜に従って石を置いて、相手の石をひっくり返す法が良いだろうと考えました。

棋譜戻る
「待った」とほぼ動労の内容となります。
棋譜の現在行の内容で石を元に戻し、
棋譜の現在行("D1")を1行戻します。

棋譜ToRange
f5等の記号から、セル(Rangeオブジェクト)に変換しています。
f5
これを
f5に分割し、
盤面の上と左にある記号から検索して、セル位置(行と列)を取得しています。
取得した行と列を、Cellsに入れる事でRangeオブジェクトにしています。



今回で、オセロソフト作成としては完了となります。
強さはそこそこ、使い勝手もそこそこ
と言うところではないでしょうか。

次回は、本シリーズも長期シリーズとなりましたので、
最後のまとめを書いておきたいと思います。


№16へ続きます。
ExcelマクロVBAでオセロ(リバーシ)を作っていきながらマクロVBAを学ぶ第16回です。15回に渡って、オセロ作成をしてきました、マクロVBAコードはかなりの量になっています。今回は最終回として、これまでを振り返ってみます。

全体の目次

はじめに
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でのCSVの扱い方まとめ|VBAサンプル集(11月9日)
VBAにおける変数のメモリアドレスについて|VBA技術解説(11月8日)
空文字列の扱い方と処理速度について(""とvbNullString)|VBA技術解説(1月7日)
Errオブジェクトとユーザー定義エラー|VBA入門(11月5日)
シングルクォートの削除とコピー(PrefixCharacter)|VBA技術解説(11月4日)
ユーザー定義型の制限とクラスとの使い分け|VBA技術解説(11月3日)
クリップボードに2次元配列を作成してシートに貼り付ける|VBA技術解説(11月1日)
VBAクラスを使ったイベント作成(Event,RaiseEvent,WithEvents)|VBA技術解説(10月31日)
VBAクラスのAttributeについて(既定メンバーとFor Each)|VBA技術解説(10月19日)
VBAの用語について:ステートメントとは|VBA技術解説(10月16日)


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

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




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


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




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