【Word VBA】迷路描画マクロ▽ソースコード

記事
IT・テクノロジー
HC220320A.png

Option Explicit
Option Base 0
Public Sub 迷路描画マクロ()
    Const MAZEXCNT = 12           '迷路横方向マス数
    Const MAZEYCNT = 12           '迷路縦方向マス数
    '
    Const MAZELEFT = 80            '迷路描画開始位置
    Const MAZETOPP = 60           '迷路
    '
    Const MAZEWIDT = 240         '迷路幅
    Const MAZEHEIG = 240      '迷路高
    '
    Const MAZEWCOL = vbBlue   '迷路壁線色
    Const MAZEWWEI = 1.5    '    太さ
    '---------------------------------------------------------------------------
    Dim Ip As Integer, Jp As Integer, Kp As Integer, Lp As Integer
    Dim intGrWd As Integer, intGrHe As Integer, intXp As Integer
  Dim intYp As Integer
    Dim intMzDt(MAZEXCNT - 1, MAZEYCNT - 1, 2) As Integer
    Dim intRn As Integer, intXb As Integer, intYb As Integer
    Dim intCn As Integer, intXw As Integer, intYw As Integer
    Dim lngCl As Long
   '
    '
    '*アルゴリズムは穴掘り法で。
    GoSub 迷路データ生成S1 '
    '*外枠
    With ActiveDocument.Shapes.AddShape(msoShapeRectangle, _
                           MAZELEFT, MAZETOPP,  MAZEWIDT, MAZEHEIG)
         .Fill.Visible = False
         .Line.ForeColor.RGB = MAZEWCOL
         .Line.Weight = MAZEWWEI
         .Line.Visible = True
    End With
    '*マス
    intGrWd = MAZEWIDT \ MAZEXCNT
    intGrHe = MAZEHEIG \ MAZEYCNT
    For Jp = 0 To MAZEYCNT - 1
        For Ip = 0 To MAZEXCNT - 1
            intXp = MAZELEFT + intGrWd * Ip
            intYp = MAZETOPP + intGrHe * Jp
            '
            If Ip < MAZEXCNT - 1 And _
              (intMzDt(Ip, Jp, 2) And &H1) <> 0 Then
              With ActiveDocument.Shapes.AddLine(intXp+intGrWd,  _
                     intYp,  intXp + intGrWd, intYp + intGrHe).Line
                   .ForeColor.RGB = MAZEWCOL         '←線色
                   .Weight = MAZEWWEI                   '←線の太さ
                   .DashStyle = msoLineSolid             '←線のスタイル
                   .Visible = msoTrue
               End With
            End If
            If Jp < MAZEYCNT - 1 And _
                                    (intMzDt(Ip, Jp, 2) And &H2) <> 0 Then
               With ActiveDocument.Shapes.AddLine(intXp, intYp + _
                      intGrHe, intXp + intGrWd, intYp + intGrHe).Line
                   .ForeColor.RGB = MAZEWCOL          '←線色
                   .Weight = MAZEWWEI                    '←線の太さ
                   .DashStyle = msoLineSolid              '←線のスタイル
                   .Visible = msoTrue
               End With
            End If
        Next Ip
    Next Jp
    Exit Sub
    '==========================================
迷路データ生成S1: '/サブルーチン
    '*テーブルクリア
    For Jp = 0 To MAZEYCNT - 1
        For Ip = 0 To MAZEXCNT - 1
            intMzDt(Ip, Jp, 0) = 0 'ルート番号
            intMzDt(Ip, Jp, 1) = 0 '道順
            intMzDt(Ip, Jp, 2) = 0 '壁情報 1:右辺 2:下辺
        Next Ip
    Next Jp
    '
    Randomize '*乱数列初期化
    '
    '*迷路の道作成
    intXp = 0: intYp = 0
    '最初
    intRn = 1: GoSub 迷路データ生成S2
    '二番目以降
    For intRn = 2 To 9999
        '起点マス検索
        intXp = -1: intYp = -1
        For Jp = 0 To MAZEYCNT - 1
            For Ip = 0 To MAZEXCNT - 1
                If intMzDt(Ip, Jp, 0) = 0 Then
                   intXp = Ip: intYp = Jp: Exit For
                End If
            Next Ip
            If intXp >= 0 And intYp >= 0 Then Exit For
        Next Jp
        '見つからなければ終了
        If intXp = -1 And intYp = -1 Then Exit For
        GoSub 迷路データ生成S2
    Next intRn
    '
    '*迷路の壁作成
    For Jp = 0 To MAZEYCNT - 1
        For Ip = 0 To MAZEXCNT - 1
            If Ip < MAZEXCNT - 1 Then
               If intMzDt(Ip, Jp, 0) = intMzDt(Ip + 1, Jp, 0) And _
                  Abs(intMzDt(Ip, Jp, 1) - intMzDt(Ip + 1, Jp, 1)) = 1 Then
                  intMzDt(Ip, Jp, 2) = intMzDt(Ip, Jp, 2) Or &H0
               Else
                  intMzDt(Ip, Jp, 2) = intMzDt(Ip, Jp, 2) Or &H1
               End If
            End If
            If Jp < MAZEYCNT - 1 Then
               If intMzDt(Ip, Jp, 0) = intMzDt(Ip, Jp + 1, 0) And _
                  Abs(intMzDt(Ip, Jp, 1) - intMzDt(Ip, Jp + 1, 1)) = 1 Then
                  intMzDt(Ip, Jp, 2) = intMzDt(Ip, Jp, 2) Or &H0
               Else
                  intMzDt(Ip, Jp, 2) = intMzDt(Ip, Jp, 2) Or &H2
               End If
            End If
        Next Ip
    Next Jp
    '*ルート毎の道結合
    For Jp = 0 To MAZEYCNT - 1
        For Ip = 0 To MAZEXCNT - 1
            'ルート番号が2以上が対象
            If intMzDt(Ip, Jp, 0) > 1 And intMzDt(Ip, Jp, 1) = 1 Then
               intCn = 0: Lp = -1
               For Kp = 0 To 3       '異なるルート番号の最大道順隣接マス検索
                   intXp = Ip + Choose(Kp + 1, 0, 1, 0, -1)
                   intYp = Jp + Choose(Kp + 1, -1, 0, 1, 0)
                   If intXp >= 0 And intYp >= 0 And _
                      intXp < MAZEXCNT And intYp < MAZEYCNT Then
                      If intMzDt(Ip, Jp, 0) <> intMzDt(intXp, intYp, 0) Then
                         If intMzDt(intXp, intYp, 1) > intCn Then
                            intCn = intMzDt(intXp, intYp, 1): Lp = Kp
                         End If
                      End If
                   End If
               Next Kp
               If Lp >= 0 Then                '対象マスの壁を削除
                  Select Case Lp
                         Case 0:
               intMzDt(Ip, Jp - 1, 2) = intMzDt(Ip, Jp - 1, 2) And &HFFFD
                         Case 1:
               intMzDt(Ip, Jp - 0, 2) = intMzDt(Ip, Jp - 0, 2) And &HFFFE
                         Case 2:
               intMzDt(Ip, Jp - 0, 2) = intMzDt(Ip, Jp - 0, 2) And &HFFFD
                         Case 3:
               intMzDt(Ip - 1, Jp, 2) = intMzDt(Ip - 1, Jp, 2) And &HFFFE
                   End Select
               End If
            End If
        Next Ip
    Next Jp
    Return
    '==========================================
迷路データ生成S2: '/サブルーチン
    intCn = 1 '道順
    intMzDt(intXp, intYp, 0) = intRn: intMzDt(intXp, intYp, 1) = intCn
    Do
        intXb = intXp: intYb = intYp:
        Jp = Int(4 * Rnd)
        For Ip = 0 To 3
            intXw = intXp + Choose(((Ip + Jp) Mod 4) + 1, 0, 1, 0, -1)
            intYw = intYp + Choose(((Ip + Jp) Mod 4) + 1, -1, 0, 1, 0)
            If intXw >= 0 And intYw >= 0 And _
               intXw < MAZEXCNT And intYw < MAZEYCNT Then
               If intMzDt(intXw, intYw, 0) = 0 Then
                  intXp = intXw: intYp = intYw: intCn = intCn + 1
                  intMzDt(intXp, intYp, 0) = intRn
                  intMzDt(intXp, intYp, 1) = intCn
                  Exit For
               End If
            End If
        Next Ip
        '行き止まりか、ゴールなら終わり
    If intXb = intXp And intYb = intYp Then Exit Do
    If intXp = MAZEXCNT - 1 And intYp = MAZEYCNT - 1 Then Exit Do
    Loop While True
    Return
End Sub

HC220320B.png
        Const MAZEXCNT = 24                '迷路横方向マス数
        Const MAZEYCNT = 24                '迷路縦方向マス数

       《参考》作成時間 およそ116秒

蛇足
 「人生こそが、最高・最低の迷路だ」と、どこかの偉い人が言っていたような・・・。


サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す ココナラコンテンツマーケット ノウハウ記事・テンプレート・デザイン素材はこちら