エクセルVBAでマルバツゲームを作ってみる

VBA

エクセルでマルバツゲームを作った。

使うもの

メインで使ったのはSelectionChangeというセルを選択したときに動作する機能。

あとは基本的なものだけ

  • if
  • for
  • array
  • Range
  • Goto

ルール

  • 左上の3*3のマスのみを使用する
  • プレイヤーが先行の○(枠外を選択すればCPUが先行になる)
  • 先に3列揃えば勝利

動き

1手目
右下に○を付けると、すぐさま真ん中に×を付けるCPU

2手目
左上に○を付けると、すぐさま右中に×を付けるCPU

3手目
左中に○

4手目
右上に○

5手目
下中に○を付けて引き分け

すぐさま画面をクリアして引き分けのメッセージボックスが表示される。

コード

開発-Visual Basic

画面左にあるプロジェクトのSheet1をダブルクリック

開いたウインドウの左上に(General)となっている部分をプルダウンからWorksheetを選択

後はプログラムウインドウに下のコードを貼り付ければOK

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    '不正な場所
    If Target.Value <> "" Then
        Exit Sub
    End If
    If Target.Row > 3 Or Target.Column > 3 Then
        Exit Sub
    End If
    
    Target.Value = "〇"
    Dim ライン構成セル(1 To 8) As Variant
    Dim ライン防御判定(1 To 8) As Variant
    Dim ライン非攻撃レベル(1 To 8) As Variant
    
    ライン構成セル(1) = Array("A1", "B1", "C1")
    ライン構成セル(2) = Array("A2", "B2", "C2")
    ライン構成セル(3) = Array("A3", "B3", "C3")
    ライン構成セル(4) = Array("A1", "A2", "A3")
    ライン構成セル(5) = Array("B1", "B2", "B3")
    ライン構成セル(6) = Array("C1", "C2", "C3")
    ライン構成セル(7) = Array("A1", "B2", "C3")
    ライン構成セル(8) = Array("C1", "B2", "A3")

    '勝っているか確認
    For i = 1 To 8
        For Each セル In ライン構成セル(i)
            If Range(セル) = "〇" Then
                勝利カウンタ = 勝利カウンタ + 1
            End If
        Next
        If 勝利カウンタ = 3 Then
            MsgBox "あなたの勝利です"
            Cells.Clear
            Exit Sub
        End If
        勝利カウンタ = 0
    Next
    '全て埋まっている場合は勝敗を確認
    For Each セル In Range("A1:C3")
        If セル <> "" Then
            飽和カウント = 飽和カウント + 1
        End If
    Next
    If 飽和カウント = 1 Then
        If Range("B2") = "" Then
            Range("B2") = "×"
            GoTo 勝敗判定
        End If
    End If
    
    If 飽和カウント = 9 Then
        GoTo 勝敗判定
    End If
    '一手勝ち確認
    For i = 1 To 8
        攻勢カウンタ = 0
        勝利のセル = ""
        For Each セル In ライン構成セル(i)
            If Range(セル) = "×" Then
                攻勢カウンタ = 攻勢カウンタ + 1
            End If
            If Range(セル) = "〇" Then
                Exit For
            End If
            If Range(セル) = "" Then
                勝利のセル = セル
            End If
            If 攻勢カウンタ = 2 And 勝利のセル <> "" Then
                Range(勝利のセル) = "×"
                GoTo 勝敗判定
        End If
        Next
    Next
    '一手負け防御
    For i = 1 To 8
        劣勢カウンタ = 0
        敗北のセル = ""
        For Each セル In ライン構成セル(i)
            If Range(セル) = "〇" Then
                劣勢カウンタ = 劣勢カウンタ + 1
            End If
            If Range(セル) = "×" Then
                Exit For
            End If
            If Range(セル) = "" Then
                敗北のセル = セル
            End If
            If 劣勢カウンタ = 2 And 敗北のセル <> "" Then
                Range(敗北のセル) = "×"
                GoTo 勝敗判定
            End If
        Next
    Next
    '〇が多いラインを確認
    For i = 1 To 8
        ライン非攻撃レベル(i) = 0
        For Each セル In ライン構成セル(i)
            If Range(セル) = "×" Then
                ライン防御判定(i) = True
            End If
            If Range(セル) = "〇" Then
                ライン非攻撃レベル(i) = ライン非攻撃レベル(i) + 1
            End If
        Next
        If ライン防御判定(i) Then
            ライン非攻撃レベル(i) = 0
        End If
    Next
    '防ぐラインを決定
    暫定防衛ライン非攻撃レベル = -1
    For i = 1 To 8
        飽和カウント = 0
        For Each セル In ライン構成セル(i)
            If Range(セル) <> "" Then
                飽和カウント = 飽和カウント + 1
            End If
        Next
        If 飽和カウント = 3 Then
            GoTo コンテニュー
        End If
        ランダム = Int(2 * Rnd)
        If ライン非攻撃レベル(i) > 暫定防衛ライン非攻撃レベル Then
            暫定防衛ライン = i
            暫定防衛ライン非攻撃レベル = ライン非攻撃レベル(i)
        ElseIf ライン非攻撃レベル(i) = 暫定防衛ライン非攻撃レベル And ランダム > 0 Then
            暫定防衛ライン = i
            暫定防衛ライン非攻撃レベル = ライン非攻撃レベル(i)
        End If
コンテニュー:
    Next
    '防ぐラインへ×を入れる
    For Each セル In ライン構成セル(暫定防衛ライン)
        ランダム = Int(2 * Rnd)
        If Range(セル) = "" And 暫定空きセル <> "" And ランダム > 0 Then
            Range(セル).Value = "×"
            GoTo 勝敗判定
        ElseIf Range(セル).Value = "" Then
            暫定空きセル = セル
        ElseIf 暫定空きセル <> "" Then
            Range(暫定空きセル).Value = "×"
            GoTo 勝敗判定
        End If
    Next
    If 暫定空きセル <> "" Then
        Range(暫定空きセル) = "×"
        GoTo 勝敗判定
    End If
    '勝敗の確認
勝敗判定:
    For i = 1 To 8
        For Each セル In ライン構成セル(i)
            If Range(セル) = "〇" Then
                勝利カウンタ = 勝利カウンタ + 1
            End If
            If Range(セル) = "×" Then
                敗北カウンタ = 敗北カウンタ + 1
            End If
        Next
        If 勝利カウンタ = 3 Then
            MsgBox "あなたの勝利です"
            Cells.Clear
            Exit Sub
        ElseIf 敗北カウンタ = 3 Then
            MsgBox "あなたの負けです"
            Cells.Clear
            Exit Sub
        ElseIf 飽和カウント = 9 Then
            MsgBox "引き分けです"
            Cells.Clear
            Exit Sub
        End If
        勝利カウンタ = 0
        敗北カウンタ = 0
    Next
End Sub

 

最後に

作りながらCPUの×をどこに置くべきか何度もif文を追加した。

最初のうちは何も考えていないような場所に×を付けたり、○を上書きするチートまでやっていた。

if文をいくつも付け足してようやく3*3のマスであれば負けないレベルにはなった。

なんだか子供の成長を見ているようだったTvT

コメント

タイトルとURLをコピーしました