今回説明するのは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を使って、三目並べゲームの作成方法を紹介します。基本的なゲームの流れとルールをVBAでどのようにプログラミングしたか、コードとともに解説していきます。このExcel VBAプログラムは、Excelシート上で三目並べ(Tic-Tac-Toe)をプレイするためのシンプルなゲームです。プログラムは、ゲームの状態を追跡するためにグローバル変数(currentPlayer, moveCount)を使用し、ユーザーの操作に基づいてセルの選択、プレイヤーの切り替え、勝利条件のチェックなどを行います。なお、今回のサンプル①のプログラムでは、人間対人間で勝負(ゲーム)する形となります。
【プログラムの流れ】
【プログラム実行条件・注意事項】
★【サンプルプログラム】
下記のリンク先よりサンプルプログラムをダウンロードする事ができます。
● 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
上記のサンプルプログラム①では、人間対人間の三目並べゲームの説明でしたが、今回は、人間対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
'
'
今回のサンプルプログラム③では、サンプル②と同様に人間対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
'
'