Find winning move in Tic-Tac-Toe with boolean arrays in VBA
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
2
down vote
favorite
I've been trying to mess around with boolean arrays in VBA since I started to try to write an algorithm to solve sudoku puzzles. I thought I'd first try to solve codeabbey tic-tac-toe. I might be reinventing the wheel here, but humor me please.
Goal is to output the winning move number, or 0 if it's a tie.
Here is sample input:
3
7 5 4 1 9 2 8 3 6
5 1 3 7 6 4 2 9 8
5 1 2 8 6 4 7 3 9
answer:
7 6 0
It's set up on a spreadsheet with A1
the number of games and each game as a space-delimited string in the following cells. Not too important, as I just bring it in and then push the end result out (C1
).
That being said, because I'm looking at using this style for another type of puzzle, I think I may have overkilled it - I could probably completely skip CheckWin
and just run all three win scenarios each time, but that would be sort of ridiculous with 81 boxes instead of 9 boxes.
Booleans are always initialized as False
, which will explain the non-result for some functions.
There is
- Main Sub
- Make the Move Sub
- Check for Win (general) Function
- Functions to check horizontal, vertical or diagonal wins
- A Sub to reset my boolean arrays to all False
I'm passing my arrays ByRef
so I can return a single Boolean
result from my functions. Plus they need to persist anyway.
I know, there are a lot of magic numbers and no Constants.
Option Explicit
Public Sub FindTicTacToeWinningMove()
Dim results As String
Dim numberOfGames As Long
Dim index As Long
numberOfGames = Sheet1.Cells(1, 1)
Dim gameNumber As Long
Dim moveNumber As Long
Dim xBoxes(1 To 9) As Boolean
Dim oBoxes(1 To 9) As Boolean
Dim rawMoves As Variant
Dim moves(1 To 9) As String
For gameNumber = 2 To numberOfGames + 1
ClearArrays xBoxes, oBoxes
rawMoves = Split(Sheet1.Cells(gameNumber, 1), " ")
For index = LBound(rawMoves) To UBound(rawMoves)
moves(index + 1) = rawMoves(index)
Next
For moveNumber = 1 To 9
Select Case moveNumber Mod 2
Case 1
If MakeMove(xBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
Case 0
If MakeMove(oBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
End Select
Next
results = results & " " & 0
Win:
Next
Sheet1.Cells(1, 3) = Trim$(results)
End Sub
Private Function MakeMove(ByRef moveArray() As Boolean, ByVal position As Long, ByVal moveNumber As Long) As Boolean
moveArray(position) = True
If moveNumber < 5 Then
MakeMove = False
Exit Function
End If
MakeMove = CheckWin(moveArray, position)
End Function
Private Function CheckWin(ByRef moveArray() As Boolean, ByVal position As Long) As Boolean
Select Case position Mod 3
Case 1
If moveArray(position + 1) Then
If CheckHorizontal(moveArray, position) Then GoTo Win
End If
If position = 7 Then
If moveArray(position - 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
ElseIf moveArray(position + 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
Case 2
If moveArray(position - 1) Then
If CheckHorizontal(moveArray, position) Then GoTo Win
End If
If position = 2 Then
If moveArray(position + 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
ElseIf moveArray(position - 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
Case 0
If moveArray(position - 1) Then
If CheckHorizontal(moveArray, position) Then GoTo Win
End If
If position = 9 Then
If moveArray(position - 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
ElseIf moveArray(position + 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
End Select
If position Mod 2 = 1 Then
If CheckDiagonal(moveArray) Then GoTo Win
End If
Exit Function
Win:
CheckWin = True
End Function
Private Function CheckHorizontal(ByRef moveArray() As Boolean, ByVal position As Long) As Boolean
Select Case position
Case 1, 2, 3
If moveArray(1) And moveArray(2) And moveArray(3) Then CheckHorizontal = True
Case 4, 5, 6
If moveArray(4) And moveArray(5) And moveArray(6) Then CheckHorizontal = True
Case 7, 8, 9
If moveArray(7) And moveArray(8) And moveArray(9) Then CheckHorizontal = True
End Select
End Function
Private Function CheckVertical(ByRef moveArray() As Boolean, ByVal position As Long) As Boolean
Select Case position
Case 1, 4, 7
If moveArray(1) And moveArray(4) And moveArray(7) Then CheckVertical = True
Case 2, 5, 8
If moveArray(2) And moveArray(5) And moveArray(8) Then CheckVertical = True
Case 3, 6, 9
If moveArray(3) And moveArray(6) And moveArray(9) Then CheckVertical = True
End Select
End Function
Private Function CheckDiagonal(ByRef moveArray() As Boolean) As Boolean
If moveArray(5) And moveArray(1) And moveArray(9) Then CheckDiagonal = True
If moveArray(5) And moveArray(3) And moveArray(7) Then CheckDiagonal = True
End Function
Private Sub ClearArrays(ByRef firstArray() As Boolean, ByRef secondArray() As Boolean)
Dim index As Long
For index = 1 To 9
firstArray(index) = False
secondArray(index) = False
Next
End Sub
programming-challenge array vba tic-tac-toe
add a comment |Â
up vote
2
down vote
favorite
I've been trying to mess around with boolean arrays in VBA since I started to try to write an algorithm to solve sudoku puzzles. I thought I'd first try to solve codeabbey tic-tac-toe. I might be reinventing the wheel here, but humor me please.
Goal is to output the winning move number, or 0 if it's a tie.
Here is sample input:
3
7 5 4 1 9 2 8 3 6
5 1 3 7 6 4 2 9 8
5 1 2 8 6 4 7 3 9
answer:
7 6 0
It's set up on a spreadsheet with A1
the number of games and each game as a space-delimited string in the following cells. Not too important, as I just bring it in and then push the end result out (C1
).
That being said, because I'm looking at using this style for another type of puzzle, I think I may have overkilled it - I could probably completely skip CheckWin
and just run all three win scenarios each time, but that would be sort of ridiculous with 81 boxes instead of 9 boxes.
Booleans are always initialized as False
, which will explain the non-result for some functions.
There is
- Main Sub
- Make the Move Sub
- Check for Win (general) Function
- Functions to check horizontal, vertical or diagonal wins
- A Sub to reset my boolean arrays to all False
I'm passing my arrays ByRef
so I can return a single Boolean
result from my functions. Plus they need to persist anyway.
I know, there are a lot of magic numbers and no Constants.
Option Explicit
Public Sub FindTicTacToeWinningMove()
Dim results As String
Dim numberOfGames As Long
Dim index As Long
numberOfGames = Sheet1.Cells(1, 1)
Dim gameNumber As Long
Dim moveNumber As Long
Dim xBoxes(1 To 9) As Boolean
Dim oBoxes(1 To 9) As Boolean
Dim rawMoves As Variant
Dim moves(1 To 9) As String
For gameNumber = 2 To numberOfGames + 1
ClearArrays xBoxes, oBoxes
rawMoves = Split(Sheet1.Cells(gameNumber, 1), " ")
For index = LBound(rawMoves) To UBound(rawMoves)
moves(index + 1) = rawMoves(index)
Next
For moveNumber = 1 To 9
Select Case moveNumber Mod 2
Case 1
If MakeMove(xBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
Case 0
If MakeMove(oBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
End Select
Next
results = results & " " & 0
Win:
Next
Sheet1.Cells(1, 3) = Trim$(results)
End Sub
Private Function MakeMove(ByRef moveArray() As Boolean, ByVal position As Long, ByVal moveNumber As Long) As Boolean
moveArray(position) = True
If moveNumber < 5 Then
MakeMove = False
Exit Function
End If
MakeMove = CheckWin(moveArray, position)
End Function
Private Function CheckWin(ByRef moveArray() As Boolean, ByVal position As Long) As Boolean
Select Case position Mod 3
Case 1
If moveArray(position + 1) Then
If CheckHorizontal(moveArray, position) Then GoTo Win
End If
If position = 7 Then
If moveArray(position - 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
ElseIf moveArray(position + 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
Case 2
If moveArray(position - 1) Then
If CheckHorizontal(moveArray, position) Then GoTo Win
End If
If position = 2 Then
If moveArray(position + 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
ElseIf moveArray(position - 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
Case 0
If moveArray(position - 1) Then
If CheckHorizontal(moveArray, position) Then GoTo Win
End If
If position = 9 Then
If moveArray(position - 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
ElseIf moveArray(position + 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
End Select
If position Mod 2 = 1 Then
If CheckDiagonal(moveArray) Then GoTo Win
End If
Exit Function
Win:
CheckWin = True
End Function
Private Function CheckHorizontal(ByRef moveArray() As Boolean, ByVal position As Long) As Boolean
Select Case position
Case 1, 2, 3
If moveArray(1) And moveArray(2) And moveArray(3) Then CheckHorizontal = True
Case 4, 5, 6
If moveArray(4) And moveArray(5) And moveArray(6) Then CheckHorizontal = True
Case 7, 8, 9
If moveArray(7) And moveArray(8) And moveArray(9) Then CheckHorizontal = True
End Select
End Function
Private Function CheckVertical(ByRef moveArray() As Boolean, ByVal position As Long) As Boolean
Select Case position
Case 1, 4, 7
If moveArray(1) And moveArray(4) And moveArray(7) Then CheckVertical = True
Case 2, 5, 8
If moveArray(2) And moveArray(5) And moveArray(8) Then CheckVertical = True
Case 3, 6, 9
If moveArray(3) And moveArray(6) And moveArray(9) Then CheckVertical = True
End Select
End Function
Private Function CheckDiagonal(ByRef moveArray() As Boolean) As Boolean
If moveArray(5) And moveArray(1) And moveArray(9) Then CheckDiagonal = True
If moveArray(5) And moveArray(3) And moveArray(7) Then CheckDiagonal = True
End Function
Private Sub ClearArrays(ByRef firstArray() As Boolean, ByRef secondArray() As Boolean)
Dim index As Long
For index = 1 To 9
firstArray(index) = False
secondArray(index) = False
Next
End Sub
programming-challenge array vba tic-tac-toe
add a comment |Â
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I've been trying to mess around with boolean arrays in VBA since I started to try to write an algorithm to solve sudoku puzzles. I thought I'd first try to solve codeabbey tic-tac-toe. I might be reinventing the wheel here, but humor me please.
Goal is to output the winning move number, or 0 if it's a tie.
Here is sample input:
3
7 5 4 1 9 2 8 3 6
5 1 3 7 6 4 2 9 8
5 1 2 8 6 4 7 3 9
answer:
7 6 0
It's set up on a spreadsheet with A1
the number of games and each game as a space-delimited string in the following cells. Not too important, as I just bring it in and then push the end result out (C1
).
That being said, because I'm looking at using this style for another type of puzzle, I think I may have overkilled it - I could probably completely skip CheckWin
and just run all three win scenarios each time, but that would be sort of ridiculous with 81 boxes instead of 9 boxes.
Booleans are always initialized as False
, which will explain the non-result for some functions.
There is
- Main Sub
- Make the Move Sub
- Check for Win (general) Function
- Functions to check horizontal, vertical or diagonal wins
- A Sub to reset my boolean arrays to all False
I'm passing my arrays ByRef
so I can return a single Boolean
result from my functions. Plus they need to persist anyway.
I know, there are a lot of magic numbers and no Constants.
Option Explicit
Public Sub FindTicTacToeWinningMove()
Dim results As String
Dim numberOfGames As Long
Dim index As Long
numberOfGames = Sheet1.Cells(1, 1)
Dim gameNumber As Long
Dim moveNumber As Long
Dim xBoxes(1 To 9) As Boolean
Dim oBoxes(1 To 9) As Boolean
Dim rawMoves As Variant
Dim moves(1 To 9) As String
For gameNumber = 2 To numberOfGames + 1
ClearArrays xBoxes, oBoxes
rawMoves = Split(Sheet1.Cells(gameNumber, 1), " ")
For index = LBound(rawMoves) To UBound(rawMoves)
moves(index + 1) = rawMoves(index)
Next
For moveNumber = 1 To 9
Select Case moveNumber Mod 2
Case 1
If MakeMove(xBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
Case 0
If MakeMove(oBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
End Select
Next
results = results & " " & 0
Win:
Next
Sheet1.Cells(1, 3) = Trim$(results)
End Sub
Private Function MakeMove(ByRef moveArray() As Boolean, ByVal position As Long, ByVal moveNumber As Long) As Boolean
moveArray(position) = True
If moveNumber < 5 Then
MakeMove = False
Exit Function
End If
MakeMove = CheckWin(moveArray, position)
End Function
Private Function CheckWin(ByRef moveArray() As Boolean, ByVal position As Long) As Boolean
Select Case position Mod 3
Case 1
If moveArray(position + 1) Then
If CheckHorizontal(moveArray, position) Then GoTo Win
End If
If position = 7 Then
If moveArray(position - 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
ElseIf moveArray(position + 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
Case 2
If moveArray(position - 1) Then
If CheckHorizontal(moveArray, position) Then GoTo Win
End If
If position = 2 Then
If moveArray(position + 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
ElseIf moveArray(position - 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
Case 0
If moveArray(position - 1) Then
If CheckHorizontal(moveArray, position) Then GoTo Win
End If
If position = 9 Then
If moveArray(position - 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
ElseIf moveArray(position + 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
End Select
If position Mod 2 = 1 Then
If CheckDiagonal(moveArray) Then GoTo Win
End If
Exit Function
Win:
CheckWin = True
End Function
Private Function CheckHorizontal(ByRef moveArray() As Boolean, ByVal position As Long) As Boolean
Select Case position
Case 1, 2, 3
If moveArray(1) And moveArray(2) And moveArray(3) Then CheckHorizontal = True
Case 4, 5, 6
If moveArray(4) And moveArray(5) And moveArray(6) Then CheckHorizontal = True
Case 7, 8, 9
If moveArray(7) And moveArray(8) And moveArray(9) Then CheckHorizontal = True
End Select
End Function
Private Function CheckVertical(ByRef moveArray() As Boolean, ByVal position As Long) As Boolean
Select Case position
Case 1, 4, 7
If moveArray(1) And moveArray(4) And moveArray(7) Then CheckVertical = True
Case 2, 5, 8
If moveArray(2) And moveArray(5) And moveArray(8) Then CheckVertical = True
Case 3, 6, 9
If moveArray(3) And moveArray(6) And moveArray(9) Then CheckVertical = True
End Select
End Function
Private Function CheckDiagonal(ByRef moveArray() As Boolean) As Boolean
If moveArray(5) And moveArray(1) And moveArray(9) Then CheckDiagonal = True
If moveArray(5) And moveArray(3) And moveArray(7) Then CheckDiagonal = True
End Function
Private Sub ClearArrays(ByRef firstArray() As Boolean, ByRef secondArray() As Boolean)
Dim index As Long
For index = 1 To 9
firstArray(index) = False
secondArray(index) = False
Next
End Sub
programming-challenge array vba tic-tac-toe
I've been trying to mess around with boolean arrays in VBA since I started to try to write an algorithm to solve sudoku puzzles. I thought I'd first try to solve codeabbey tic-tac-toe. I might be reinventing the wheel here, but humor me please.
Goal is to output the winning move number, or 0 if it's a tie.
Here is sample input:
3
7 5 4 1 9 2 8 3 6
5 1 3 7 6 4 2 9 8
5 1 2 8 6 4 7 3 9
answer:
7 6 0
It's set up on a spreadsheet with A1
the number of games and each game as a space-delimited string in the following cells. Not too important, as I just bring it in and then push the end result out (C1
).
That being said, because I'm looking at using this style for another type of puzzle, I think I may have overkilled it - I could probably completely skip CheckWin
and just run all three win scenarios each time, but that would be sort of ridiculous with 81 boxes instead of 9 boxes.
Booleans are always initialized as False
, which will explain the non-result for some functions.
There is
- Main Sub
- Make the Move Sub
- Check for Win (general) Function
- Functions to check horizontal, vertical or diagonal wins
- A Sub to reset my boolean arrays to all False
I'm passing my arrays ByRef
so I can return a single Boolean
result from my functions. Plus they need to persist anyway.
I know, there are a lot of magic numbers and no Constants.
Option Explicit
Public Sub FindTicTacToeWinningMove()
Dim results As String
Dim numberOfGames As Long
Dim index As Long
numberOfGames = Sheet1.Cells(1, 1)
Dim gameNumber As Long
Dim moveNumber As Long
Dim xBoxes(1 To 9) As Boolean
Dim oBoxes(1 To 9) As Boolean
Dim rawMoves As Variant
Dim moves(1 To 9) As String
For gameNumber = 2 To numberOfGames + 1
ClearArrays xBoxes, oBoxes
rawMoves = Split(Sheet1.Cells(gameNumber, 1), " ")
For index = LBound(rawMoves) To UBound(rawMoves)
moves(index + 1) = rawMoves(index)
Next
For moveNumber = 1 To 9
Select Case moveNumber Mod 2
Case 1
If MakeMove(xBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
Case 0
If MakeMove(oBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
End Select
Next
results = results & " " & 0
Win:
Next
Sheet1.Cells(1, 3) = Trim$(results)
End Sub
Private Function MakeMove(ByRef moveArray() As Boolean, ByVal position As Long, ByVal moveNumber As Long) As Boolean
moveArray(position) = True
If moveNumber < 5 Then
MakeMove = False
Exit Function
End If
MakeMove = CheckWin(moveArray, position)
End Function
Private Function CheckWin(ByRef moveArray() As Boolean, ByVal position As Long) As Boolean
Select Case position Mod 3
Case 1
If moveArray(position + 1) Then
If CheckHorizontal(moveArray, position) Then GoTo Win
End If
If position = 7 Then
If moveArray(position - 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
ElseIf moveArray(position + 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
Case 2
If moveArray(position - 1) Then
If CheckHorizontal(moveArray, position) Then GoTo Win
End If
If position = 2 Then
If moveArray(position + 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
ElseIf moveArray(position - 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
Case 0
If moveArray(position - 1) Then
If CheckHorizontal(moveArray, position) Then GoTo Win
End If
If position = 9 Then
If moveArray(position - 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
ElseIf moveArray(position + 3) Then
If CheckVertical(moveArray, position) Then GoTo Win
End If
End Select
If position Mod 2 = 1 Then
If CheckDiagonal(moveArray) Then GoTo Win
End If
Exit Function
Win:
CheckWin = True
End Function
Private Function CheckHorizontal(ByRef moveArray() As Boolean, ByVal position As Long) As Boolean
Select Case position
Case 1, 2, 3
If moveArray(1) And moveArray(2) And moveArray(3) Then CheckHorizontal = True
Case 4, 5, 6
If moveArray(4) And moveArray(5) And moveArray(6) Then CheckHorizontal = True
Case 7, 8, 9
If moveArray(7) And moveArray(8) And moveArray(9) Then CheckHorizontal = True
End Select
End Function
Private Function CheckVertical(ByRef moveArray() As Boolean, ByVal position As Long) As Boolean
Select Case position
Case 1, 4, 7
If moveArray(1) And moveArray(4) And moveArray(7) Then CheckVertical = True
Case 2, 5, 8
If moveArray(2) And moveArray(5) And moveArray(8) Then CheckVertical = True
Case 3, 6, 9
If moveArray(3) And moveArray(6) And moveArray(9) Then CheckVertical = True
End Select
End Function
Private Function CheckDiagonal(ByRef moveArray() As Boolean) As Boolean
If moveArray(5) And moveArray(1) And moveArray(9) Then CheckDiagonal = True
If moveArray(5) And moveArray(3) And moveArray(7) Then CheckDiagonal = True
End Function
Private Sub ClearArrays(ByRef firstArray() As Boolean, ByRef secondArray() As Boolean)
Dim index As Long
For index = 1 To 9
firstArray(index) = False
secondArray(index) = False
Next
End Sub
programming-challenge array vba tic-tac-toe
edited Mar 1 at 1:50
200_success
123k14142399
123k14142399
asked Mar 1 at 1:38
Raystafarian
5,4781046
5,4781046
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
Excellent job on this coding challenge.
ClearArrays: Subroutine
This Subroutine isn't needed. Use the built in VBA Erase
method instead.
Erase xBoxes
Erase oBoxes
FindTicTacToeWinningMove: Subroutine
As a personal preference, I would have just used 0 based Arrays.
rawMoves = Split(Sheet1.Cells(gameNumber, 1), " ")
For index = LBound(rawMoves) To UBound(rawMoves)
moves(index + 1) = rawMoves(index)
Next
In the next code blocK I would:
Replace the
Select Case
with anIf Else
statement.Select Case
statements are pretty lengthy to use for just 2 cases.GoTo
statements should be avoided unless writing an Error Handler. You could replaceGoTo Win
withExit For
. The trick is to take advantage of how aFor Next
loop works. AfterNext
the counter is incremented and the exit condition is checked. If the counter is greater than the exit condition then the loop exits. IfFor moveNumber = 1 To 9
runs uninterrupted thenmoveNumber = 10
after the loop is complete elsemoveNumber
will equal between 1 and 9 depending on whenExit For
was executed.
For moveNumber = 1 To 9
Select Case moveNumber Mod 2
Case 1
If MakeMove(xBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
Case 0
If MakeMove(oBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
End Select
Next
I more condensed way to write the code above is as follows:
For moveNumber = 1 To 9
If moveNumber Mod 2 Then
If MakeMove(xBoxes, moves(moveNumber), moveNumber) Then Exit For
Else
If MakeMove(oBoxes, moves(moveNumber), moveNumber) Then Exit For
End If
Next
results = results & " " & IIf(moveNumber = 10, 0, moveNumber)
Of course we could condense it further but this looks a like ridiculous:
For moveNumber = 1 To 9
If MakeMove(IIf(CBool(moveNumber Mod 2), xBoxes, oBoxes), moves(moveNumber), moveNumber) Then Exit For
Next
results = results & " " & IIf(moveNumber = 10, 0, moveNumber)
MakeMove: Function
It is best practice to have Boolean Functions sound like a question (e.g. isWin, hasWon, isGameOver). Following this rule, you should call MakeMove
and CheckWin
separately. That being said, I seen plenty of game code that had Move
return a Boolean.
CheckWin, CheckHorizontal, CheckDiagonal
CheckWin
is over complicated. There is no reason to try and optimize the codes performance. There are only 8 sets of 3 positions in the array to test.
Private Function hasWon(ByRef moveArray() As Boolean) As Boolean
Dim sequence As Variant
Dim a As Long, b As Long, c As Long
For Each sequence In Array(Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9), _
Array(1, 4, 7), Array(2, 5, 8), Array(3, 6, 9), _
Array(5, 1, 9), Array(5, 3, 7))
hasWon = moveArray(sequence(0)) * moveArray(sequence(1)) * moveArray(sequence(2))
If hasWon Then Exit Function
Next
End Function
Note: The result of multiplying the 3 positions in the Boolean Array together will be 0 if any of the conditions are False and non-zero if all conditions are True. This is how Boolean logic works. Alternatively, I could have just used And
instead of *
.
All good advice. I couldn't think ofClear
- I kept coming back to VB.NET functions. That's something I definitely overlooked.
â Raystafarian
Mar 1 at 21:55
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
Excellent job on this coding challenge.
ClearArrays: Subroutine
This Subroutine isn't needed. Use the built in VBA Erase
method instead.
Erase xBoxes
Erase oBoxes
FindTicTacToeWinningMove: Subroutine
As a personal preference, I would have just used 0 based Arrays.
rawMoves = Split(Sheet1.Cells(gameNumber, 1), " ")
For index = LBound(rawMoves) To UBound(rawMoves)
moves(index + 1) = rawMoves(index)
Next
In the next code blocK I would:
Replace the
Select Case
with anIf Else
statement.Select Case
statements are pretty lengthy to use for just 2 cases.GoTo
statements should be avoided unless writing an Error Handler. You could replaceGoTo Win
withExit For
. The trick is to take advantage of how aFor Next
loop works. AfterNext
the counter is incremented and the exit condition is checked. If the counter is greater than the exit condition then the loop exits. IfFor moveNumber = 1 To 9
runs uninterrupted thenmoveNumber = 10
after the loop is complete elsemoveNumber
will equal between 1 and 9 depending on whenExit For
was executed.
For moveNumber = 1 To 9
Select Case moveNumber Mod 2
Case 1
If MakeMove(xBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
Case 0
If MakeMove(oBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
End Select
Next
I more condensed way to write the code above is as follows:
For moveNumber = 1 To 9
If moveNumber Mod 2 Then
If MakeMove(xBoxes, moves(moveNumber), moveNumber) Then Exit For
Else
If MakeMove(oBoxes, moves(moveNumber), moveNumber) Then Exit For
End If
Next
results = results & " " & IIf(moveNumber = 10, 0, moveNumber)
Of course we could condense it further but this looks a like ridiculous:
For moveNumber = 1 To 9
If MakeMove(IIf(CBool(moveNumber Mod 2), xBoxes, oBoxes), moves(moveNumber), moveNumber) Then Exit For
Next
results = results & " " & IIf(moveNumber = 10, 0, moveNumber)
MakeMove: Function
It is best practice to have Boolean Functions sound like a question (e.g. isWin, hasWon, isGameOver). Following this rule, you should call MakeMove
and CheckWin
separately. That being said, I seen plenty of game code that had Move
return a Boolean.
CheckWin, CheckHorizontal, CheckDiagonal
CheckWin
is over complicated. There is no reason to try and optimize the codes performance. There are only 8 sets of 3 positions in the array to test.
Private Function hasWon(ByRef moveArray() As Boolean) As Boolean
Dim sequence As Variant
Dim a As Long, b As Long, c As Long
For Each sequence In Array(Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9), _
Array(1, 4, 7), Array(2, 5, 8), Array(3, 6, 9), _
Array(5, 1, 9), Array(5, 3, 7))
hasWon = moveArray(sequence(0)) * moveArray(sequence(1)) * moveArray(sequence(2))
If hasWon Then Exit Function
Next
End Function
Note: The result of multiplying the 3 positions in the Boolean Array together will be 0 if any of the conditions are False and non-zero if all conditions are True. This is how Boolean logic works. Alternatively, I could have just used And
instead of *
.
All good advice. I couldn't think ofClear
- I kept coming back to VB.NET functions. That's something I definitely overlooked.
â Raystafarian
Mar 1 at 21:55
add a comment |Â
up vote
2
down vote
accepted
Excellent job on this coding challenge.
ClearArrays: Subroutine
This Subroutine isn't needed. Use the built in VBA Erase
method instead.
Erase xBoxes
Erase oBoxes
FindTicTacToeWinningMove: Subroutine
As a personal preference, I would have just used 0 based Arrays.
rawMoves = Split(Sheet1.Cells(gameNumber, 1), " ")
For index = LBound(rawMoves) To UBound(rawMoves)
moves(index + 1) = rawMoves(index)
Next
In the next code blocK I would:
Replace the
Select Case
with anIf Else
statement.Select Case
statements are pretty lengthy to use for just 2 cases.GoTo
statements should be avoided unless writing an Error Handler. You could replaceGoTo Win
withExit For
. The trick is to take advantage of how aFor Next
loop works. AfterNext
the counter is incremented and the exit condition is checked. If the counter is greater than the exit condition then the loop exits. IfFor moveNumber = 1 To 9
runs uninterrupted thenmoveNumber = 10
after the loop is complete elsemoveNumber
will equal between 1 and 9 depending on whenExit For
was executed.
For moveNumber = 1 To 9
Select Case moveNumber Mod 2
Case 1
If MakeMove(xBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
Case 0
If MakeMove(oBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
End Select
Next
I more condensed way to write the code above is as follows:
For moveNumber = 1 To 9
If moveNumber Mod 2 Then
If MakeMove(xBoxes, moves(moveNumber), moveNumber) Then Exit For
Else
If MakeMove(oBoxes, moves(moveNumber), moveNumber) Then Exit For
End If
Next
results = results & " " & IIf(moveNumber = 10, 0, moveNumber)
Of course we could condense it further but this looks a like ridiculous:
For moveNumber = 1 To 9
If MakeMove(IIf(CBool(moveNumber Mod 2), xBoxes, oBoxes), moves(moveNumber), moveNumber) Then Exit For
Next
results = results & " " & IIf(moveNumber = 10, 0, moveNumber)
MakeMove: Function
It is best practice to have Boolean Functions sound like a question (e.g. isWin, hasWon, isGameOver). Following this rule, you should call MakeMove
and CheckWin
separately. That being said, I seen plenty of game code that had Move
return a Boolean.
CheckWin, CheckHorizontal, CheckDiagonal
CheckWin
is over complicated. There is no reason to try and optimize the codes performance. There are only 8 sets of 3 positions in the array to test.
Private Function hasWon(ByRef moveArray() As Boolean) As Boolean
Dim sequence As Variant
Dim a As Long, b As Long, c As Long
For Each sequence In Array(Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9), _
Array(1, 4, 7), Array(2, 5, 8), Array(3, 6, 9), _
Array(5, 1, 9), Array(5, 3, 7))
hasWon = moveArray(sequence(0)) * moveArray(sequence(1)) * moveArray(sequence(2))
If hasWon Then Exit Function
Next
End Function
Note: The result of multiplying the 3 positions in the Boolean Array together will be 0 if any of the conditions are False and non-zero if all conditions are True. This is how Boolean logic works. Alternatively, I could have just used And
instead of *
.
All good advice. I couldn't think ofClear
- I kept coming back to VB.NET functions. That's something I definitely overlooked.
â Raystafarian
Mar 1 at 21:55
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
Excellent job on this coding challenge.
ClearArrays: Subroutine
This Subroutine isn't needed. Use the built in VBA Erase
method instead.
Erase xBoxes
Erase oBoxes
FindTicTacToeWinningMove: Subroutine
As a personal preference, I would have just used 0 based Arrays.
rawMoves = Split(Sheet1.Cells(gameNumber, 1), " ")
For index = LBound(rawMoves) To UBound(rawMoves)
moves(index + 1) = rawMoves(index)
Next
In the next code blocK I would:
Replace the
Select Case
with anIf Else
statement.Select Case
statements are pretty lengthy to use for just 2 cases.GoTo
statements should be avoided unless writing an Error Handler. You could replaceGoTo Win
withExit For
. The trick is to take advantage of how aFor Next
loop works. AfterNext
the counter is incremented and the exit condition is checked. If the counter is greater than the exit condition then the loop exits. IfFor moveNumber = 1 To 9
runs uninterrupted thenmoveNumber = 10
after the loop is complete elsemoveNumber
will equal between 1 and 9 depending on whenExit For
was executed.
For moveNumber = 1 To 9
Select Case moveNumber Mod 2
Case 1
If MakeMove(xBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
Case 0
If MakeMove(oBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
End Select
Next
I more condensed way to write the code above is as follows:
For moveNumber = 1 To 9
If moveNumber Mod 2 Then
If MakeMove(xBoxes, moves(moveNumber), moveNumber) Then Exit For
Else
If MakeMove(oBoxes, moves(moveNumber), moveNumber) Then Exit For
End If
Next
results = results & " " & IIf(moveNumber = 10, 0, moveNumber)
Of course we could condense it further but this looks a like ridiculous:
For moveNumber = 1 To 9
If MakeMove(IIf(CBool(moveNumber Mod 2), xBoxes, oBoxes), moves(moveNumber), moveNumber) Then Exit For
Next
results = results & " " & IIf(moveNumber = 10, 0, moveNumber)
MakeMove: Function
It is best practice to have Boolean Functions sound like a question (e.g. isWin, hasWon, isGameOver). Following this rule, you should call MakeMove
and CheckWin
separately. That being said, I seen plenty of game code that had Move
return a Boolean.
CheckWin, CheckHorizontal, CheckDiagonal
CheckWin
is over complicated. There is no reason to try and optimize the codes performance. There are only 8 sets of 3 positions in the array to test.
Private Function hasWon(ByRef moveArray() As Boolean) As Boolean
Dim sequence As Variant
Dim a As Long, b As Long, c As Long
For Each sequence In Array(Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9), _
Array(1, 4, 7), Array(2, 5, 8), Array(3, 6, 9), _
Array(5, 1, 9), Array(5, 3, 7))
hasWon = moveArray(sequence(0)) * moveArray(sequence(1)) * moveArray(sequence(2))
If hasWon Then Exit Function
Next
End Function
Note: The result of multiplying the 3 positions in the Boolean Array together will be 0 if any of the conditions are False and non-zero if all conditions are True. This is how Boolean logic works. Alternatively, I could have just used And
instead of *
.
Excellent job on this coding challenge.
ClearArrays: Subroutine
This Subroutine isn't needed. Use the built in VBA Erase
method instead.
Erase xBoxes
Erase oBoxes
FindTicTacToeWinningMove: Subroutine
As a personal preference, I would have just used 0 based Arrays.
rawMoves = Split(Sheet1.Cells(gameNumber, 1), " ")
For index = LBound(rawMoves) To UBound(rawMoves)
moves(index + 1) = rawMoves(index)
Next
In the next code blocK I would:
Replace the
Select Case
with anIf Else
statement.Select Case
statements are pretty lengthy to use for just 2 cases.GoTo
statements should be avoided unless writing an Error Handler. You could replaceGoTo Win
withExit For
. The trick is to take advantage of how aFor Next
loop works. AfterNext
the counter is incremented and the exit condition is checked. If the counter is greater than the exit condition then the loop exits. IfFor moveNumber = 1 To 9
runs uninterrupted thenmoveNumber = 10
after the loop is complete elsemoveNumber
will equal between 1 and 9 depending on whenExit For
was executed.
For moveNumber = 1 To 9
Select Case moveNumber Mod 2
Case 1
If MakeMove(xBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
Case 0
If MakeMove(oBoxes, moves(moveNumber), moveNumber) Then
results = results & " " & moveNumber
GoTo Win
End If
End Select
Next
I more condensed way to write the code above is as follows:
For moveNumber = 1 To 9
If moveNumber Mod 2 Then
If MakeMove(xBoxes, moves(moveNumber), moveNumber) Then Exit For
Else
If MakeMove(oBoxes, moves(moveNumber), moveNumber) Then Exit For
End If
Next
results = results & " " & IIf(moveNumber = 10, 0, moveNumber)
Of course we could condense it further but this looks a like ridiculous:
For moveNumber = 1 To 9
If MakeMove(IIf(CBool(moveNumber Mod 2), xBoxes, oBoxes), moves(moveNumber), moveNumber) Then Exit For
Next
results = results & " " & IIf(moveNumber = 10, 0, moveNumber)
MakeMove: Function
It is best practice to have Boolean Functions sound like a question (e.g. isWin, hasWon, isGameOver). Following this rule, you should call MakeMove
and CheckWin
separately. That being said, I seen plenty of game code that had Move
return a Boolean.
CheckWin, CheckHorizontal, CheckDiagonal
CheckWin
is over complicated. There is no reason to try and optimize the codes performance. There are only 8 sets of 3 positions in the array to test.
Private Function hasWon(ByRef moveArray() As Boolean) As Boolean
Dim sequence As Variant
Dim a As Long, b As Long, c As Long
For Each sequence In Array(Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9), _
Array(1, 4, 7), Array(2, 5, 8), Array(3, 6, 9), _
Array(5, 1, 9), Array(5, 3, 7))
hasWon = moveArray(sequence(0)) * moveArray(sequence(1)) * moveArray(sequence(2))
If hasWon Then Exit Function
Next
End Function
Note: The result of multiplying the 3 positions in the Boolean Array together will be 0 if any of the conditions are False and non-zero if all conditions are True. This is how Boolean logic works. Alternatively, I could have just used And
instead of *
.
answered Mar 1 at 6:49
user109261
All good advice. I couldn't think ofClear
- I kept coming back to VB.NET functions. That's something I definitely overlooked.
â Raystafarian
Mar 1 at 21:55
add a comment |Â
All good advice. I couldn't think ofClear
- I kept coming back to VB.NET functions. That's something I definitely overlooked.
â Raystafarian
Mar 1 at 21:55
All good advice. I couldn't think of
Clear
- I kept coming back to VB.NET functions. That's something I definitely overlooked.â Raystafarian
Mar 1 at 21:55
All good advice. I couldn't think of
Clear
- I kept coming back to VB.NET functions. That's something I definitely overlooked.â Raystafarian
Mar 1 at 21:55
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188578%2ffind-winning-move-in-tic-tac-toe-with-boolean-arrays-in-vba%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password