I'm debuging this for days and i don't know what I made wrong in this piece of code for Tic-Tac-Toe game and AI (well I know its not real AI but...) I have choosen for this was Alpha-Beta pruning. Its 7x7 board so it would be too heavy for pure minimax implementation.
Problem I have is that i can't figure out why Alpha-Beta is not blocking player to stall the game and wait for player move and use proper move in his favour, or just simply tie the game.
I've decided that center of board will have more points(for end score) than the one at the edges of the board. I belive that moves more to the center will have more chance to success than the ones in the edges, thats why i made AddScoreToMove function that evaluates that move.
To Ensure that eval function will check EVERY possible moves at board I didn't made that function to work as find first xxx (for example at row0 and col0,col1,col2) and return (cause maybe there is 4X's or 4O's). Also 4X or 4O gives substantially more score than other ones and should be considered as win.
At this moment my PCplayer( O's) play like this
Can anyone tell me what i made wrong? It's my second program with AI, and first was with minimax on 3x3 board whitch worked fine.
C# code is below
VB.NET CODE:
Public Class Form1
Dim board As Char(,) = {
{" ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " "}}
Class Move
Public row, col As Integer
End Class
Dim BestMoveRow As Integer = 0
Dim BestMoveCol As Integer = 0
Dim BestMoveScore As Integer = 0
Shared player As Char = "X", opponent As Char = "O"
Shared Function AddScoreToMove(thatMove As Move) As Integer
Dim row As Integer = thatMove.row
Dim col As Integer = thatMove.col
'0 score, move is at border
If ((row >= 1 And row <= 5) And col = 0) Then
Return 0
ElseIf ((row >= 1 And row <= 5) And col = 6) Then
Return 0
ElseIf (row = 0 And (col >= 0 And col <= 6)) Then
Return 0
ElseIf (row = 6 And (col >= 0 And col <= 6)) Then
Return 0
End If
'1 score, thatMove is at border +1
If ((row >= 2 And row <= 4) And col = 1) Then
Return 1
ElseIf ((row >= 2 And row <= 4) And col = 5) Then
Return 1
ElseIf (row = 1 And (col >= 1 And col <= 5)) Then
Return 1
ElseIf (row = 5 And (col >= 1 And col <= 5)) Then
Return 1
End If
'2 score, thatMove is at border +2
If (row = 2 And col = 2) Then
Return 2
ElseIf (row = 2 And col = 4) Then
Return 2
ElseIf (row = 2 And (col >= 2 And col <= 4)) Then
Return 2
ElseIf (row = 4 And (col >= 2 And col <= 4)) Then
Return 2
End If
'3 Center thatMove
If (row = 3 And col <= 3) Then
Return 3
End If
Return 0 'error not added lane
End Function
Private Shared Function eval(ByVal b As Char(,)) As Integer
Dim playerScorerow As Integer = 0
Dim playerScorecol As Integer = 0
Dim playerScorecross As Integer = 0
Dim pcScorerow As Integer = 0
Dim pcScorecol As Integer = 0
Dim pcScorecross As Integer = 0
''EVALUATE rows
For row As Integer = 0 To 3
For col As Integer = 0 To 6
'initialize moves to evaluate
Dim move3 As New Move With {
.row = row + 3,
.col = col
}
Dim move2 As New Move With {
.row = row + 2,
.col = col
}
Dim move1 As New Move With {
.row = row + 1,
.col = col
}
Dim move0 As New Move With {
.row = row,
.col = col
}
If Not b(row, col) = " " Then 'ITS NOT EMPTY - PLAYER OR PC MOVED HERE
Dim moveScore As Integer = AddScoreToMove(move0) 'EVALUATE THAT MOVE
If b(row, col) = b(row + 1, col) Then 'THERE IS 2 X or 2 O
Dim move1Score As Integer = AddScoreToMove(move1)
If b(row + 1, col) = b(row + 2, col) Then 'THERE IS 3x or 3O
Dim move2Score As Integer = AddScoreToMove(move2)
If b(row + 2, col) = b(row + 3, col) Then 'THERE IS 4X or 4O
Dim move3Score As Integer = AddScoreToMove(move3)
If b(row, col) = player Then 'PLAYER HAVE 4X HERE
playerScorerow = Math.Max(playerScorerow, 100 + move3Score + move2Score + move1Score + moveScore) 'GET HIGHEST OF ALL EVALUATIONS OF THAT FOR LOOPS
ElseIf b(row, col) = opponent Then 'PC HAVE 4O HERE
pcScorerow = Math.Min(pcScorerow, -100 - move3Score - move2Score - move1Score - moveScore)
End If
End If
If b(row, col) = player Then
playerScorerow = Math.Max(playerScorerow, 5 + move2Score + move1Score + moveScore)
ElseIf b(row, col) = opponent Then
pcScorerow = Math.Min(pcScorerow, -5 - move2Score - move1Score - moveScore)
End If
End If
If b(row, col) = player Then
playerScorerow = Math.Max(playerScorerow, 2 + move1Score + moveScore)
ElseIf b(row, col) = opponent Then
pcScorerow = Math.Min(pcScorerow, -2 - move1Score - moveScore)
End If
End If
If b(row, col) = player Then
playerScorerow = Math.Max(playerScorerow, moveScore)
ElseIf b(row, col) = opponent Then
pcScorerow = Math.Min(pcScorerow, -moveScore)
End If
End If
Next
Next
''col win
For row As Integer = 0 To 6
For col As Integer = 0 To 3
Dim move3 As New Move With {
.row = row + 3,
.col = col
}
Dim move2 As New Move With {
.row = row + 2,
.col = col
}
Dim move1 As New Move With {
.row = row + 1,
.col = col
}
Dim move0 As New Move With {
.row = row,
.col = col
}
If Not b(row, col) = " " Then
Dim moveScore As Integer = AddScoreToMove(move0)
If b(row, col) = b(row, col + 1) Then
Dim moveScore1 As Integer = AddScoreToMove(move1)
If b(row, col + 1) = b(row, col + 2) Then
Dim moveScore2 As Integer = AddScoreToMove(move2)
If b(row, col + 2) = b(row, col + 3) Then
Dim moveScore3 As Integer = AddScoreToMove(move3)
If b(row, col) = player Then
playerScorerow = Math.Max(playerScorerow, 100 + moveScore3 + moveScore2 + moveScore1 + moveScore)
ElseIf b(row, col) = opponent Then
pcScorerow = Math.Min(pcScorerow, -100 - moveScore3 - moveScore2 - moveScore1 - moveScore)
End If
End If
If b(row, col) = player Then
playerScorerow = Math.Max(playerScorerow, 5 + moveScore2 + moveScore1 + moveScore)
ElseIf b(row, col) = opponent Then
pcScorerow = Math.Min(pcScorerow, -5 - moveScore2 - moveScore1 - moveScore)
End If
End If
If b(row, col) = player Then
playerScorerow = Math.Max(playerScorerow, 2 + moveScore1 + moveScore)
ElseIf b(row, col) = opponent Then
pcScorerow = Math.Min(pcScorerow, -2 - moveScore1 - moveScore)
End If
End If
If b(row, col) = player Then
playerScorerow = Math.Max(playerScorerow, moveScore)
ElseIf b(row, col) = opponent Then
pcScorerow = Math.Min(pcScorerow, -moveScore)
End If
End If
Next
Next
'NOT FULLY IMPLEMENTED
'cross win
For row As Integer = 0 To 3
For col As Integer = 0 To 3
If Not b(row, col) = " " Then
If (b(row, col) = b(row + 1, col + 1) AndAlso b(row + 1, col + 1) = b(row + 2, col + 2) AndAlso b(row + 2, col + 2) = b(row + 3, col + 3)) Then
If b(row, col) = player Then
Return +10
ElseIf b(row, col) = opponent Then
Return -10
End If
End If
End If
Next
Next
'NOT FULLY IMPLEMENTED
'cross win
For row As Integer = 0 To 3
For col As Integer = 3 To 6
If Not b(row, col) = " " Then
If (b(row, col) = b(row + 1, col - 1) AndAlso b(row + 1, col - 1) = b(row + 2, col - 2) AndAlso b(row + 2, col - 2) = b(row + 3, col - 3)) Then
If b(row, col) = player Then
Return +10
ElseIf b(row, col) = opponent Then