C# AlphaBeta修剪不是阻塞,是评估问题吗?
我已经调试了好几天了,我不知道我在这段Tic-Tac-Toe游戏和人工智能的代码中犯了什么错误(我知道这不是真正的人工智能,但…),我选择了Alpha-Beta修剪。它的7x7板,因此对于纯minimax实现来说太重了 我的问题是,我不明白为什么阿尔法-贝塔并没有阻止玩家暂停游戏,等待玩家移动,并使用适当的移动,以利于他,或者只是简单地平局游戏 我已经决定,板的中心将有更多的分数(最终得分)比一个在边缘的董事会。我相信向中间移动的次数比向边缘移动的次数更多,这就是为什么我制作了AddScoreToMove函数来计算移动次数。 为了确保eval功能将检查板上所有可能的移动,我没有使该功能作为find first xxx(例如在row0和col0、col1、col2)和return(因为可能有4X或4O)工作。此外,4X或4O的得分明显高于其他评分,应视为获胜。C# AlphaBeta修剪不是阻塞,是评估问题吗?,c#,vb.net,algorithm,artificial-intelligence,minimax,C#,Vb.net,Algorithm,Artificial Intelligence,Minimax,我已经调试了好几天了,我不知道我在这段Tic-Tac-Toe游戏和人工智能的代码中犯了什么错误(我知道这不是真正的人工智能,但…),我选择了Alpha-Beta修剪。它的7x7板,因此对于纯minimax实现来说太重了 我的问题是,我不明白为什么阿尔法-贝塔并没有阻止玩家暂停游戏,等待玩家移动,并使用适当的移动,以利于他,或者只是简单地平局游戏 我已经决定,板的中心将有更多的分数(最终得分)比一个在边缘的董事会。我相信向中间移动的次数比向边缘移动的次数更多,这就是为什么我制作了AddScoreT
此时此刻,我的PCO球员就这样打球 谁能告诉我我做错了什么?这是我的第二个人工智能程序,第一个是3x3电路板上的minimax,它工作得很好 代码如下 VB.NET代码:
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
Return -10
End If
End If
End If
Next
Next
Dim scoreValues() As Integer = {playerScorerow, playerScorecol, playerScorecross, pcScorerow, pcScorecol, pcScorecross}
Dim max = scoreValues.OrderByDescending(Function(z) Math.Abs(z)).FirstOrDefault()
Return max
End Function
Private Shared Function MiniMax(ByVal board As Char(,), ByVal machineMove As Boolean, ByVal depth As Integer) As Integer
Const alpha As Integer = -10_000
Const beta As Integer = 10_000
Return AlphaBetaPruning(board, machineMove, depth, beta, alpha)
End Function
Private Shared Function AlphaBetaPruning(ByVal board As Char(,), ByVal machineMove As Boolean, ByVal depth As Integer, ByVal beta As Integer, ByVal alpha As Integer) As Integer
If depth = 0 Then Return eval(board)
If machineMove Then 'min PC MOVE
For i As Integer = 0 To 6
For j As Integer = 0 To 6
If board(i, j) = " " Then
board(i, j) = opponent
Dim score As Integer = Math.Min(AlphaBetaPruning(board, Not machineMove, depth - 1, beta, alpha), eval(board))
board(i, j) = " "
If score < beta Then
Form1.BestMoveRow = i
Form1.BestMoveCol = j
Form1.BestMoveScore = score
beta = score
End If
If alpha >= beta Then Exit For 'cutoff
End If
Next
Next
Return beta
Else 'max PLAYER MOVE
For i As Integer = 0 To 6
For j As Integer = 0 To 6
If board(i, j) = " " Then
board(i, j) = player
Dim score As Integer = Math.Max(AlphaBetaPruning(board, Not machineMove, depth - 1, beta, alpha), eval(board))
board(i, j) = " "
If score > alpha Then
alpha = score
End If
If alpha >= beta Then Exit For
End If
Next
Next
Return alpha
End If
End Function
End Class
公共类表单1
将电路板变暗为字符(,)={
{" ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " "}}
阶级运动
公共行,列为整数
末级
Dim BestMoveRow作为整数=0
Dim BestMoveCol作为整数=0
Dim BestMoveScore为整数=0
共享玩家为Char=“X”,对手为Char=“O”
共享函数AddScoreToMove(移动为移动)为整数
将行调整为整数=thatMove.row
Dim col As Integer=thatMove.col
“0分,移动在边界处
如果((行>=1,行=1,行=0,列=0,列=2,列=2,列=beta),则退出“切断”
如果结束
下一个
下一个
返回贝塔
Else的最大玩家移动
对于i,整数=0到6
对于j,作为整数=0到6
如果板(i,j)=“那么
棋盘(i,j)=玩家
整数分数=Math.Max(alphabetaprunning(板,非机器移动,深度-1,beta,alpha),eval(板))
板(i,j)=“
如果分数>α,则
阿尔法=分数
如果结束
如果alpha>=beta,则退出测试
如果结束
下一个
下一个
返回阿尔法
如果结束
端函数
末级
C#代码
公共类表单1
{
私有字符[,]板=新[]{;
阶级运动
{
公共int row,col;
}
private int BestMoveRow=0;
私有int-BestMoveCol=0;
私有int BestMoveScore=0;
私有静态字符播放器=“X”;
私有静态char=“O”;
公共静态int AddScoreToMove(移动即移动)
{
int行=thatMove.row;
int col=thatMove.col;
//0分,移动在边界处
如果(((row>=1&row=1&row=0&col=0&col=2&row=1&col=1&col=2&col=2&col)在又调试了一天之后,我有点不知所措,但我想出了如何绕过它,这可能是这个问题的真正解决方案。
Alpabeta只专注于获胜,这实际上与EVE函数有关,如果我们考虑更多的因子到EVE函数,那么函数就更好了。
这就是为什么我们有
基本获胜因素->这是对赢得比赛的动作的评估
阻挡敌人因素->暂停游戏
还有一个分叉因子我还没有实现。
信息如下:
来自
简而言之,简单的AlphaBeta函数和简单的(仅)获胜评估不考虑比赛时间。
我们必须编写适当的阻塞和分叉函数
Private Shared Function evalBlock(ByVal b As Char(,)) As Move
Dim blockingMove As New Move With {
.row = -1,
.col = -1
}
''row block
For row As Integer = 0 To 4
For col As Integer = 0 To 6
If Not b(row, col) = " " Then
If b(row, col) = b(row + 1, col) Then '2 X or 2 O
If b(row, col) = player Then
If b(row + 2, col) = " " Then
blockingMove.row = row + 2
blockingMove.col = col
Return blockingMove
End If
If row > 0 Then
If b(row - 1, col) = " " Then
blockingMove.row = row - 1
blockingMove.col = col
Return blockingMove
End If
End If
End If
End If
End If
Next
Next
''col block
For row As Integer = 0 To 6
For col As Integer = 0 To 4
If Not b(row, col) = " " Then
If b(row, col) = b(row, col + 1) Then '2 X or 2 O
If b(row, col) = player Then
If b(row, col + 2) = " " Then
blockingMove.row = row
blockingMove.col = col + 2
Return blockingMove
End If
If col > 1 Then
If b(row, col - 1) = " " Then
blockingMove.row = row
blockingMove.col = col - 1
Return blockingMove
End If
End If
End If
End If
End If
Next
Next
'\ cross block
For row As Integer = 0 To 4
For col As Integer = 0 To 4
If Not b(row, col) = " " Then
If (b(row, col) = b(row + 1, col + 1)) Then
If b(row, col) = player Then
If b(row + 2, col + 2) = " " Then
blockingMove.row = row + 2
blockingMove.col = col + 2
End If
If (row > 0 And col > 0) Then
If b(row - 1, col - 1) = " " Then
blockingMove.row = row - 1
blockingMove.col = col - 1
End If
End If
End If
End If
End If
Next
Next
'/ cross block
For row As Integer = 0 To 4
For col As Integer = 2 To 6
If Not b(row, col) = " " Then
If (b(row, col) = b(row + 1, col - 1)) Then
If b(row, col) = player Then
If b(row, col) = " " Then
blockingMove.row = row + 2
blockingMove.col = col - 2
End If
End If
End If
End If
Next
Next
blockingMove.row = -1
blockingMove.col = -1
Return blockingMove
End Function
当然,返回阻挡移动没有任何作用。在AlphaBeta函数中,我们必须为其指定适当的值。因此,我发现我们的AI将阻止玩家进行2次获胜移动,并且阻挡比获胜更可取。另外,在玩家移动2次后阻挡比3次后阻挡更有意义,因为如果我们使用4步获胜的规则
大概是这样的:
Dim score As Integer = Math.Min(AlphaBetaPruning(board, Not machineMove, depth - 1, beta, alpha), eval(board) + depth)
Dim BlockingMove As Move = evalBlock(board)
If BlockingMove.row <> -1 Then
Dim blockingMoveScore As Integer = 5000
If score < blockingMoveScore Then
Form1.BestMoveRow = BlockingMove.row
Form1.BestMoveCol = BlockingMove.col
Form1.BestMoveScore = score
End If
End If
Dim score As Integer=Math.Min(alphabetaprunning(板,非机器移动,深度-1,beta,alpha),eval(板)+深度)
Dim BlockingMove As Move=蒸发锁定(板)
如果阻止move.row-1,则
Dim blockingMoveScore为整数=5000
如果分数
这就是为什么我在第一场AI比赛后就输了。
你应该调试、监控变量,看看哪里出了问题。7x7棋盘的游戏规则是什么?@user3386109在大多数情况下,4O或4X是赢家的规则,但我看到了5的变化。你为什么要将棋盘交给AlphaBeta
Dim score As Integer = Math.Min(AlphaBetaPruning(board, Not machineMove, depth - 1, beta, alpha), eval(board) + depth)
Dim BlockingMove As Move = evalBlock(board)
If BlockingMove.row <> -1 Then
Dim blockingMoveScore As Integer = 5000
If score < blockingMoveScore Then
Form1.BestMoveRow = BlockingMove.row
Form1.BestMoveCol = BlockingMove.col
Form1.BestMoveScore = score
End If
End If