EXCEL VBA 初心者でもできる!Excelで遊べる三目並べ!Tic-Tac-Toe(コード解説付き・ダウンロード可能)

 

EXCEL VBA 初心者でもできる!Excelで遊べる三目並べ!ゲームを作る(コード解説付き・ダウンロード可能)

 

●はじめに

今回説明するのはExcel VBAで三目並べでゲームを作成しましたので、この作成した三目並べ解説を行います。3つのサンプルプログラムを作成しており、プログラム①⇒②⇒③につれて複雑な処理を行っております。それでは、まず、三目並べについて説明します。三目並べ(Tic-Tac-Toe)は、二人で遊ぶ単純なペンと紙のゲームです。プレイヤーは交互に、「O」と「X」のマークを、3×3のグリッドに入れていきます。勝利の条件は、自分のマークを縦、横、または斜めの一列に揃えることです。一方がこの条件を満たすか、すべてのマスが埋まるまでゲームは続けられます。
このゲームは非常に簡単で、戦略も限られているため、大人同士の遊びとしてはすぐに飽きられることがありますが、子供たちにとっては理論的思考や先読みの基礎を学ぶ良い手段となります。また、手軽に遊べるため、ちょっとした時間潰しやリラックスするためのアクティビティとしても楽しまれています。
それでは、三目並べのゲームの作り方を順番に説明いたします。

●【EXCEL VBA 初心者でもできる!Excelで遊べるブラックジャックゲーム、下記を参照して下さい】

 

●【Worksheet.SelectionChange イベント (Excel)、下記を参照して下さい】(Microsoft社 様)】
https://learn.microsoft.com/ja-jp/office/vba/api/excel.worksheet.selectionchange

 

 

Excel VBAで三目並べゲームを作ってみた!①:二人で遊ぶ( 人間 対 人間)

 

 

●プログラム説明 (サンプル①)

今回説明するのは、ExcelのセルとVBAを使って、三目並べゲームの作成方法を紹介します。基本的なゲームの流れとルールをVBAでどのようにプログラミングしたか、コードとともに解説していきます。このExcel VBAプログラムは、Excelシート上で三目並べ(Tic-Tac-Toe)をプレイするためのシンプルなゲームです。プログラムは、ゲームの状態を追跡するためにグローバル変数(currentPlayer, moveCount)を使用し、ユーザーの操作に基づいてセルの選択、プレイヤーの切り替え、勝利条件のチェックなどを行います。なお、今回のサンプル①のプログラムでは、人間対人間で勝負(ゲーム)する形となります。

 

【プログラムの流れ】

  • Worksheet_SelectionChange: ユーザーがセルを選択するたびに発生するイベント。セルがゲームのグリッド(B2:D4)内で、かつ空の場合、現在のプレイヤーの記号をそのセルに記入し、手数を増やします。勝利条件を満たしているか、または引き分け条件(全てのセルが埋まる)に達しているかを確認し、必要に応じてゲームを再開始します。
  • StartGame: ゲームを初期化するためのサブルーチン。B2:D4の範囲のセルをクリアし、ゲームの状態を初期状態(Xの手番、手数0)にリセットします。
  • TogglePlayer: 現在のプレイヤーをXからO、またはOからXに切り替えます。
  • CheckWinner: 現在のプレイヤーが勝利条件を満たしているかどうかをチェックします。勝利条件は、任意の行、列、または対角線上に同じプレイヤーの記号が3つ揃うことです。
  • CheckThree: 3つの指定されたセルが同じプレイヤーの記号であるかどうかをチェックする関数です。

【プログラム実行条件・注意事項】

  • セルの選択範囲: ゲームのグリッド外のセルを選択しても何も起こりません。
  • セルの状態: すでに記号が入っているセルを選択した場合、そのセルは変更されません。
  • 手数の制限: 手数が9に達するとゲームは自動的に終了します。これは引き分けを意味することが多いです。
  • エラーハンドリング: プログラムにはエラーハンドリングのコードが含まれていません。不正な入力や予期しない動作が発生した場合の処理が必要かもしれません。
  • インターフェースの単純さ: グラフィカルなインターフェースやアニメーションは含まれていません。ゲームは非常に基本的な形で行われます。

★【サンプルプログラム】
下記のリンク先よりサンプルプログラムをダウンロードする事ができます。
● tic-tac-toe01 (サンプルプログラム)

 

 

Option Explicit

' 公開変数の宣言
Public currentPlayer As String
Public moveCount As Integer

' セルが選択されたときに実行されるイベント
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("B2:D4")) Is Nothing Then
        If IsEmpty(Target.Value) And moveCount < 9 Then
            Target.Value = currentPlayer
            moveCount = moveCount + 1

            If CheckWinner(currentPlayer) Then
                MsgBox currentPlayer & " wins!"
                StartGame
            ElseIf moveCount = 9 Then
                MsgBox "It's a draw!"
                StartGame
            Else
                TogglePlayer
            End If
        End If
    End If
End Sub

' ゲームの開始と初期化
Sub StartGame()
    Dim cell As Range
    For Each cell In Me.Range("B2:D4")
        cell.Value = ""
        cell.Interior.Color = xlNone
    Next cell
    currentPlayer = "X"
    moveCount = 0
End Sub

' プレイヤーの交代
Sub TogglePlayer()
    If currentPlayer = "X" Then
        currentPlayer = "O"
    Else
        currentPlayer = "X"
    End If
End Sub

' 勝利条件のチェック
Function CheckWinner(player As String) As Boolean
    CheckWinner = False
    If CheckThree("B2", "B3", "B4", player) Or CheckThree("C2", "C3", "C4", player) Or _
       CheckThree("D2", "D3", "D4", player) Or CheckThree("B2", "C2", "D2", player) Or _
       CheckThree("B3", "C3", "D3", player) Or CheckThree("B4", "C4", "D4", player) Or _
       CheckThree("B2", "C3", "D4", player) Or CheckThree("B4", "C3", "D2", player) Then
        CheckWinner = True
    End If
End Function

' 3つのセルが同じプレイヤーの記号かチェック
Function CheckThree(cell1 As String, cell2 As String, cell3 As String, player As String) As Boolean
    CheckThree = (Range(cell1).Value = player And Range(cell2).Value = player And Range(cell3).Value = player)
End Function


 

●実行前~実行後 ※このプログラムを実行すると、ユーザーはExcelのシート上で三目並べをプレイできます。勝者が決定すると、そのプレイヤーが勝ったことを示すポップアップメッセージが表示され、新しいゲームが自動的に開始されます。9手を超えるとゲームは引き分けとなります。
(画面クリックして拡大)

 

 

 

Excel VBAで三目並べゲームを作ってみた!②:一人で遊ぶ(人間 対 CPU)

 

 

●プログラム説明 (サンプル②)

上記のサンプルプログラム①では、人間対人間の三目並べゲームの説明でしたが、今回は、人間対CPUとの勝負(ゲーム)となります。このVBAプログラムはExcel上で三目並べ(Tic-Tac-Toe)をプレイするためのものです。プレイヤー(’O’)とコンピューター(’X’)が交互にゲームを進めます。プレイヤーの選択やコンピューターのランダムな手、勝利条件のチェック、ゲームのリセットなどの機能が含まれています。セル選択イベントに基づいてゲームの進行が管理され、勝利条件を満たすと勝利メッセージが表示されます。引き分けの状況やゲームの再開始もプログラム内で処理されています。全体的に、このプログラムはExcel VBAを使用して基本的なゲームロジックを実装しており、ユーザーとコンピューターが対戦するインタラクティブな三目並べゲームを提供します。

【プログラムの流れ】
・Worksheet_SelectionChange:
プレイヤーがB2:D4範囲内の空のセルを選択したときに、そのセルに「O」を入力し、手数をカウントアップする。勝利条件をチェックし、勝利または引き分けの場合はメッセージを表示してゲームを再開始する。それ以外の場合は、コンピューターの手を呼び出す。
・ComputerMove: コンピューターがB2:D4範囲内の空のセルの中からランダムに一つ選び、「X」を入力する。勝利条件をチェックし、勝利または引き分けの場合はメッセージを表示してゲームを再開始する。次のプレイヤーを「O」に設定する。
・StartGame: B2:D4範囲内のセルをクリアし、現在のプレイヤーを「O」に設定し、手数を0にリセットする。
・CheckWinner: 指定されたプレイヤーが勝利条件を満たしているかどうかをチェックする。
・CheckThree: 指定された3つのセルが同じプレイヤーの記号であるかをチェックする。

 

【プログラム実行条件・注意事項】
・プレイヤーの入力: ユーザーは常に「O」を使用し、コンピューターは「X」を使用する。
・手数の制限: 9手に達するとゲームは自動的に引き分けとなる。
・ランダム性: コンピューターの手はランダムであり、戦略は含まれていない。
・エラーハンドリング: エラーハンドリングのコードが含まれていないため、不正な入力や予期しない動作には対応していない。
・パフォーマンス: 無駄なループ(For i = 1 To 100000000)※この部分については、コンピューター側が直ぐに配置するのを遅らせるため。

★【サンプルプログラム】
下記のリンク先よりサンプルプログラムをダウンロードする事ができます。
● tic-tac-toe02(サンプルプログラム)

 

'
'
Option Explicit

' 公開変数の宣言
Public currentPlayer As String  ' 現在のプレイヤーを保持する変数('O' または 'X')
Public moveCount As Integer     ' ゲーム中の手数をカウントする変数

' セルが選択されたときに実行されるイベントハンドラ
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    ' 選択されたセルがゲームのグリッド内かどうかチェック
    If Not Intersect(Target, Me.Range("B2:D4")) Is Nothing Then
        ' セルが空かつ現在のプレイヤーが 'O' の場合
        If IsEmpty(Target.Value) And currentPlayer = "O" Then
            ' 選択されたセルに現在のプレイヤーの記号を設定
            Target.Value = currentPlayer
            ' 手数を1増やす
            moveCount = moveCount + 1

            ' 勝利条件をチェック
            If CheckWinner(currentPlayer) Then
                ' 勝利した場合、勝利メッセージを表示し、ゲームを再開始
                MsgBox currentPlayer & " wins!"
                StartGame
            ' 手数が9以上の場合(引き分け)
            ElseIf moveCount >= 9 Then
                ' 引き分けのメッセージを表示し、ゲームを再開始
                MsgBox "It's a draw!"
                StartGame
            ' それ以外の場合
            Else
                ' コンピューターの手を呼び出し
                ComputerMove
            End If
        End If
    End If
End Sub

' コンピューターの手順
Sub ComputerMove()
    Dim i As Long
    Dim emptyCells As Collection
    Set emptyCells = New Collection  ' 空のセルを格納するためのコレクション
    
    ' タイムディレイのためのループ(パフォーマンス上の問題あり)
    For i = 1 To 100000000
    Next i
    
    Dim cell As Range
    ' ゲームのグリッドをループして空のセルをコレクションに追加
    For Each cell In Me.Range("B2:D4")
        If IsEmpty(cell.Value) Then
            emptyCells.Add cell
        End If
    Next cell

    ' 空のセルがある場合
    If emptyCells.Count > 0 Then
        Dim randomIndex As Integer
        Randomize  ' ランダムな数を生成するための初期化
        ' 空のセルの中からランダムに一つ選択
        randomIndex = Int((emptyCells.Count * Rnd) + 1)
        ' 選択されたセルに 'X' を設定
        emptyCells.Item(randomIndex).Value = "X"
        ' 手数を1増やす
        moveCount = moveCount + 1

        ' 勝利条件をチェック
        If CheckWinner("X") Then
            ' 勝利した場合、勝利メッセージを表示し、ゲームを再開始
            MsgBox "X wins!"
            StartGame
        ' 手数が9以上の場合(引き分け)
        ElseIf moveCount >= 9 Then
            ' 引き分けのメッセージを表示し、ゲームを再開始
            MsgBox "It's a draw!"
            StartGame
        End If
    End If

    ' 次のプレイヤーを 'O' に設定
    currentPlayer = "O"
End Sub

' ゲームの開始と初期化
Sub StartGame()
    Dim cell As Range
    ' ゲームのグリッド内のセルをループしてリセット
    For Each cell In Me.Range("B2:D4")
        cell.Value = ""  ' セルの値をクリア
        'cell.Interior.Color = xlNone  ' セルの背景色をクリア(現在はコメントアウト)
    Next cell
    ' 現在のプレイヤーを 'O' に設定
    currentPlayer = "O"
    ' 手数を0にリセット
    moveCount = 0
End Sub

' 勝利条件のチェック
Function CheckWinner(player As String) As Boolean
    ' 勝利しているかどうかの初期値はFalse
    CheckWinner = False
    ' 各行、各列、または対角線が同じプレイヤーの記号で揃っているかチェック
    If CheckThree("B2", "B3", "B4", player) Or CheckThree("C2", "C3", "C4", player) Or _
       CheckThree("D2", "D3", "D4", player) Or CheckThree("B2", "C2", "D2", player) Or _
       CheckThree("B3", "C3", "D3", player) Or CheckThree("B4", "C4", "D4", player) Or _
       CheckThree("B2", "C3", "D4", player) Or CheckThree("B4", "C3", "D2", player) Then
        CheckWinner = True  ' いずれかの条件を満たしていればTrueに設定
    End If
End Function

' 3つのセルが同じプレイヤーの記号かチェック
Function CheckThree(cell1 As String, cell2 As String, cell3 As String, player As String) As Boolean
    ' 3つのセルがすべて指定されたプレイヤーの記号であればTrue、そうでなければFalseを返す
    CheckThree = (Range(cell1).Value = player And Range(cell2).Value = player And Range(cell3).Value = player)
End Function
'
'

 

●実行前~実行後 ※スターボタンを押してゲームを開始します。プレイヤーは「O」を使用し、コンピューターは「X」をランダムに配置します。どちらかが勝利条件を満たすか、9手で引き分けになると、ゲームはメッセージを表示して再開始します。
(画面クリックして拡大)

 

 

Excel VBAで三目並べゲームを作ってみた!③:1人で遊ぶ(人間 対 AI?CPU)

 

 

●プログラム説明 (サンプル③)

今回のサンプルプログラム③では、サンプル②と同様に人間対CPUとのゲームですが、CPU側が遥かに賢くなっています。サンプルでは、空いているマスにランダムに配置するように出来ていますが、今回のサンプル③では、3つ並ぶのを阻止したり、早く3つ並べる様に考えて配置するプログラムを追加しているので、②のプログラムと違い賢くなっています。

★コンピュータの手を賢くするロジックを組み込む①②

①✖を配置する場所を探す:コンピュータ(✖)は、自分が勝つために縦、横、斜めのいずれかで3つの✖を揃えることを試みます。これは、既に2つの✖が並んでいる行、列、または対角線を探し、空いているセルに✖を配置することによって実現されます。
②〇の勝利を阻止する:もし上記の戦略で配置する場所がない場合、コンピュータは〇が勝つのを阻止するために動きます。これは、既に2つの〇が並んでいる行、列、または対角線を探し、空いているセルに✖を配置することによって実現されます。が交互に手を進め、勝利条件を満たすか9手に達すると、勝利者が発表され、ゲームが再開始されます。勝利条件が満たされない場合は引き分けとなります。

【プログラムの流れ】
・Worksheet_SelectionChange:
ユーザーがセルを選択すると、選択されたセルがゲームグリッド内にあるかをチェックし、現在のプレイヤーが「O」の場合、セルに「O」を入力して手数を増やします。勝利条件をチェックし、勝利または引き分けの場合、メッセージを表示してゲームを再開始します。それ以外の場合は、コンピューターの手を進行させます
・ComputerMove:
勝利する手があればそれを選択し、なければユーザーの勝利を阻止する手を選択します。どちらもない場合はランダムな手を選択します。手数を増やし、ゲームの状態をチェックします。
・FindWinningMove:
指定されたプレイヤーが勝利する可能性のある手を見つけます。
・PlaceRandomMove:
空のセルの中からランダムに手を選択して配置します。
・CheckGameStatus:
勝利条件をチェックし、勝利または引き分けの場合、メッセージを表示してゲームを再開始します。
・StartGame:
ゲームを初期化し、セルをリセットして現在のプレイヤーを「O」に設定し、手数を0にリセットします。
・CheckWinner:
勝利条件をチェックします。
・CheckThree:
指定された3つのセルが同じプレイヤーの記号であるかをチェックします。

 

【プログラム実行条件・注意事項】
パフォーマンス:
コンピューターの手を選択するロジックにおいて、効率的なアルゴリズムを使用することが重要です。
エラーハンドリング:
エラー処理が不足している可能性があります。適切なエラーハンドリングを追加することを検討してください。
ユーザー入力:
ユーザーは「O」のみを使用し、コンピューターは「X」を使用します。

 

★【サンプルプログラム】
下記のリンク先よりサンプルプログラムをダウンロードする事ができます。
● tic-tac-toe03(サンプルプログラム)

 

'
'
Option Explicit

' 公開変数の宣言
Public currentPlayer As String  ' 現在のプレイヤー('O' または 'X')を格納する変数
Public moveCount As Integer     ' ゲーム中の手数をカウントする変数

' セルが選択されたときに実行されるイベントハンドラ
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    ' 選択されたセルがゲームのグリッド(B2:D4)内にあるかチェック
    If Not Intersect(Target, Me.Range("B2:D4")) Is Nothing Then
        ' セルが空で、現在のプレイヤーが 'O' である場合
        If IsEmpty(Target.Value) And currentPlayer = "O" Then
            ' 選択されたセルに現在のプレイヤーの記号を入力
            Target.Value = currentPlayer
            ' 手数を1増やす
            moveCount = moveCount + 1

            ' 勝利条件をチェックする関数を呼び出し
            If CheckWinner(currentPlayer) Then
                ' 勝利した場合、メッセージボックスで通知し、ゲームを再開始
                MsgBox currentPlayer & " wins!"
                StartGame
            ' 手数が9以上で引き分けの場合
            ElseIf moveCount >= 9 Then
                ' 引き分けのメッセージを表示し、ゲームを再開始
                MsgBox "It's a draw!"
                StartGame
            ' それ以外の場合
            Else
                ' コンピューターの手順を実行
                ComputerMove
            End If
        End If
    End If
End Sub

' コンピューターの手順
Sub ComputerMove()
    Dim i As Long
    Dim emptyCells As Collection
    Set emptyCells = New Collection  ' 空のセルを格納するためのコレクションを初期化
    
    ' 人工的な遅延を作成するためのループ(CPUが考えている感じをだすため)
    For i = 1 To 100000000
    Next i
    
    Dim cell As Range
    ' ゲームのグリッド内の空のセルを探索し、コレクションに追加
    For Each cell In Me.Range("B2:D4")
        If IsEmpty(cell.Value) Then
            emptyCells.Add cell
        End If
    Next cell

    ' 空のセルがある場合
    If emptyCells.Count > 0 Then
        Dim randomIndex As Integer
        Randomize  ' ランダム数生成器を初期化
        ' 空のセルの中からランダムに一つ選択
        randomIndex = Int((emptyCells.Count * Rnd) + 1)
        ' 選択されたセルに 'X' を設定
        emptyCells.Item(randomIndex).Value = "X"
        ' 手数を1増やす
        moveCount = moveCount + 1

        ' 勝利条件をチェック
        If CheckWinner("X") Then
            ' 勝利した場合、メッセージボックスで通知し、ゲームを再開始
            MsgBox "X wins!"
            StartGame
        ' 手数が9以上で引き分けの場合
        ElseIf moveCount >= 9 Then
            ' 引き分けのメッセージを表示し、ゲームを再開始
            MsgBox "It's a draw!"
            StartGame
        End If
    End If

    ' 次のプレイヤーを 'O' に設定
    currentPlayer = "O"
End Sub

' ゲームの開始と初期化
Sub StartGame()
    Dim cell As Range
    ' ゲームのグリッド内のセルをリセット
    For Each cell In Me.Range("B2:D4")
        cell.Value = ""  ' セルの値をクリア
        'cell.Interior.Color = xlNone  ' セルの背景色をクリア
    Next cell
    ' 現在のプレイヤーを 'O' に設定
    currentPlayer = "O"
    ' 手数を0にリセット
    moveCount = 0
End Sub

' 勝利条件のチェック
Function CheckWinner(player As String) As Boolean
    ' 勝利しているかどうかの初期状態はFalse
    CheckWinner = False
    ' 各行、各列、または対角線が同じプレイヤーの記号で揃っているかをチェック
    If CheckThree("B2", "B3", "B4", player) Or CheckThree("C2", "C3", "C4", player) Or _
       CheckThree("D2", "D3", "D4", player) Or CheckThree("B2", "C2", "D2", player) Or _
       CheckThree("B3", "C3", "D3", player) Or CheckThree("B4", "C4", "D4", player) Or _
       CheckThree("B2", "C3", "D4", player) Or CheckThree("B4", "C3", "D2", player) Then
        CheckWinner = True  ' いずれかの条件を満たした場合はTrueに設定
    End If
End Function

' 3つのセルが同じプレイヤーの記号かチェック
Function CheckThree(cell1 As String, cell2 As String, cell3 As String, player As String) As Boolean
    ' 指定された3つのセルが同じプレイヤーの記号であればTrue、そうでなければFalseを返す
    CheckThree = (Range(cell1).Value = player And Range(cell2).Value = player And Range(cell3).Value = player)
End Function
'
'

 

●実行前~実行後 ※ユーザーとコンピューターが交互に手を進め、勝利条件を満たすか9手に達すると、勝利者が発表され、ゲームが再開始されます。勝利条件が満たされない場合は引き分けとなります。 なお、今回のプログラムでは、三目並べのコンピュータの手を賢くするため、2つの戦略が用いられます。①コンピュータ(✖)は縦、横、斜めに3つの✖を揃えるため、2つ並んだ✖の列や行、対角線を探し空いているセルに✖を置く。②配置場所がなければ、コンピュータは〇の勝利を阻止し、2つの〇が並んだ場所を見つけてそこに✖を置く。
(画面クリックして拡大)

 

 

 

最後まで、ご覧いただきまして誠に有難うございました。
また、VBAに関するテクニックや便利な手法などをこのサイトに掲載していきますので、定期的に参照していただけると幸いです。

 

AKIRA