2012-02-07 2 views
0

나는 3 일 동안 내 머리카락을 잡아 당겨 미니 맥 알고리즘과 재귀 적 호출 모두에서 처음 시도한 작은 코드에서 무엇이 잘못되었는지 알아 내려고했습니다. 프로그래밍에 비교적 새로운). 기본적으로, 나는 실제로 배워서 작업하고 싶었던 것을 제외하고는 애플리케이션에서 작동하는 모든 것을 가지고있다 : minimax 알고리즘. 플레이어가 이동하게 할 때마다움직임이 직접 시야에있을 때 Minmax 알고리즘 만 승리합니다. 그렇지 않으면 항상 플레이어가이기도록 항상 허락합니다.

기본적으로, 컴퓨터는 두 가지 중 하나를 수행합니다

  • 를 바로 옆에 경력 이동이있는 경우, 그 움직임을 사용합니다. 파이처럼 쉽습니다.
  • 그러나이 이동이 직접적인 시야가 아니라면, 어떤 이동 이 플레이어를 이길 수있게합니다. 정확히 무엇을 해야하는지 반대.

나는에서 오지 않을 것을 알고 :

  • 그것의 포인터와 몇 가지 이상한 것은에서 오는 수있는 경우는 이사회의 평가 자체가 모르는 legalmove 게터
  • 을하지만, 평가자는 올바른 점수를 반환합니다.
  • 여기

코드입니다 (I 시작 프로그램을 얻을 기능의 일부를 잘라) :

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 

당신이 도움이 될 수 있습니다 희망!

+0

15 년 전 VB에서 Reversi를위한 프로그램을 만들었습니다. 그것은 나보다 강했습니다. 남은 시간에 따른 사고의 깊이가 있습니다. 그것은 효과가 있었다. 예, VB는 편리한 도구는 아니지만 질문자가 Objective C로 이동할 때 많은 행복을 가져다 줄 것입니다. 물론, 나는 Word VB 또는 Excel VB에 대해 말하는 것이 아니다. 이것들은 하나님의 형벌입니다. – Gangnus

+0

오류의 원인이되는 부분 만 여기에 두어야합니다. 그리고 당신 자신에 의해 그것을 지역화하십시오. 디버거에서 모든 진드기 게임을 단계별로 진행하는 것은 그리 어렵지 않습니다. 거기에 가장 가까운 오류 – Gangnus

+0

VB.NET 코드가 VB6, 아무 잘못 코딩에 볼 수 있습니다. 컴파일은 C#과 동일합니다. – tcarvin

답변

0

신청서를 분실했습니다. 당신은 깨끗한 프로그래밍의 규칙을 어겼습니다. 그리고 그러한 알고리즘에서, 분기 재귀와 함께, 그 부검은 처벌됩니다. 당신은 질문이 누구의 이동 분석 되나는 걸 알 수 빠져 있습니다.

AI 수준에서 GetComputerBestMove와 같은 기능이 없어야합니다. 프로 그램이 UI 레벨에서만 알 필요가 있으며, 누가 그 움직임을 생각할 것인가. 인공 지능 수준에 관해서는 FindMyBestMove (부울로 측면, AllowedDepth 정수로) 기능이 있어야합니다 그것은 이름이 아닙니다. 이 함수는 적의 이동을 분석 할 때 같은 함수에 반대 값을 전달하는 것을 제외하고는 "side"값을 사용해서는 안됩니다. 일부 게임에서는 첫 번째와 두 번째 플레이어의 전략이 다를 수 있으며, 거기에서 이동 평가에 사용합니다. AllowedDepth는 모든 재귀 단계를 내리고 0에 도달하면 해당 단계에서 재귀를 사용할 수 없습니다. 이 변수를 사용하여 AI 수준을 설정할 수 있습니다.

+0

저는 주로 독창적으로 스타일을 배웁니다. (아주 기본적인 고등학생들이 과학 수업을 듣고 프로그래밍에 들어 갔으며 vb.net의 구문을 가르쳐주었습니다. 클린 프로그래밍의 규칙은 어디에서 읽을 수 있습니까? 그것은 내 funtion의 이름을 Get_Best_Move로 변경하는 것일 뿐입니 까? 내 실제 문제의 주제에 대한 도움을 주셔서 감사합니다. 나는 디버거를 확실히 사용하고 어떤 부분이 무엇을하고 있는지 보게 될 것입니다. 문제의 잠시 동안의 의심이었습니다. 또한, 나는이 게임에 대해 허용 된 깊이를 만들고 싶지 않습니다. – Ropesnake

+0

마지막으로, 어떻게하면 부름을 없앨 수 있습니까? 예를 들어 .owner 할당과 같이 COMPUTER_PIECE로 설정하는 것이 필요하다고 생각합니다. 내가 모르는 전략이 있습니까? – Ropesnake

+0

토마스 헌트 (Thomas, Hunt)의 "pragmacic programmer, journeyman from master"라는 어딘가에서 다운로드를 시도하십시오. 시원한 뉴스를 위해 노력하지 않고 스타일에 매우 좋습니다. – Gangnus

0

코드에 명백한 문제가 나타나지 않지만 (그렇다면 SO에서 실행되지는 않을 것입니다) 반대로 "기본"값을 초기화하는 것으로 의심됩니다. 예를 들어, COMPUTER를 계산할 때, mybest.Score보다 높으면 reply.Score의 값을 받아들이지 만 합리적으로 낮은 초기 값은 2가됩니다. 그러면 반대쪽 시작 값 -2와 반대가됩니다. 견적 코드를 읽지 않았으므로 문제가 될 수 있는지 여부는 알 수 없습니다. 아마도 2의 초기 값은이 경우에는 결코 절대로 모를 것입니까?

+0

아니요, 점수는 컴퓨터 측에서 -2로 설정되어 실제 반환 값으로 덮어 쓰게됩니다. 그게 아니고. – Ropesnake

+0

오른쪽. 제가 당신의 코드를 읽을 때가 밤이었습니다. 내 잘못이야. – kkm

+0

어쨌든 도움 주셔서 고마워요. :) – Ropesnake