0

私は3日間、ミニマックスアルゴリズムと一般的な再帰呼び出し(プログラミングに比較的慣れていない)の両方で最初に試みた小さなコードで何がうまくいかなかったかを理解しようと努力してきました。基本的に、実際に学習して作業したいもの、つまりミニマックスアルゴリズムを除いて、すべてがアプリケーションで機能しています。

基本的に、プレーヤーが移動するたびに、コンピューターは次の2つのいずれかを実行します。

  • そのすぐ隣に勝利の動きがある場合、それはその動きを使用します。やさしい。
  • ただし、この動きが直接見えない場合は、プレーヤーが勝つことができる動きを選択します。それがすべきことの正反対。

私はそれがから来ていないことを知っています:

  • リーガルムーブゲッター
  • ボードエバリュエーター自体は、それがポインターを持った奇妙なものから来ているのかどうかわかりませんが、エバリュエーターは正しいスコアを返しています。

コードは次のとおりです(プログラムを開始する関数の一部を切り取りました):

Public Structure Board
    Public lbl As Label
    Public owner As String
    Public posX As Integer
    Public posY As Integer
End Structure

Public Structure LegalMove
    Public posX As Integer
    Public posY As Integer
End Structure

Public Structure Best
    Public Move As LegalMove
    Public Score As Integer
End Structure

Public Class Form1
    Public Const PLAYER_PIECE As String = "X"
    Public Const COMPUTER_PIECE As String = "O"
    Public Const HUMAN_WIN As Integer = -1
    Public Const COMPUTER_WIN As Integer = 1
    Public Const TIE As Integer = 0
    Public Const COMPUTER As Boolean = True
    Public Const HUMAN As Boolean = False
    Public Game_Ended As Boolean = False
    Public Turn As String = "Human"
    Public Board(2, 2) As Board
    'Sets all objects up (mostly labels, and the board)
Private Sub On_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim intindex As Integer
    Dim intindex2 As Integer
    For intindex = 0 To 2
        For intindex2 = 0 To 2
            Dim Label As New Label
            Label.Name = "lbl" & intindex & intindex2
            Label.AutoSize = False
            Label.TextAlign = ContentAlignment.MiddleCenter
            Label.Font = New Font("Arial", 48, FontStyle.Bold)
            Label.Size = New System.Drawing.Size(100, 100)
            Label.Location = New System.Drawing.Point(intindex * 100, intindex2 * 100)
            Label.BorderStyle = Windows.Forms.BorderStyle.FixedSingle
            Board(intindex, intindex2).lbl = Label
            Board(intindex, intindex2).posX = intindex
            Board(intindex, intindex2).posY = intindex2
            Me.Controls.Add(Label)
            AddHandler Board(intindex, intindex2).lbl.Click, AddressOf Player_Move
        Next
    Next
End Sub
'If a player clicks on one of the labels, it will attmpt to put a player piece on that tile, and direct the game to the computer's turn.
Sub Player_Move(ByVal sender As System.Object, ByVal e As System.EventArgs)
    Dim Current_Board As Board = GetBoard(sender)
    Dim Best As Best
    If Current_Board.owner = Nothing Then
        Board(Current_Board.posX, Current_Board.posY).owner = PLAYER_PIECE
        Board(Current_Board.posX, Current_Board.posY).lbl.Text = PLAYER_PIECE
        Call Check_Board(False, Nothing)
        If Game_Ended = False Then
            Turn = "Computer"
            Best = Get_Computer_Move(COMPUTER)
            Board(Best.Move.posX, Best.Move.posY).owner = COMPUTER_PIECE
            Board(Best.Move.posX, Best.Move.posY).lbl.Text = COMPUTER_PIECE
            Call Check_Board(False, Nothing)
        End If
        Game_Ended = False
        Turn = "Human"
    End If
End Sub

'Checks win/tie conditions. If it is a simulation (for ai), then it will return a number. If it is for legitimate checking, it will call the win function, or tie.
Function Check_Board(ByVal simulation As Boolean, ByVal side As Boolean)
    Dim intindex As Integer
    Dim intindex2 As Integer
    'Vertical Check
    For intindex = 0 To 2
        If Board(intindex, 0).owner = Board(intindex, 1).owner And Board(intindex, 1).owner = Board(intindex, 2).owner And Board(intindex, 0).owner <> Nothing Then
            If simulation = False Then
                Win()
            Else
                If Board(intindex, 0).owner = COMPUTER_PIECE Then
                    Return 1
                Else
                    Return -1
                End If
            End If
        End If
    Next
    'Horizantal Check
    For intindex = 0 To 2
        If Board(0, intindex).owner = Board(1, intindex).owner And Board(1, intindex).owner = Board(2, intindex).owner And Board(0, intindex).owner <> Nothing Then
            If simulation = False Then
                Win()
            Else
                If Board(0, intindex).owner = COMPUTER_PIECE Then
                    Return 1
                Else
                    Return -1
                End If
            End If
        End If
    Next
    'Diagonal Check
    Dim intoppindex As Integer
    Dim intoppindex2 As Integer
    For intindex = 0 To 2 Step 2
        For intindex2 = 0 To 2 Step 2
            If intindex = 0 Then
                intoppindex = 2
            Else
                intoppindex = 0
            End If
            If intindex2 = 0 Then
                intoppindex2 = 2
            Else
                intoppindex2 = 0
            End If
            If Board(intindex, intindex2).owner = Board(1, 1).owner And Board(1, 1).owner = Board(intoppindex, intoppindex2).owner And Board(intindex, intindex2).owner <> Nothing Then
                If simulation = False Then
                    Win()
                Else
                    If Board(1, 1).owner = COMPUTER_PIECE Then
                        Return 1
                    Else
                        Return -1
                    End If
                End If
            End If
        Next
    Next
    'Full Board
    Dim movedcount As Integer
    For intindex = 0 To 2
        For intindex2 = 0 To 2
            If Board(intindex, intindex2).owner <> Nothing Then
                movedcount += 1
            End If
        Next
    Next
    If movedcount = 9 Then
        If simulation = False Then
            MessageBox.Show("It is a tie. Resetting the board.")
            For intindex = 0 To 2
                For intindex2 = 0 To 2
                    Board(intindex, intindex2).owner = Nothing
                    Board(intindex, intindex2).lbl.Text = Nothing
                Next
            Next
            Game_Ended = True
        Else
            Return 0
        End If
    End If
    Return Nothing
End Function

'Allows labels to be processed in to the board
Public Function GetBoard(ByVal sender As Label)
    Dim intindex As Integer
    Dim intindex2 As Integer
    For intindex = 0 To 2
        For intindex2 = 0 To 2
            If Board(intindex, intindex2).lbl.Name = sender.Name Then
                Return Board(intindex, intindex2)
            End If
        Next
    Next
    Return Nothing
End Function

'If a player wins, it will display a message box and reset the board
Sub Win()
    MessageBox.Show(Turn & " has won. Resetting the board.")
    Dim intindex As Integer
    Dim intindex2 As Integer
    For intindex = 0 To 2
        For intindex2 = 0 To 2
            Board(intindex, intindex2).owner = Nothing
            Board(intindex, intindex2).lbl.Text = Nothing
        Next
    Next
    Game_Ended = True
End Sub

'Minmax algorithm that tries to get best possible move by accessing every possible scenario in the game tree. NOT WORKING. Returns a "best" object, that is then used to place the computer's piece.
Public Function Get_Computer_Move(ByVal side As Boolean)
    Dim mybest As New Best
    Dim reply As New Best
    Dim LegalMoveslst As List(Of LegalMove)
    LegalMoveslst = Get_Legal_Moves(Board)

    'This allows to look at other's next move.
    Dim oppside As Boolean
    If side = COMPUTER Then
        oppside = HUMAN
    Else
        oppside = COMPUTER
    End If

    'At lowest end of a given branch (win, loss, or tie), the current score is returned.
    mybest.Score = Check_Board(True, side)
    If mybest.Score <> Nothing Then
        Return mybest
    End If

    'Base values so something is always there.
    If side = COMPUTER Then
        mybest.Score = -2
    Else
        mybest.Score = 2
    End If

    For Each LegalMove In LegalMoveslst
        If side = COMPUTER Then
            Board(LegalMove.posX, LegalMove.posY).owner = COMPUTER_PIECE
        Else
            Board(LegalMove.posX, LegalMove.posY).owner = PLAYER_PIECE
        End If
        reply = Get_Computer_Move(oppside)
        Board(LegalMove.posX, LegalMove.posY).owner = Nothing
        If ((side = COMPUTER And reply.Score > mybest.Score) Or (side = HUMAN And reply.Score < mybest.Score)) Then
            mybest.Move = LegalMove
            mybest.Score = reply.Score
        End If
    Next
    Return mybest
End Function

'Returns potential legal moves on the board
Public Function Get_Legal_Moves(ByVal tempBoard(,) As Board)
    Dim intindex As Integer
    Dim intindex2 As Integer
    Dim legalmoves As New List(Of LegalMove)
    For intindex = 0 To 2
        For intindex2 = 0 To 2
            If tempBoard(intindex, intindex2).owner = Nothing Then
                Dim legalmove As New LegalMove
                legalmove.posX = intindex
                legalmove.posY = intindex2
                legalmoves.Add(legalmove)
            End If
        Next
    Next
    Return legalmoves
End Function
End Class

あなたが助けることができることを願っています!

4

2 に答える 2

0

私はあなたのアプリケーションで迷子になっています。あなたはクリーンなプログラミングのルールを破りました。そして、そのようなアルゴリズムでは、分岐再帰を使用して、その副が罰せられます。明らかに、あなたはその動きが現在分析されている質問に迷いました。

AIレベルでGetComputerBestMoveのような関数があってはなりません。UIレベルでのみ、プログラムは誰が移動中に考えるかを知る必要があります。AIレベルに関しては、関数FindMyBestMove(side as Boolean、AllowedDepth as Integer)が必要です。これは名前ではありません。この関数は、敵の動きを分析するときに同じ関数の反対を渡すことを除いて、他の目的で「side」の値を使用するべきではありません。一部のゲームでは、最初のプレーヤーと2番目のプレーヤーの戦略が異なる場合があり、そこで移動評価に使用します。AllowedDepthは次のようになります-すべての再帰ステップがダウンし、0に達すると、関数はそのステップで再帰を使用できなくなります。この変数を使用して、AIのレベルを設定できます。

于 2012-02-07T09:32:53.467 に答える
0

コードに明らかな問題は見られませんが(ただし、問題が発生した場合は、SOで問題が発生することはありません)、「ベース」値を逆に初期化していると思われます。たとえば、COMPUTERの計算では、の値を受け入れますが、初期値は適度に低いはずreply.Scoreですmybest.Scoreが、2です。これは、反対側の開始値である-2とは対照的です。私はあなたの推定コードを読んでいなかったので、それが問題になるかどうかはわかりません。たぶん、この場合、初期値の2が決して最適化されることはありませんか?

于 2012-02-07T09:42:31.407 に答える