VBAサンプル集
Excel将棋:マクロVBAの学習用(№1)

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

Excel将棋:マクロVBAの学習用(№1)


Excelで将棋を作ってみましょう。


今やコンピューター将棋はプロをしのぐ強さです。
しかし、Excelでそのようなソフトを作ろうと言うのではありません。
と言いますか、残念ながら私には作れません、、、

ExcelマクロVBAの学習素材として将棋を作ってみましょう。
とりあえずは、人vs人で動かしてゲームとして成立するところまでを目標とします。

VBAはクラスの作成が中心になっていくと思います。
VBAテクニックの紹介として、意図的に多彩な方法を使っていきます。
したがって、同じようなことを違う方法で実装する場合も出てくるかもしれません。
Excel将棋を作る目的はVBAの学習であり、これをお伝えするための記事として進めていきます。

少しずつVBAを作成しつつ記事を書いていくことになります。
したがって最終的にどのようなものになるかは、作りながら考えていきます。

本シリーズでは、VBAコードの解説は要点だけになります。
マクロVBAの基本事項は他のページで学習してください。
本シリーズの中では、適宜下記の該当する解説ページへのリンクを付けておくようにします。
ExcelマクロVBA入門
VBAはExcelの操作を自動化するマクロ機能で使われているプログラミング言語です。「VisualBasicApplications」の略になります。マクロVBA入門シリーズでは、始めはより詳しく丁寧に解説し、少しずつ難易度を上げることで無理なく学習を進められるようにしています。
Excelマクロ再入門
VBAを学習しようとして、本を読んでもWEBをみても、結局挫折してしまった方を対象に、VBA再入門と題してマクロVBAの基礎の学習を実践形式で進める連載を開始します。理屈は最低限にとどめ、とにかくマクロVBAが書けるようになることを目的とします。
VBAクラス入門
VBAの学習を続けていくと、いずれ必ずクラスとかオブジェクト指向といった言葉に出くわします。VBAクラスについて、基礎から実践応用まで解説していきます。VBEの「挿入」の一番下にある「クラスモジュール」については、存在は知っていても使う機会が無かったかもしれません。

初回の今回は、要件定義とシート作成までになります。
次回以降、クラスの設計から入り1つずつ実装していく予定です。


Excel将棋の要件定義

・駒の初期配置
「対局開始」で駒を初期配置する。
・1クリックで駒の選択、次のクリックで駒を移動
・手番側の駒をクリックで選択している駒を強調表示
・選択している駒の移動可能場所の強調表示
・再度同じ駒をクリックで解除
・移動先のクリックで駒を移動
・駒の移動先に相手の駒があれば取る
取った駒は駒台に移動
・敵陣(3段位内)に入ったら成るか成らないか選択
駒が成れる条件
・敵陣に入った場合
・敵陣内で動いた場合
・敵陣から外に出た場合
・反則(禁じ手)は着手不可とする
以下の反則(禁じ手)は着手自体が出来ないようにする。
・動けないところに駒を進める
・二手指し
・二歩
・王手放置
・身動きの取れない駒
・打ち歩詰め
・連続王手の千日手
※より下の方がより難しいと思われますが、実装順は適宜検討
・詰み判定で勝敗を表示
玉が詰んでいる、または「投了」ボタンで終局し、勝敗を表示
・先手後手それぞれの消費時間の表示
秒単位の切り捨てとして累計時間を表示
持ち時間の実装は予定せず。可能なら実装

Excel将棋のシート作成

完成シート

VBA マクロ Excel将棋

※マクロを起動するボタンは、今後の記事で随時追加していきます。

シートを作成するマクロVBA

手作業でも良いのですが、いつでもどのシートでも作成できるようにVBAにしておきます。
駒の配置は「対局開始」のマクロで行うのでここでは必要ありませんが、書式の確認のために入れています。

Sub シート作成()
  Dim ws As Worksheet
  Set ws = ActiveWorkbook.ActiveSheet
  ws.Cells.Clear
  ActiveWindow.DisplayGridlines = False
  
  Dim rng As Range
  Set rng = ws.Range("B2")
  ws.Names.Add Name:="開始位置", RefersToLocal:=rng
  
  Call 名前定義設定(rng)
  Call 列幅行高設定(rng)
  Call セル結合設定(rng)
  Call セル書式設定(rng)
  Call 文字設定(rng)
End Sub

Sub 名前定義設定(ByVal rng As Range)
  With rng.Worksheet
    .Names.Add Name:="将棋盤", RefersToLocal:=rng.Offset(4, 5).Resize(9, 9)
    .Names.Add Name:="先手持駒", RefersToLocal:=rng.Offset(6, 16).Resize(7, 2)
    .Names.Add Name:="先手消費時間", RefersToLocal:=rng.Offset(15, 12).Resize(1, 2)
    .Names.Add Name:="後手持駒", RefersToLocal:=rng.Offset(4, 1).Resize(7, 2)
    .Names.Add Name:="後手消費時間", RefersToLocal:=rng.Offset(1, 6).Resize(1, 2)
    .Names.Add Name:="手数", RefersToLocal:=rng.Offset(15, 5)
    .Names.Add Name:="棋譜", RefersToLocal:=rng.Offset(15, 6).Resize(1, 3)
  End With
End Sub

Sub 列幅行高設定(ByVal rng As Range)
  With rng.EntireColumn
    .Offset(, 0).ColumnWidth = 2.4
    .Offset(, 1).ColumnWidth = 2.4
    .Offset(, 2).ColumnWidth = 4
    .Offset(, 3).ColumnWidth = 0.47
    .Offset(, 4).ColumnWidth = 1.6
    .Offset(, 5).Resize(, 9).ColumnWidth = 4
    .Offset(, 14).ColumnWidth = 1.6
    .Offset(, 15).ColumnWidth = 0.47
    .Offset(, 16).ColumnWidth = 4
    .Offset(, 17).ColumnWidth = 2.4
    .Offset(, 18).ColumnWidth = 2.4
  End With
  
  With rng.EntireRow
    .Offset(0).Resize(17).RowHeight = 18
    .Offset(2).RowHeight = 4.8
    .Offset(3).RowHeight = 13.8
    .Offset(4).Resize(9).RowHeight = 28.2
    .Offset(13).RowHeight = 13.8
    .Offset(14).RowHeight = 4.8
  End With
End Sub

Sub セル結合設定(ByVal rng As Range)
  With rng.Worksheet
    .Range("後手消費時間").Merge
    .Range("先手消費時間").Merge
    .Range("棋譜").Merge
  End With
End Sub

Sub セル書式設定(ByVal rng As Range)
  With rng.Worksheet.Range("開始位置")
    .Resize(17, 19).BorderAround LineStyle:=xlContinuous
  End With
  
  With rng.Worksheet.Range("将棋盤")
    .Offset(-1, -1).Resize(11, 11).BorderAround LineStyle:=xlContinuous, Weight:=xlThick
    .Offset(-1, -1).Resize(11, 11).Interior.Color = RGB(255, 222, 117)
    
    .Borders.LineStyle = xlContinuous
    .Font.Name = "AR教科書体M"
    .Font.Size = 20
    .Font.Bold = True
    .HorizontalAlignment = xlCenter
    
    .Resize(3).Font.Name = "@AR教科書体M" '後手陣のみ
    .Resize(3).Orientation = 90 '後手陣のみ
    
    .Offset(-1).Resize(1).Font.Name = "MS Pゴシック"
    .Offset(-1).Resize(1).Font.Size = 8
    .Offset(-1).Resize(1).HorizontalAlignment = xlCenter
    .Offset(-1).Resize(1).VerticalAlignment = xlCenter
    
    .Offset(, 9).Resize(, 1).Font.Name = "MS Pゴシック"
    .Offset(, 9).Resize(, 1).Font.Size = 8
    .Offset(, 9).Resize(, 1).HorizontalAlignment = xlCenter
    .Offset(, 9).Resize(, 1).VerticalAlignment = xlCenter
  End With
    
  With rng.Worksheet.Range("先手持駒")
    .BorderAround LineStyle:=xlContinuous
    .Interior.Color = RGB(255, 222, 117)
    
    .Offset(, 0).Resize(, 1).Font.Name = "AR教科書体M"
    .Offset(, 0).Resize(, 1).Font.Size = 20
    .Offset(, 0).Resize(, 1).Font.Bold = True
    .Offset(, 0).Resize(, 1).HorizontalAlignment = xlCenter
    
    .Offset(, 1).Resize(, 1).Font.Name = "MS Pゴシック"
    .Offset(, 1).Resize(, 1).Font.Size = 11
    .Offset(, 1).Resize(, 1).Font.Bold = True
    .Offset(, 1).Resize(, 1).HorizontalAlignment = xlLeft
  End With
  
  With rng.Worksheet.Range("後手持駒")
    .BorderAround LineStyle:=xlContinuous
    .Interior.Color = RGB(255, 222, 117)
    
    .Offset(, 1).Resize(, 1).Font.Name = "@AR教科書体M"
    .Offset(, 1).Resize(, 1).Orientation = 90
    .Offset(, 1).Resize(, 1).Font.Size = 20
    .Offset(, 1).Resize(, 1).Font.Bold = True
    .Offset(, 1).Resize(, 1).HorizontalAlignment = xlCenter
    
    .Offset(, 0).Resize(, 1).Font.Name = "MS Pゴシック"
    .Offset(, 0).Resize(, 1).Font.Size = 11
    .Offset(, 0).Resize(, 1).Font.Bold = True
    .Offset(, 0).Resize(, 1).HorizontalAlignment = xlRight
  End With
  
  With rng.Worksheet.Range("先手消費時間")
    .Offset(, -1).Resize(, 3).BorderAround LineStyle:=xlContinuous
    .Offset(, -1).Resize(, 3).Interior.Color = vbBlack
    .Offset(, -1).Resize(, 3).Font.Name = "MS Pゴシック"
    .Offset(, -1).Resize(, 3).Font.Size = 11
    .Offset(, -1).Resize(, 3).Font.Bold = True
    .Offset(, -1).Resize(, 3).Font.Color = vbWhite
    
    .HorizontalAlignment = xlCenter
    .NumberFormatLocal = "h:mm:ss"
  End With
  
  With rng.Worksheet.Range("後手消費時間")
    .Offset(, -1).Resize(, 3).BorderAround LineStyle:=xlContinuous
    .Offset(, -1).Resize(, 3).Interior.Color = vbWhite
    .Offset(, -1).Resize(, 3).Font.Name = "MS Pゴシック"
    .Offset(, -1).Resize(, 3).Font.Size = 11
    .Offset(, -1).Resize(, 3).Font.Bold = True
    
    .HorizontalAlignment = xlCenter
    .NumberFormatLocal = "h:mm:ss"
  End With
  
  With rng.Worksheet.Range("手数")
    .Resize(, 4).Borders.LineStyle = xlContinuous
    .Resize(, 4).Interior.Color = RGB(252, 228, 217)
    .Resize(, 4).Font.Name = "MS Pゴシック"
    .Resize(, 4).Font.Size = 11
  End With
End Sub

Sub 文字設定(ByVal rng As Range)
  Dim ary1(1 To 9, 1 To 9)
  Dim i As Long, j As Long
  For i = 1 To 9
    For j = 1 To 9
      Select Case i
        Case 1, 9
          Select Case j
            Case 1, 9
              ary1(i, j) = "香"
            Case 2, 8
              ary1(i, j) = "桂"
            Case 3, 7
              ary1(i, j) = "銀"
            Case 4, 6
              ary1(i, j) = "金"
            Case 5
              ary1(i, j) = "王"
          End Select
        Case 2, 8
          If (i = 2 And j = 2) Or (i = 8 And j = 8) Then
            ary1(i, j) = "飛"
          End If
          If (i = 2 And j = 8) Or (i = 8 And j = 2) Then
            ary1(i, j) = "角"
          End If
        Case 3, 7
          ary1(i, j) = "歩"
      End Select
    Next
  Next
  
  With rng.Worksheet
    .Range("将棋盤").Offset(-1).Resize(1).Value = Array(9, 8, 7, 6, 5, 4, 3, 2, 1)
    .Range("将棋盤").Offset(, 9).Resize(, 1).Value = WorksheetFunction.Transpose(Array("一", "二", "三", "四", "五", "六", "七", "八", "九"))
    .Range("先手消費時間").Offset(, -1).Resize(, 1).Value = "先手"
    .Range("先手消費時間").Value = TimeSerial(1, 15, 15)
    .Range("後手消費時間").Offset(, -1).Resize(, 1).Value = "後手"
    .Range("後手消費時間").Value = TimeSerial(1, 15, 15)
    .Range("将棋盤").Value = ary1
    .Range("先手持駒").Offset(, 0).Resize(, 1).Value = WorksheetFunction.Transpose(Array("飛", "角", "金", "銀", "桂", "香", "歩"))
    .Range("先手持駒").Offset(, 1).Resize(, 1).Value = WorksheetFunction.Transpose(Array(2, 2, 4, 4, 4, 4, 18))
    .Range("後手持駒").Offset(, 1).Resize(, 1).Value = WorksheetFunction.Transpose(Array("歩", "香", "桂", "銀", "金", "角", "飛"))
    .Range("後手持駒").Resize(, 1).Value = WorksheetFunction.Transpose(Array(18, 4, 4, 4, 4, 2, 2))
    .Range("手数").Value = 100
    .Range("棋譜").Value = "▲3三銀右上成"
  End With
End Sub

※フォントや色は適宜変更してください。
書式設定は特に他で使いまわすことも無いので、VBAをダラダラと一つずつ記述しています。
場所ごとに細かく設定しているので、細部が少しずつ違っています。

複数のシートでゲームができるように、名前定義はシート範囲としています。
名前定義については以下を参照してください。
第92回.名前定義(Names)|VBA入門
名前定義をマクロVBAで扱う場合の解説になります、名前定義は、複数セル範囲や単一セルに対して名前を付けることで、そのセル範囲を参照する時に名前で参照できるようにするものです。名前で参照できることで、セル位置(行位置、列位置)を固定値で指定しなくて済むようになります。

OffsetResizeを多用しています。
第82回.RangeのResizeプロパティ|VBA入門
Resizeプロパティは、指定されたセル範囲(Rangeオブジェクト)のサイズを変更します、そして、サイズが変更されたセル範囲(Rangeオブジェクト)を返します。サイズ変更は、縦方向の行数、横方向の列数の両方またはどちらか一方を指定できます。
第83回.RangeのOffsetプロパティ|VBA入門
Offsetプロパティは、指定されたセル範囲(Rangeオブジェクト)をオフセット(移動)します、オフセット(移動)したセル範囲を表すRangeオブジェクトを返します。Offsetとは、「差し引きする」意味ですが、Offsetプロパティで取得されるのは、元のRange範囲を、指定した行数・列数移動したRange範囲になります。
Offset、Resizeを使いこなそう|VBA技術解説
OffsetとResizeは、エクセルVBAで非常に便利であり、ぜひ使いこなしてもらいたい機能です。Offsetはセル範囲の位置をずらし、Resizeはセル範囲のサイズを変更します。どちらも、RangeとCellsだけで記述することは可能ですが、OffsetとResizeを使う事で、簡潔にVBAを記述することができるようになります。

文字を逆さまにする方法

文字を逆さまにするには以下の設定をします。
・フォント名の先頭に@を付ける
・文字の方向を90度上にする
ただし、半角文字は逆さまにできません。

VBA マクロ Excel将棋

VBA マクロ Excel将棋

Excel将棋の目次

№1. Excel将棋:マクロVBAの学習用
Excelで将棋を作ってみましょう。今やコンピューター将棋はプロをしのぐ強さです。しかし、Excelでそのようなソフトを作ろうと言うのではありません。と言いますか、残念ながら私には作れません、、、ExcelマクロVBAの学習素材として将棋を作ってみましょう。
№2. Excel将棋:クラスの設計
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。今回は、VBAクラスの設計になります。設計といっても、どのようなプロパティ・メソッドをもたせるかといった概要だけです。
№3. Excel将棋:駒クラスの作成
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。今回は、駒クラスの作成になります。駒クラスに必要な部品クラスとして、位置クラスと移動クラスを先に作成してから駒クラスの作成に進みます。
№4. Excel将棋:駒クラスの単体テスト
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。今回は、前回の№3.Excel将棋:駒クラスの作成、この単体テストになります。駒クラスは、今後作成していく駒台クラス、将棋盤クラスで使用するものです。
№5. Excel将棋:駒台クラスの作成&単体テスト
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。今回は、駒台クラスの作成と単体テストになります。作成するクラス全体の設計は、№2.Excel将棋:クラスの設計、こちらを参照してください。
№6. Excel将棋:位置クラスをデフォルトインスタンスに変更
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。今回は、前に作った位置クラスをデフォルトインスタンスに変更します。作成するクラス全体の設計は、№2.Excel将棋:クラスの設計、こちらを参照してください。
№7. Excel将棋:将棋盤クラスの作成&単体テスト
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。今回は、いよいよ将棋盤クラスを作成します。駒クラスを2次元配列(1To9,1To9)に入れて将棋盤全体を管理します。
№8. Excel将棋:将棋進行クラスの作成
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。今回は、シートとやり取りする将棋進行クラスを作成します。ここまでは、作成したクラスのテスト実行用のVBAを別途作成し、結果をイミディエイトウィンドウに表示して確認していました。
№9. Excel将棋:駒を動かす
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。今回は、駒を動かします。駒を動かせるように将棋進行クラスを拡張します。将棋進行クラスの完成はまだまだこれからですが、駒を動かせるようになるとゲームらしくなってきます。
№10. Excel将棋:相手の駒を取る、持ち駒を打つ
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。今回は、相手の駒を取ったり、持駒を打ったりできるようにします。取った駒は駒台へ移し、駒台から駒を選んで打てるようにします。
№11. Excel将棋:駒を成る
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。今回は、駒を成れるようにします。ただし、将棋では成らない選択も出来ますので、成れるタイミングで成るか成らないかを選択できるようにします。
№12. Excel将棋:棋譜をユーザーフォームに表示する
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。今回は、ユーザーフォームを作成し、初手からの棋譜を表示できるようにします。シート操作ができるように、ユーザーフォームはモードレスで表示します。
№13. Excel将棋:棋譜選択でその時点の盤面に戻す
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。今回は、棋譜フォームの棋譜を選択することで、その時点の盤面に戻す機能を実装します。さらに、その時点から指し継ぐこともできるようにします。
№14. Excel将棋:棋譜ファイルの出力と読込自動再生
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。今回は、KIF形式の棋譜ファイルの出力と、KIF形式の棋譜ファイルを読み込んで初手から終局までを自動再生させます。
№15. Excel将棋:反則(禁じ手)判定
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。今回は、反則(禁じ手)の判定を入れます。禁じ手は指し手そのものが出来ないようにします。※クラス名、プロシージャー名、変数名に日本語を使用しています。
№16. Excel将棋:終局(詰み)判定と打ち歩詰め
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。今回は、前回の反則(禁じ手)の続きで「打ち歩詰め」を実装します。打ち歩詰めを判定するには、そもそも「詰み」の判定が必要です。
№17. Excel将棋:千日手と連続王手の千日手
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。今回は、千日手と反則の「連続王手の千日手」を実装します。千日手は、他とは違ってある局面だけでは判定できません。
№18 Excel将棋:ひとまず完成、これまでとこれから
Excelで将棋を作ってみましょう。人vs人で動かしてゲームとして成立するところまでが当面の目標です。前回でひとまず当初目標の人vs人で動かしてゲームとして成立するところまでできました。連載の途中で、急遽棋譜の出力と読み込んで自動再生も作成しました。
№19 Excel将棋:棋譜ファイルから対局一覧作成
Excelで将棋を作るシリーズの当初目標の、人vs人で動かしてゲームとして成立するところまでは完成しました。今回は機能拡張として、棋譜ファイルを読み込み対局一覧を作成します。複数の棋譜ファイルも一度に処理できるようにしています。



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

数独(ナンプレ)を解くVBAに挑戦№1
数独(ナンプレ)を解くアルゴリズムの要点とパフォーマンスの検証№1
ナンバーリンク(パズル)を解くVBAに挑戦№1
ナンバーリンクを解くVBAのパフォーマンス改善№1
オセロを作りながらマクロVBAを学ぼう
他ブックへのリンクエラーを探し解除
Excelシートの複雑な計算式を解析するVBA
Excel将棋:マクロVBAの学習用(№1)
Excel囲碁:万波奈穂先生に捧ぐ
Excel囲碁:再起動後も続けて打てるように改造
エクセルVBAで15パズルを作ってみた


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

import文(パッケージ・モジュールのインポート)|Python入門(9月24日)
例外処理(try文)とexception一覧|Python入門(9月23日)
リスト内包表記|Python入門(9月22日)
Pythonの引数は参照渡しだが・・・|Python入門(9月21日)
lambda(ラムダ式、無名関数)と三項演算子|Python入門(9月20日)
関数内関数(関数のネスト)とスコープ|Python入門(9月18日)
関数の定義(def文)と引数|Python入門(9月18日)
組み込み関数一覧|Python入門(9月17日)
辞書(dict型)|Python入門(9月16日)
入力規則への貼り付けを禁止する|VBA技術解説(9月16日)


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

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.マクロって何?VBAって何?|VBA入門
5.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
6.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
7.繰り返し処理(For Next)|VBA入門
8.セルに文字を入れるとは(Range,Value)|VBA入門
9.とにかく書いてみよう(Sub,End Sub)|VBA入門
10.マクロはどこに書くの(VBEの起動)|VBA入門




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


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



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