C# AlphaBeta修剪不是阻塞,是评估问题吗?

C# AlphaBeta修剪不是阻塞,是评估问题吗?,c#,vb.net,algorithm,artificial-intelligence,minimax,C#,Vb.net,Algorithm,Artificial Intelligence,Minimax,我已经调试了好几天了,我不知道我在这段Tic-Tac-Toe游戏和人工智能的代码中犯了什么错误(我知道这不是真正的人工智能,但…),我选择了Alpha-Beta修剪。它的7x7板,因此对于纯minimax实现来说太重了 我的问题是,我不明白为什么阿尔法-贝塔并没有阻止玩家暂停游戏,等待玩家移动,并使用适当的移动,以利于他,或者只是简单地平局游戏 我已经决定,板的中心将有更多的分数(最终得分)比一个在边缘的董事会。我相信向中间移动的次数比向边缘移动的次数更多,这就是为什么我制作了AddScoreT

我已经调试了好几天了,我不知道我在这段Tic-Tac-Toe游戏和人工智能的代码中犯了什么错误(我知道这不是真正的人工智能,但…),我选择了Alpha-Beta修剪。它的7x7板,因此对于纯minimax实现来说太重了

我的问题是,我不明白为什么阿尔法-贝塔并没有阻止玩家暂停游戏,等待玩家移动,并使用适当的移动,以利于他,或者只是简单地平局游戏

我已经决定,板的中心将有更多的分数(最终得分)比一个在边缘的董事会。我相信向中间移动的次数比向边缘移动的次数更多,这就是为什么我制作了AddScoreToMove函数来计算移动次数。 为了确保eval功能将检查板上所有可能的移动,我没有使该功能作为find first xxx(例如在row0和col0、col1、col2)和return(因为可能有4X或4O)工作。此外,4X或4O的得分明显高于其他评分,应视为获胜。
此时此刻,我的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