VBAサンプル集
Excel将棋:駒クラスの作成(№3)

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

Excel将棋:駒クラスの作成(№3)


VBA マクロ Excel将棋

Excelで将棋を作ってみましょう。
人vs人で動かしてゲームとして成立するところまでが当面の目標です。


今回は、駒クラスの作成になります。
駒クラスに必要な部品クラスとして、位置クラスと移動クラスを先に作成してから駒クラスの作成に進みます。

駒クラスは、エクセルのセルのような基本の存在になります。
作成するクラス全体の設計は、№2. Excel将棋:クラスの設計、こちらを参照してください。
・作成するクラスの役割と作成順 ・作成するクラスのメンバー一覧 ・駒の移動の定義 ・Excel将棋の目次

※クラス名、プロシージャー名、変数名に日本語を使用しています。
日本語を適宜使う事は、
VBAを読むときの手助けとしては、コメントをダラダラと書くより、はるかに助けになると思います。
仕事で使うVBAでは、あまり日本語は使用しないのですが、
今回はVBAの勉強材料としてのゲーム作成という事で日本語を使っていきます。

位置クラス

位置クラスの設計

種別 名称 説明
変数 1~9
変数 1~9

将棋では筋、段と言い、筋は右から1,2,…となります。
しかし、ここでは配列の位置としての行・列の数値で管理します。

位置クラスのVBA

クラス名称:cls位置

Option Explicit

Public 行 As Integer
Public 列 As Integer

デフォルトインスタンスに変更

後に、位置クラスをデフォルトインスタンスに変更
・デフォルトインスタンスに変更する理由と方法 ・位置クラスのインポート用ソース ・cls位置とg位置の使い方の違い ・位置クラス変更に伴う駒クラスの変更 ・Excel将棋の目次

これにともないクラスの名前も、g位置に変更しました。

移動クラス

移動クラスの設計

種別 名称 説明
変数 1~9
変数 1~9
変数 回数 1~8

将棋では筋、段と言い、筋は右から1,2,…となります。
しかし、ここでは配列の位置としての行・列の数値で管理します。

移動クラスのVBA

クラス名称:cls移動

Option Explicit

Public 行 As Integer
Public 列 As Integer
Public 回数 As Integer

駒クラス

駒クラスの設計

種別 名称 説明
プロパティ 正式名称 飛車、角行、金将、銀将、桂馬、香車、歩兵
プロパティ 表示名称 飛、角、金、銀、桂、香、歩
プロパティ 成駒名称 龍、馬、金、成銀、成桂、成香、と
プロパティ 表示順 駒台の表示順
プロパティ 先手 先手True、後手False
プロパティ 成り 先りTrue、未成りFalse
プロパティ 駒位置 縦横(行列)で取得・設定
プロパティ 駒移動 別表参照
プロパティ 成駒移動 別表参照
メソッド 駒作成 駒の正式名称を受け取って、その駒特有の情報を設定する
メソッド 駒位置設定 駒位置プロパティの設定を行・列で行う
メソッド 移動可能位置 駒が移動できる位置をcls位置(行、列)のCollectionで返す

駒クラスのVBA

クラス名称:cls駒

Option Explicit

Private p正式名称 As String
Private p表示名称 As String
Private p成駒名称 As String
Private p表示順 As Integer
Private p先手 As Boolean
Private p成り As Boolean
Private p駒位置 As cls位置
Private p駒移動() As cls移動
Private p成駒移動() As cls移動

'**********************************************************************
' 駒の名称や動きの定義
'**********************************************************************
                    '正式名称,表示名称,成駒名称,表示順
Private Const cns王将定義  As String = "王将,玉, ,0"
Private Const cns飛車定義  As String = "飛車,飛,龍,1"
Private Const cns角行定義  As String = "角行,角, ,2"
Private Const cns金将定義  As String = "金将,金, ,3"
Private Const cns銀将定義  As String = "銀将,銀,全,4"
Private Const cns桂馬定義  As String = "桂馬,桂,圭,5"
Private Const cns香車定義  As String = "香車,香,杏,6"
Private Const cns歩兵定義  As String = "歩兵,歩,と,7"
                    '行,列,回数
Private Const cns王将移動  As String = "-1,-1, 1;" & _
                    "-1, 0, 1;" & _
                    "-1, 1, 1;" & _
                    " 0,-1, 1;" & _
                    " 0, 1, 1;" & _
                    " 1,-1, 1;" & _
                    " 1, 0, 1;" & _
                    " 1, 1, 1;"
Private Const cns飛車移動  As String = "-1, 0, 8;" & _
                    " 1, 0, 8;" & _
                    " 0,-1, 8;" & _
                    " 0, 1, 8;"
Private Const cns龍王移動  As String = "-1, 0, 8;" & _
                    " 1, 0, 8;" & _
                    " 0,-1, 8;" & _
                    " 0, 1, 8;" & _
                    "-1,-1, 1;" & _
                    "-1, 1, 1;" & _
                    " 1,-1, 1;" & _
                    " 1, 1, 1;"
Private Const cns角行移動  As String = "-1,-1, 8;" & _
                    "-1, 1, 8;" & _
                    " 1,-1, 8;" & _
                    " 1, 1, 8;"
Private Const cns龍馬移動  As String = "-1,-1, 8;" & _
                    "-1, 1, 8;" & _
                    " 1,-1, 8;" & _
                    " 1, 1, 8;" & _
                    "-1,-1, 1;" & _
                    "-1, 1, 1;" & _
                    " 1,-1, 1;" & _
                    " 1, 1, 1;"
Private Const cns金将移動  As String = "-1,-1, 1;" & _
                    "-1, 0, 1;" & _
                    "-1, 1, 1;" & _
                    " 0,-1, 1;" & _
                    " 0, 1, 1;" & _
                    " 1, 0, 1;"
Private Const cns銀将移動  As String = "-1,-1, 1;" & _
                    "-1, 0, 1;" & _
                    "-1, 1, 1;" & _
                    " 1,-1, 1;" & _
                    " 1, 1, 1;"
Private Const cns桂馬移動  As String = "-2,-1, 1;" & _
                    "-2, 1, 1;"
Private Const cns香車移動  As String = "-1, 0, 8;"
Private Const cns歩兵移動  As String = "-1, 0, 1;"
              
'**********************************************************************
' 公開プロパティ
'**********************************************************************

Public Property Let 正式名称(ByVal Value As String)
  p正式名称 = Value
End Property
Public Property Get 正式名称() As String
  正式名称 = p正式名称
End Property

Public Property Let 表示名称(ByVal Value As String)
  p表示名称 = Value
End Property
Public Property Get 表示名称() As String
  表示名称 = IIf(Me.成り, p成駒名称, p表示名称)
End Property

Public Property Let 成駒名称(ByVal Value As String)
  p成駒名称 = Value
End Property
Public Property Get 成駒名称() As String
  成駒名称 = p成駒名称
End Property

Public Property Let 表示順(ByVal Value As String)
  p表示順 = Value
End Property
Public Property Get 表示順() As String
  表示順 = p表示順
End Property

Public Property Let 駒移動(ByRef arg移動() As cls移動)
  p駒移動 = arg移動
End Property
Public Property Get 駒移動() As cls移動()
  駒移動 = p駒移動
End Property

Public Property Let 成駒移動(ByRef arg移動() As cls移動)
  p成駒移動 = arg移動
End Property
Public Property Get 成駒移動() As cls移動()
  成駒移動 = p成駒移動
End Property

Public Property Let 先手(ByVal Value As Boolean)
  p先手 = Value
End Property
Public Property Get 先手() As Boolean
  先手 = p先手
End Property

Public Property Let 成り(ByVal Value As Boolean)
  p成り = Value
End Property
Public Property Get 成り() As Boolean
  成り = p成り
End Property

Public Property Set 駒位置(ByVal arg駒位置 As cls位置)
  Set p駒位置 = arg駒位置
End Property
Public Property Get 駒位置() As cls位置
  Set 駒位置 = p駒位置
End Property

'**********************************************************************
' 公開メソッド
'**********************************************************************

'駒の正式名称を受け取って、その駒特有の情報を設定する
Public Function 駒作成(ByVal arg名称 As String, _
            ByVal arg先手 As Boolean, _
            Optional ByVal arg行 As Integer = 0, _
            Optional ByVal arg列 As Integer = 0) As cls駒
  Dim tmp定義 As String
  Dim tmp移動 As String, tmp成移動 As String
  Select Case arg名称
    Case "王将", "玉将", "王", "玉"
      tmp定義 = cns王将定義
      tmp移動 = cns王将移動
      tmp成移動 = "" '成れない
    Case "飛車", "飛"
      tmp定義 = cns飛車定義
      tmp移動 = cns飛車移動
      tmp成移動 = cns龍王移動
    Case "角行", "角"
      tmp定義 = cns角行定義
      tmp移動 = cns角行移動
      tmp成移動 = cns龍馬移動
    Case "金将", "金"
      tmp定義 = cns金将定義
      tmp移動 = cns金将移動
      tmp成移動 = "" '成れない
    Case "銀将", "銀"
      tmp定義 = cns銀将定義
      tmp移動 = cns銀将移動
      tmp成移動 = cns金将移動
    Case "桂馬", "桂"
      tmp定義 = cns桂馬定義
      tmp移動 = cns桂馬移動
      tmp成移動 = cns金将移動
    Case "香車", "香"
      tmp定義 = cns香車定義
      tmp移動 = cns香車移動
      tmp成移動 = cns金将移動
    Case "歩兵", "歩"
      tmp定義 = cns歩兵定義
      tmp移動 = cns歩兵移動
      tmp成移動 = cns金将移動
    Case Else
      Err.Raise 9999 '形式的に記述
  End Select
  
  Dim sSplit() As String
  sSplit = Split(tmp定義, ",")
  Me.正式名称 = sSplit(0)
  Me.表示名称 = sSplit(1)
  Me.成駒名称 = sSplit(2)
  Me.表示順 = sSplit(3)
  Me.駒移動 = 駒移動設定(tmp移動)
  Me.成駒移動 = 駒移動設定(tmp成移動)
  Me.先手 = arg先手
  Call Me.駒位置設定(arg行, arg列)
  
  Set 駒作成 = Me
End Function

'駒位置プロパティの設定を行・列で行う
Public Sub 駒位置設定(ByVal arg行 As Integer, _
           ByVal arg列 As Integer)
  Dim obj位置 As New cls位置
  obj位置.行 = arg行
  obj位置.列 = arg列
  Set Me.駒位置 = obj位置
End Sub

'駒が移動できる位置をcls位置(行、列)のCollectionで返す
Public Function 駒移動可能位置(ary盤面) As Collection
  Dim col位置 As New Collection
  Dim tmp移動 As Variant 'For Eachで使用する都合でVariant
  Dim tmp位置 As cls位置
  Dim i As Long
  
  For Each tmp移動 In IIf(Me.成り, Me.成駒移動, Me.駒移動)
    For i = 1 To tmp移動.回数
      Set tmp位置 = New cls位置
      '先手後手で進む方向を反転させる
      tmp位置.行 = Me.駒位置.行 + (tmp移動.行 * i * IIf(Me.先手, 1, -1))
      tmp位置.列 = Me.駒位置.列 + (tmp移動.列 * i * IIf(Me.先手, 1, -1))
      '盤外に出たら内側のForのみ抜ける
      If tmp位置.行 < LBound(ary盤面, 1) Or _
        tmp位置.行 > UBound(ary盤面, 1) Or _
        tmp位置.列 < LBound(ary盤面, 2) Or _
        tmp位置.列 > UBound(ary盤面, 2) Then
        Exit For
      End If
      If ary盤面(tmp位置.行, tmp位置.列) Is Nothing Then
        '駒が無いので駒を置ける
        col位置.Add tmp位置
      Else
        '相手の駒なら取れる、自分の駒ならそれ以上進めない
        If ary盤面(tmp位置.行, tmp位置.列).先手 <> Me.先手 Then
          col位置.Add tmp位置
        End If
        Exit For
      End If
    Next
  Next
  Set 駒移動可能位置 = col位置
End Function

'**********************************************************************
' 非公開メソッド
'**********************************************************************

'駒の動きを定義したConstより配列を作成する
Private Function 駒移動設定(ByVal arg動き As String) As cls移動()
  Dim ary移動() As cls移動
  Dim tmp移動 As cls移動
  Dim sSplit1() As String, sSplit2() As String
  Dim i As Long, j As Long
  
  '行,列,回数;行,列,回数;・・・; 最後は;で終わる前提
  sSplit1 = Split(arg動き, ";")
  If UBound(sSplit1) < 0 Then Exit Function '成らない駒
  ReDim ary移動(LBound(sSplit1) To UBound(sSplit1) - 1)
  For i = LBound(sSplit1) To UBound(sSplit1) - 1
    sSplit2 = Split(sSplit1(i), ",")
    Set tmp移動 = New cls移動
    tmp移動.行 = sSplit2(LBound(sSplit2) + 0)
    tmp移動.列 = sSplit2(LBound(sSplit2) + 1)
    tmp移動.回数 = sSplit2(LBound(sSplit2) + 2)
    Set ary移動(i) = tmp移動
  Next
  
  駒移動設定 = ary移動
End Function

駒クラスVBAの解説

駒の定義情報はクラス外に出したい気もしますが、他に依存せずこのクラスだけで完結させておきたいのでここに記載しました。

ほとんどのプロパティは、変数をPublicにするだけで用が足りてしまいますが、やはり拡張性を考慮して面倒でもプロパティを作成しておきました。
例えば「表示名称」は、成りの状態で取得を切り替えていますが、これは一旦VBAを書き終えてから変更したものです。
また、プロパティにしておけばブレークポイントも設定できるので、より細かいデバッグも可能になります。
ウォッチ ウィンドウで変数変化を捉えることもできますが、、、)
・ウォッチ ウィンドウの表示 ・ウォッチ ウィンドウとは ・「ウォッチ式の追加」の操作手順 ・ウォッチ式の追加 ・ウォッチ ウィンドウの制限と注意 ・ウォッチ ウィンドウの最後に

当初VBA作成時にプロパティ作成が面倒な場合は変数をPublicにしておいても良いでしょう。
作成が進んでいく過程で必要に応じてプロパティに変更していっても構いません。

以下では、メソッドの注意点のみ記載します。

駒作成
駒の名称や動きの定義から駒オブジェクトを作成しています。
VBA自体は名称で分岐しているだけの単純なものですが、
Functionとして自身のオブジェクトを戻している点だけ注意してください。
これにより、

Dim obj駒 As New cls駒
Call obj駒.駒作成(駒名, 先手, 行, 列)
Set ary(行, 列) = obj駒

Dim obj駒 As New cls駒
Set ary(行, 列) = obj駒.駒作成(駒名, 先手, 行, 列)

この後者の書き方ができるようにしています。

駒移動可能位置
飛車であれば、
-1,0,8
これは、現在位置から、
Offset(-1, 0)
これを8回繰り返す指定になります。
この繰り返しの中で、
・盤の外(インデックス<1 Or インデックス>9)になったら終了
・駒が無ければ移動可能
・相手の駒が出てきたら、その位置も移動できるが、そこで繰り返し終了
・自分の駒が出てきたら、その手前で終了

使用しているVBAの参考ページ

第58回.コレクションとは(Collection)|VBA入門
・コレクションの中から単一オブジェクトを指定する場合 ・セルであるRangeオブジェクトのコレクションは? ・コレクションの要素数 ・Collectionオブジェクト
第59回.コレクション処理(For Each)|VBA入門
・For Each の構文 ・Exit For ・For Each の使用例 ・RangeオブジェクトのFor Each ・For Each サイト内の参考ページ
第112回.動的配列(ReDim)|VBA入門
・ReDimステートメント ・要素数の変更について ・配列について
第113回.配列に関連する関数|VBA入門
・LBound関数とUBound 関数 ・Array関数 ・IsArray 関数 ・Join関数 ・Filter関数 ・Eraseステートメント
第115回.Split関数|VBA入門
・Split関数 ・区切り文字が文字列式内に存在しない場合 ・空文字("")をSplitした場合 ・Split関数の使用例
IIf関数|VBAtyr4
・IIf関数 ・IIf関数の注意点 ・IIf関数の使用例
第140回.Property {Get|Let|Set} ステートメント|VBA入門
・そもそもプロパティとは ・VBAでプロパティを作成するステートメント ・Property {Get|Let|Set} ステートメントの構文 ・Propertyプロシージャの使用例 ・Propertyプロシージャの実践例
VBAクラス入門
VBAの学習を続けていくと、いずれ必ずクラスとかオブジェクト指向といった言葉に出くわします。VBAクラスについて、基礎から実践応用まで解説していきます。VBEの「挿入」の一番下にある「クラスモジュール」については、存在は知っていても使う機会が無かったかもしれません。

Excel将棋の目次

№1. Excel将棋:マクロVBAの学習用
・Excel将棋の要件定義 ・Excel将棋のシート作成 ・Excel将棋の目次
№2. Excel将棋:クラスの設計
・作成するクラスの役割と作成順 ・作成するクラスのメンバー一覧 ・駒の移動の定義 ・Excel将棋の目次
№3. Excel将棋:駒クラスの作成
・位置クラス ・移動クラス ・駒クラス ・駒クラスVBAの解説 ・使用しているVBAの参考ページ ・Excel将棋の目次
№4. Excel将棋:駒クラスの単体テスト
・駒クラスのテスト内容 ・駒クラスのテストVBAコード ・駒クラスのテストVBAの結果 ・Excel将棋の目次
№5. Excel将棋:駒台クラスの作成&単体テスト
・駒クラス ・駒台クラスVBAの解説 ・駒台クラスのテストVBAコード ・駒クラスのテストVBAの結果 ・Excel将棋の目次
№6. Excel将棋:位置クラスをデフォルトインスタンスに変更
・デフォルトインスタンスに変更する理由と方法 ・位置クラスのインポート用ソース ・cls位置とg位置の使い方の違い ・位置クラス変更に伴う駒クラスの変更 ・Excel将棋の目次
№7. Excel将棋:将棋盤クラスの作成&単体テスト
・将棋盤クラス ・将棋盤クラスVBAの解説 ・将棋盤クラスのテストVBAコード ・将棋盤クラスのテストVBAの結果 ・Excel将棋の目次
№8. Excel将棋:将棋進行クラスの作成
・将棋進行クラス ・将棋進行クラスVBAの解説 ・将棋進行クラスの起動方法 ・将棋盤クラスのテストVBAの結果 ・Excel将棋の目次
№9. Excel将棋:駒を動かす
・駒クラスにプロパティ追加 ・将棋進行クラスの変更点 ・将棋進行クラスのVBA ・Excel将棋の実行動作 ・Excel将棋の目次
№10. Excel将棋:相手の駒を取る、持ち駒を打つ
・主な変更追加箇所 ・全体の構成 ・Excel将棋の動作 ・Excel将棋の全VBAコード ・Excel将棋の目次
№11. Excel将棋:駒を成る
・主な変更追加箇所 ・Excel将棋の動作 ・変更したクラスのVBA ・Excel将棋の目次
№12. Excel将棋:棋譜をユーザーフォームに表示する
・棋譜について ・主な変更内容 ・ユーザーフォームの作成 ・Excel将棋の動作 ・変更したクラスのVBA ・Excel将棋の目次
№13. Excel将棋:棋譜選択でその時点の盤面に戻す
・Excel将棋の動作 ・全体構成図 ・全プロシージャー・プロパティの一覧 ・クリックで着手した時の主なプロシージャーの流れ ・Excel将棋のダウンロード ・Excel将棋の目次
№14. Excel将棋:棋譜ファイルの出力と読込自動再生
・Excel将棋の動作 ・VBAの修正箇所について ・Excel将棋のダウンロード ・棋譜KIFファイルのサンプル ・Excel将棋の目次
№15. Excel将棋:反則(禁じ手)判定
・反則(禁じ手) ・Excel将棋の動作 ・各クラスの共通で持つプロパティを整理 ・VBAの修正箇所について ・Excel将棋のダウンロード ・Excel将棋の目次
№16. Excel将棋:終局(詰み)判定と打ち歩詰め
・反則(禁じ手) ・Excel将棋の動作 ・VBAの追加・修正箇所について ・Excel将棋のダウンロード ・Excel将棋の目次
№17. Excel将棋:千日手と連続王手の千日手
・反則(禁じ手) ・Excel将棋の動作 ・VBAの修正箇所について ・Excel将棋のダウンロード ・Excel将棋の目次
№18 Excel将棋:ひとまず完成、これまでとこれから
・Excel将棋のこれから ・Excel将棋の目次 ・Excel将棋のダウンロード ・当初のクラス設計 ・作成するクラスのメンバー一覧 ・全体構成図 ・全プロシージャー・プロパティの一覧 ・全VBAコード
№19 Excel将棋:棋譜ファイルから対局一覧作成
・対局一覧のシート ・Excel将棋の動作 ・全体構成図 ・Excel将棋のダウンロード ・新規追加したVBAコード ・Excel将棋の目次



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

抜けている数値を探せ|エクセル雑感(2022-07-01)
.Net FrameworkのSystem.Collectionsを利用|VBA技術解説(2022-06-29)
迷路ネコが影分身の術を体得したら…|エクセル雑感(2022-06-27)
迷路にネコが挑戦したら、どうなるかな…|エクセル雑感(2022-06-26)
サロゲートペアに対応した自作関数(Len,Left,Mid,Right)|エクセル雑感(2022-06-24)
「マクロの登録」で登録できないプロシージャーは?|エクセル雑感(2022-06-23)
オブジェクトのByRef、ByVal、Variant|エクセル雑感(2022-06-22)
コメントから特定形式の年月を取り出す|エクセル雑感(2022-06-19)
4,9を使わない連番作成|エクセル雑感(2022-06-17)
連番を折り返して出力|エクセル雑感(2022-06-16)


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

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.繰り返し処理(For Next)|VBA入門
5.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
6.Excelショートカットキー一覧|Excelリファレンス
7.マクロって何?VBAって何?|VBA入門
8.並べ替え(Sort)|VBA入門
9.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
10.エクセルVBAでのシート指定方法|VBA技術解説




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


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



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