在我第一次尝试极小极大算法和一般的递归调用(我对编程相对较新)时,我已经花了三天时间试图弄清楚我在哪些小代码中出了什么问题。基本上,除了我想在其中实际学习和研究的东西:极小极大算法之外,我的应用程序中的所有东西都在工作。
基本上,每当玩家移动时,计算机将执行以下两项操作之一:
- 如果它旁边有一个获胜的举动,它将使用该举动。非常简单。
- 然而,如果这个动作不是直接可见的,它会选择任何让玩家获胜的动作。与它应该做的完全相反。
我知道它不是来自:
- 合法移动吸气剂
- 板评估器本身,不知道它是否可能来自带有指向它的一些奇怪的东西,但评估器正在返回正确的分数。
这是代码(我删掉了一些启动程序的函数):
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
希望你能帮忙!