【问题标题】:Py-Game Connect4 - Minimax (Program Halting Recursively)Py-Game Connect4 - Minimax(递归程序停止)
【发布时间】:2021-04-09 04:27:33
【问题描述】:

main.py

from Player import Player

import tkinter as tk
import pygame
import pygame_menu
import time
import colors
import Connect4 as cFour
import Minimax as mx


def text_format(option, textSize, textColor):
    """
    Creates a text object to show in the main menu
    """
    newFont = pygame.font.Font(pygame_menu.font.FONT_FRANCHISE, textSize)
    newText = newFont.render(option, 0, textColor)
    return newText

def load_screen():
    """
    This initializes the window for pygame to use
    """
    screen = pygame.display.set_mode((600, 600))
    pygame.display.set_caption("Connect4")
    return screen

def get_player_details(screen):
    """
    Creates a tkinter object(button) that gets players names
    """
    root = tk.Tk()
    root.title("Player Names!")

    tk.Label(root, text="Player One", fg="blue").grid(row=0)
    tk.Label(root, text="Player Two", fg="red").grid(row=1)

    p1 = tk.Entry(root, font=(None, 15))
    p2 = tk.Entry(root, font=(None, 15))

    p1.grid(row=0, column=1)
    p2.grid(row=1, column=1)

    tk.Button(root, text='Play!', command= lambda: play_game(p1.get(),p2.get(), root, screen)).grid(row=10, column=1, sticky=tk.W)
    tk.mainloop()
    
def get_player_ai_details(screen):
    """
    Creating the panel to allow the user to select a color and go against the AI
    """
    options = ["Player 1", "Player 2"]
    root = tk.Tk()
    root.title("Player 1(Blue) or 2(Red)?")

    colorChoice= tk.StringVar(root)
    colorChoice.set(options[0])

    tk.OptionMenu(root, colorChoice, *options).grid(row=3)

    p1 = tk.Entry(root, font=(None, 15))
    p1.grid(row=3, column=1)

    tk.Button(root, text="Play Computer!", command=lambda: play_computer(colorChoice.get(), p1.get(), root, screen)).grid(row=10, column=1)
    
    tk.mainloop()

def play_computer(colorChoice, playerName, root, screen):
    """
    Connect4 play function (human v computer)
    """
    root.destroy()

    if colorChoice == "Player 1":
        mx.Minimax(Player(playerName), Player("Ed"), screen).play_computer()
    else:
        mx.Minimax(Player("Ed"), Player(playerName), screen).play_computer()
    
def play_game(p1Name, p2Name, root, screen):
    """
    Connect4 play function (human v human)
    """
    root.destroy()
    game = cFour.Connect4(Player(p1Name.strip()), Player(p2Name.strip()), screen).play()

if __name__ == "__main__":
    pygame.init()
    screen = load_screen()

    features = [
        ("Player Vs Player", colors.yellow),
        ("Player Vs AI", colors.red),
        ("Quit", colors.gray)
    ]

    iterator = 0
    menu = True
    while menu:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

            #This if block makes it where the user doesnt have to click arrow key up/down if they have exhausted the possible options, it will loop you throughout options
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_DOWN:
                    iterator += 1
                    if iterator == len(features):
                        iterator = 0

                if event.key == pygame.K_UP:
                    iterator -= 1
                    if iterator < 0:
                        iterator = len(features) - 1

                if event.key == pygame.K_RETURN:
                    if selected == "Player Vs Player":
                        get_player_details(screen)
                    if selected == "Player Vs AI":
                        get_player_ai_details(screen)
                    if selected == "Quit":
                        pygame.quit()
                        quit()
            selected = features[iterator][0]
                
        screen.fill(colors.blue)
        screen_rect = screen.get_rect()
        for i in range(0, len(features)):
            counter = -50 + (i * 90) # Equation that sets distance between each choice in main menu
            if i == iterator:
                text = text_format(features[i][0], 80, features[i][1])
            else:
                text = text_format(features[i][0], 80, colors.black)
            player_rect = text.get_rect(center=screen_rect.center)
            player_rect[1] = player_rect[1] + counter
            screen.blit(text, player_rect)    
        pygame.display.update()

Connect4.py

import pygame
import colors
import tkinter as tk
import pygame_menu
# import pandas as pd
import random

class Connect4:
    """
    Class used to represent connect4 game
    """
    def __init__(self, player1, player2, screen):

        # Use 1 version of the screen instead of trying to create a new one
        self.screen = screen

        # Circle Radius and Width
        self.WIDTH = 0
        self.CIRCLERADIUS = 25

        # Game-Time Variables
        self.player1 = player1
        self.player2 = player2
        self.moveNumber = 0
        self.gameOver = False
        self.COLUMNS = 7
        self.ROWS = 6
        self.EMPTY = 99
        self.board = [[self.EMPTY for x in range(self.COLUMNS)] for y in range(self.ROWS)]

        # The distance between where the window starts and the game board is placed
        self.DISTANCE = 90

        # Space between each circle
        self.DISTANCEGAP = 70

        # Setting rectangle default       
        self.LEFT = 50
        self.TOP = 70
        self.HEIGHT = 470
        self.RECWIDTH = 500

        #Creating new tkinterobject
        self.root = tk.Tk()
        self.scoreboard = {self.player1.name: 0, self.player2.name: 0, "ties": 0}
        
        # Storing locations of available moves given a user clicks the window -- Tuple of locations
        self.POSITIONS = [
            (
                self.DISTANCE + (self.DISTANCEGAP*column) - self.CIRCLERADIUS,
                self.DISTANCE + (self.DISTANCEGAP*column) + self.CIRCLERADIUS
            )
            for column in range(0, self.COLUMNS)
        ] 

    def who_won(self, board, piece):
        """
        Determines the state of the game and finds if there is a winner
        """
        # Horizontal
        for col in range(0, self.COLUMNS - 3):
            for row in range(0, self.ROWS):
                if board[row][col] == piece and board[row][col + 1] == piece and board[row][col + 2] == piece and board[row][col + 3] == piece:
                    return True

        # Vertical
        for col in range(0, self.COLUMNS):
            for row in range(0, self.ROWS - 3):
                if board[row][col] == piece and board[row + 1][col] == piece and board[row + 2][col] == piece and board[row + 3][col] == piece:
                    return True
                
        # Up-Left/Down-Right
        for col in range(3, self.COLUMNS):
            for row in range(3, self.ROWS):
                if board[row][col] == piece and board[row - 1][col - 1] == piece and board[row - 2][col - 2] == piece and board[row - 3][col - 3] == piece:
                    return True
        
        # Up-Right/Down-Left
        for col in range(0, self.COLUMNS - 3):
            for row in range(3, self.ROWS):
                if board[row][col] == piece and board[row - 1][col + 1] == piece and board[row - 2][col + 2] == piece and board[row - 3][col + 3] == piece:
                    return True
        
        # A winning move is not found
        return False

    def is_legal_move(self, position, board):
        """
        Validates if a move is available/legal
        """
        if board[0][position] == self.EMPTY:
            return True
        return False

    def display_board(self):
        """
        Displaying the game board to the user
        """
        # Function: rect(surface, color, rectangle object, optional width) -- First one forms the outline of the board
        pygame.draw.rect(self.screen, colors.salmon, (self.LEFT, self.TOP, self.RECWIDTH, self.HEIGHT), 13)

        # This forms inner-most rectangle that users play on
        pygame.draw.rect(self.screen, colors.burlywood, (self.LEFT, self.TOP, self.RECWIDTH, self.HEIGHT))
        
        for column in range(0, self.COLUMNS):
            colEq = self.DISTANCE + (self.DISTANCEGAP * column)
            for row in range(0, self.ROWS):
                # 125 is used here to make a the board placed in the center of the board and helps finding a value for self.TOP easier
                rowEq = 125 + (self.DISTANCEGAP * row)
                if self.board[row][column] == self.EMPTY:
                    color = colors.white
                elif self.board[row][column] == 0:
                    color = colors.realBlue
                elif self.board[row][column] == 1:
                    color = colors.red
                pygame.draw.circle(self.screen, color, (colEq, rowEq), self.CIRCLERADIUS, self.WIDTH)
        pygame.display.flip()
    
    def play(self):
        """
        This is the game-loop
        """
        while not self.gameOver:
            self.display_board()
            if self.moveNumber % 2 == 0:
                userText, userRect = self.display_player_name(self.player1.name, colors.realBlue)
            elif self.moveNumber % 2 == 1:
                userText, userRect = self.display_player_name(self.player2.name, colors.red)
            self.screen.blit(userText, userRect) 

            for event in pygame.event.get():
                self.screen.fill(colors.aquamarine) # Set up background color
                if event.type == pygame.QUIT: 
                    self.gameOver = True 
                elif event.type == pygame.MOUSEBUTTONDOWN:
                    x, y = pygame.mouse.get_pos()
                    position = self.get_column_position(x)
                    if self.moveNumber % 2 == 0 and position != self.EMPTY:
                        if self.is_legal_move(position, self.board):                            
                            self.drop_piece_animation(position)
                            if self.who_won(self.board, 0):
                                self.gameOver = True
                                self.scoreboard[self.player1.name] = self.scoreboard.get(self.player1.name) + 1
                                userText, userRect = self.display_player_name(self.player1.name + " " + "Wins!!!", colors.dark_gray)
                            elif self.check_if_tie(self.board):
                                self.gameOver = True
                                self.scoreboard["ties"] = self.scoreboard.get("ties") + 1
                                userText, userRect = self.display_player_name("It is a TIE!!!", colors.dark_gray)

                    elif self.moveNumber % 2 == 1 and position != self.EMPTY:
                        if self.is_legal_move(position, self.board):                            
                            self.drop_piece_animation(position)
                            if self.who_won(self.board, 1):
                                self.gameOver = True
                                self.scoreboard[self.player2.name] = self.scoreboard.get(self.player2.name) + 1
                                userText, userRect = self.display_player_name(self.player2.name + " " + "Wins!!!", colors.dark_gray)
                            elif self.check_if_tie(self.board):
                                self.gameOver = True
                                self.scoreboard["ties"] = self.scoreboard.get("ties") + 1
                                userText, userRect = self.display_player_name("It is a TIE!!!", colors.dark_gray)
        self.display_board()
        self.screen.blit(userText, userRect) 
        pygame.display.flip()
        self.display_scoreboard(False)
            
    def display_scoreboard(self, isAi):
        """
        This enables the tkinter object so I can display the user options after : Victory/Loss/Tie
        """
        self.root.geometry('460x150+300+0')
        self.reset()
        self.root.title("Choices")

        # This creates the feedback information screen that the user sees after a game
        tk.Label(self.root, text="Close window to go to main menu", font=(None, 15, 'underline'), anchor='w', justify='left').grid(row=0, column=1, sticky="NSEW")
        tk.Label(self.root, text=self.player1.name + ": " + str(self.scoreboard.get(self.player1.name)), font=(None, 15), anchor='w', justify='left').grid(row=1, column=1, sticky = "NSEW")
        tk.Label(self.root, text=self.player2.name + ": " + str(self.scoreboard.get(self.player2.name)), font=(None, 15), anchor='w', justify='left').grid(row=2, column=1, sticky="NSEW")
        tk.Label(self.root, text="Ties: " + str(self.scoreboard.get("ties")), font=(None, 15), anchor='w', justify='left').grid(row=3, column=1, sticky="NSEW")

        # if isAi == True:
        #     # tk.Button(self.root, text='Rematch!', command=self.playAi, font=(None, 12), fg="blue").grid(row=4, column=1, sticky=tk.W)
        # else:
        tk.Button(self.root, text='Rematch!', command=self.play, font=(None, 12), fg="blue").grid(row=4, column=1, sticky=tk.W)
        
        # tk.Button(self.root, text='Rematch with Swap!', command= lambda: self.swapPlayers(isAi), font=(None, 12), fg="red").grid(row=4, column=2, sticky=tk.W)

        tk.Entry(self.root)
        self.root.mainloop()
    
    def check_if_tie(self, board):
        """
        A possible game state : Checking for a tie
        """
        totalPieces = 0
        for col in range(0, self.COLUMNS):
            for row in range(0, self.ROWS):
                if board[row][col] == 0 or board[row][col] == 1:
                    totalPieces += 1  
        if totalPieces == 42:
            return True
        else:
            return False

    def display_player_name(self, name, color):
        """
        A feature to help users know who's turn it is that gets displayed
        """
        font = pygame.font.Font(pygame_menu.font.FONT_FRANCHISE, 60) 
        text = font.render(name, True, color)
        textRect = text.get_rect()
        textRect.center = (len(name) * 30, 20)
        return text, textRect

    def drop_piece_animation(self, position):
        """
        Inserting a piece at a given position with the animation of a piece drop
        """
        tmpRow = 5
        while self.board[tmpRow][position] == 1 or self.board[tmpRow][position] == 0:
            tmpRow -= 1

        for i in range(0, tmpRow + 1):
            self.board[i][position] = self.moveNumber % 2
            self.display_board()
            pygame.time.delay(200)
            pygame.display.flip()
            self.board[i][position] = self.EMPTY

        self.board[tmpRow][position] = self.moveNumber % 2
        self.moveNumber += 1

    def get_column_position(self, position):
        """
        Takes a X coordinate value dependent on a click and determines what column user clicked
        """
        index = 0
        for i in self.POSITIONS:
            if position + self.CIRCLERADIUS/2 >= i[0] and position - self.CIRCLERADIUS/2 <= i[1]:
                return index
            index += 1
        return self.EMPTY

    def reset(self):
        """
        Restoring the game in its original state
        """
        self.moveNumber = 0
        self.board = [[self.EMPTY for x in range(self.COLUMNS)] for y in range(self.ROWS)]
        self.gameOver = False
    
    def play_computer(self):
        """
        This is the game-loop used for AI play
        """
        # If/else block to distinguish the human/Ai because the ai cant mouse click events
        if self.player1.name == "Ed": # Ed Watkins (Staten Island)
            humanPlayer = 1
            computerPlayer = 0

            humanName = self.player2.name
            computerName = self.player1.name

        elif self.player2.name == "Ed":
            humanPlayer = 0
            computerPlayer = 1

            humanName = self.player1.name
            computerName = self.player2.name
            
        while not self.gameOver:
            self.display_board()
            if self.moveNumber % 2 == 0:
                userText, userRect = self.display_player_name(self.player1.name, colors.blue)
            elif self.moveNumber % 2 == 1:
                userText, userRect = self.display_player_name(self.player2.name, colors.red)
            self.screen.blit(userText, userRect) 

            for event in pygame.event.get():
                self.screen.fill(colors.aquamarine) # Set up background color
                if event.type == pygame.QUIT: 
                    self.gameOver = True 
                elif event.type == pygame.MOUSEBUTTONDOWN:
                    x, y = pygame.mouse.get_pos()
                    position = self.get_column_position(x)
                    if self.moveNumber % 2 == humanPlayer and position != self.EMPTY:
                        if self.is_legal_move(position, self.board):                            
                            self.drop_piece_animation(position)
                            if self.who_won(self.board, humanPlayer):
                                self.gameOver = True
                                self.scoreboard[humanName] = self.scoreboard.get(humanName) + 1
                                userText, userRect = self.display_player_name(humanName + " " + "Wins!!!", colors.dark_gray)
                            elif self.check_if_tie(self.board):
                                self.gameOver = True
                                self.scoreboard["ties"] = self.scoreboard.get("ties") + 1
                                userText, userRect = self.display_player_name("It is a TIE!!!", colors.dark_gray)
            if self.moveNumber % 2 == computerPlayer and self.gameOver == False:
                move = self.generate_move(self.board, 4, computerPlayer, humanPlayer, True, self.moveNumber)
                self.drop_piece_animation(move)
                if self.who_won(self.board, computerPlayer):
                    self.gameOver = True
                    self.scoreboard[computerName] = self.scoreboard.get(computerName) + 1
                    userText, userRect = self.display_player_name(computerName + " " + "Wins!!!", colors.dark_gray)
                elif self.check_if_tie(self.board):
                    self.gameOver = True
                    self.scoreboard["ties"] = self.scoreboard.get("ties") + 1
                    userText, userRect = self.display_player_name("It is a TIE!!!", colors.dark_gray)

        self.display_board()
        self.screen.blit(userText, userRect) 
        pygame.display.flip()

Minimax.py

from Connect4 import Connect4
import random
from copy import copy, deepcopy
import pygame

class Minimax(Connect4):
    def __init__(self, player1, player2, screen):
        super().__init__(player1, player2, screen)
    
    def is_game_over(self, board):
        if self.who_won(board, 1) or self.who_won(board, 0):
            return True
        return False

    def generate_move(self, board, depth, computerPlayer, humanPlayer, maximizingPlayer, moveNumber):
        if depth == 0 or self.is_game_over(board) or self.check_if_tie(board):
            if self.is_game_over(board):
                if self.who_won(board, computerPlayer):
                    return 1000000
                elif self.who_won(board, humanPlayer):
                    return -1000000
                elif self.check_if_tie(board):
                    return 0
            else:
                return self.get_game_score(board, computerPlayer, humanPlayer)

        if maximizingPlayer:
            maxValue = -1000000
            for move in range(0, self.COLUMNS):
                tmpBoard = self.copyBoard(board)
                if self.is_legal_move(move, tmpBoard):
                    self.drop_piece_computer(move, tmpBoard, moveNumber)
                    result = self.generate_move(tmpBoard, depth - 1, computerPlayer, humanPlayer, False, moveNumber + 1)
                    if result >= maxValue:
                        maxValue = result
                        bestMove = move
            return bestMove
        else:
            minValue = 1000000
            for move in range(0,self.COLUMNS):
                tmpBoard = self.copyBoard(board)
                if self.is_legal_move(move, tmpBoard):
                    self.drop_piece_computer(move, tmpBoard, moveNumber)
                    result = self.generate_move(tmpBoard, depth - 1, humanPlayer, humanPlayer, True, moveNumber + 1)
                    if result <= minValue:
                        minValue = result
                        thismove = move
            return thismove

    def copyBoard(self, board):
        tmpList = [[self.EMPTY for x in range(self.COLUMNS)] for y in range(self.ROWS)]
        for row in range(0, self.ROWS):
            for col in range(0, self.COLUMNS):
                tmpList[row][col] = board[row][col]
        
        return tmpList

    def drop_piece_computer(self, position, board, moveNumber):
        """
        Inserting a piece at a given position with the animation of a piece drop
        """
        tmpRow = 5
        while board[tmpRow][position] == 1 or board[tmpRow][position] == 0:
            tmpRow -= 1

        
        board[tmpRow][position] = moveNumber % 2
        # moveNumber += 1

    def get_game_score(self, board, computerPlayer, humanPlayer):
        totalScore = 0
        totalScore += self.get_hori_score(board, computerPlayer, humanPlayer)
        # totalScore += self.get_vert_score(board, computerPlayer, humanPlayer)
        # totalScore += self.get_upright_score(board, computerPlayer, humanPlayer)
        # totalScore += self.get_upleft_score(board, computerPlayer, humanPlayer)

        return totalScore

    def get_hori_score(self, board, computerPlayer, humanPlayer):
        score = 0
        # List to collect all the groupings of 4(Horizontally) out of the current game state
        groupingFourList = []
        for col in range(0, self.COLUMNS - 3):
            for row in range(0, self.ROWS):
                groupingFourList.append(board[row][col])
                groupingFourList.append(board[row][col + 1])
                groupingFourList.append(board[row][col + 2])
                groupingFourList.append(board[row][col + 3])

                computerPieces = self.count_player_pieces(groupingFourList, 1)
                humanPieces = self.count_player_pieces(groupingFourList, 0)
                emptyPieces = self.count_player_pieces(groupingFourList, self.EMPTY)

                score += self.score_metric(computerPieces, humanPieces, emptyPieces)
                groupingFourList = []
        
        return score

    def get_upright_score(self, board, computerPlayer, humanPlayer):
        score = 0
        # List to collect all the groupings of 4(Horizontally) out of the current game state
        groupingFourList = []
        for col in range(0, self.COLUMNS - 3):
            for row in range(3, self.ROWS):
                groupingFourList.append(board[row][col])
                groupingFourList.append(board[row - 1][col + 1])
                groupingFourList.append(board[row - 2][col + 2])
                groupingFourList.append(board[row - 3][col + 3])

                computerPieces = self.count_player_pieces(groupingFourList, 1)
                humanPieces = self.count_player_pieces(groupingFourList, 0)
                emptyPieces = self.count_player_pieces(groupingFourList, self.EMPTY)

                score += self.score_metric(computerPieces, humanPieces, emptyPieces)
                groupingFourList = []
        
        return score

    def get_upleft_score(self, board, computerPlayer, humanPlayer):
        score = 0
        # List to collect all the groupings of 4(Horizontally) out of the current game state
        groupingFourList = []
        for col in range(3, self.COLUMNS):
            for row in range(3, self.ROWS):
                groupingFourList.append(board[row][col])
                groupingFourList.append(board[row - 1][col - 1])
                groupingFourList.append(board[row - 2][col - 2])
                groupingFourList.append(board[row - 3][col - 3])

                computerPieces = self.count_player_pieces(groupingFourList, 1)
                humanPieces = self.count_player_pieces(groupingFourList, humanPlayer)
                emptyPieces = self.count_player_pieces(groupingFourList, self.EMPTY)

                score += self.score_metric(computerPieces, humanPieces, emptyPieces)
                groupingFourList = []
        
        return score

    def get_vert_score(self, board, computerPlayer, humanPlayer):
        score = 0
        # List to collect all the groupings of 4(Horizontally) out of the current game state
        groupingFourList = []
        for col in range(0, self.COLUMNS):
            for row in range(0, self.ROWS -3):
                groupingFourList.append(board[row][col])
                groupingFourList.append(board[row + 1][col])
                groupingFourList.append(board[row + 2][col])
                groupingFourList.append(board[row + 3][col])

                computerPieces = self.count_player_pieces(groupingFourList, computerPlayer)
                humanPieces = self.count_player_pieces(groupingFourList, humanPlayer)
                emptyPieces = self.count_player_pieces(groupingFourList, self.EMPTY)

                score += self.score_metric(computerPieces, humanPieces, emptyPieces)
                groupingFourList = []
        
        return score

    def count_player_pieces(self, groupingFourList, playerPiece):
        totalPieces = 0

        for piece in groupingFourList:
            if piece == playerPiece:
                totalPieces += 1
        
        return totalPieces

    def score_metric(self, computerPieces, humanPieces, emptyPieces):
        score = 0

        # Making bot prioritize playing defense than offense
        # Thats why the score is lower when regarding the enemy: AI chooses highest scoring move
        if (computerPieces == 4):
            score += 100
        elif (computerPieces == 3 and emptyPieces == 1):
            score += 20
        elif (computerPieces == 2 and emptyPieces == 2):
            score += 10
        if (humanPieces == 3 and emptyPieces == 1):
            score -= 100

        return score

colors.py

"""
Valid colors to use got it from this link : https://python-forum.io/Thread-PyGame-PyGame-Colors
"""
realBlue = (0,0,255)
white = (255,255,255)
green = (0,255,0)
black = (0,0,0)
orange = (255,100,10)
blue_green = (0,255,170)
marroon = (115,0,0)
lime = (180,255,100)
pink = (255,100,180)
purple = (240,0,255)
magenta = (255,0,230)
brown = (100,40,0)
forest_green = (0,50,0)
navy_blue = (0,0,100)
rust = (210,150,75)
dandilion_yellow = (255,200,0)
highlighter = (255,255,100)
sky_blue = (0,255,255)
light_gray = (200,200,200)
dark_gray = (50,50,50)
tan = (230,220,170)
coffee_brown = (200,190,140)
moon_glow = (235, 245, 255)
burlywood = (255, 211, 155)
salmon = (139, 76, 57)
aquamarine = (127, 255, 212)

#Colors used for menu
blue = (135, 206, 250)
yellow = (255, 255, 0)
red = (255,0,0)
gray = (128, 128, 128)

播放器.py

class Player():
    def __init__(self, name):
        self.name = name

解决方案已解决,但 stackoverflow 不允许我删除问题。我希望删除问题的原因是因为提供的答案不是解决方案,所以它只会让其他人失望。

【问题讨论】:

  • @rabbid76 所以你想让我告诉你解决方法是什么但让它成为答案?
  • @Rabbid76 希望这是有道理的。

标签: python-3.x recursion pygame minimax


【解决方案1】:

好的解决方法如下:

在这部分代码中,这是遍历搜索空间的一部分,并根据每个玩家的最佳移动来评估游戏状态。通过这种算法,AI 知道每个玩家的最佳走法,并可以做出“好的”走法。

        if maximizingPlayer:
            maxValue = -1000000
            for move in range(0, self.COLUMNS):
                tmpBoard = self.copyBoard(board)
                if self.is_legal_move(move, tmpBoard):
                    self.drop_piece_computer(move, tmpBoard, moveNumber)
                    result = self.generate_move(tmpBoard, depth - 1, computerPlayer, humanPlayer, False, moveNumber + 1)
                    if result >= maxValue:
                        maxValue = result
                        bestMove = move
            return bestMove
        else:
            minValue = 1000000
            for move in range(0,self.COLUMNS):
                tmpBoard = self.copyBoard(board)
                if self.is_legal_move(move, tmpBoard):
                    self.drop_piece_computer(move, tmpBoard, moveNumber)
                    result = self.generate_move(tmpBoard, depth - 1, humanPlayer, humanPlayer, True, moveNumber + 1)
                    if result <= minValue:
                        minValue = result
                        thismove = move
            return thismove

但是,如果您仔细观察,当我在 !maximizing player 函数中将函数递归调用回 AI 时:

result = self.generate_move(tmpBoard, depth - 1, humanPlayer, humanPlayer, True, moveNumber + 1)

换句话说,当模拟人类玩家在通用棋盘上玩以生成 ai 动作时,它假设有 2 个人类玩家,这就是为什么会发生停止的原因,因为你不能与 2 个相同的玩家进行游戏.

如此变化:

result = self.generate_move(tmpBoard, depth - 1, humanPlayer, humanPlayer, True, moveNumber + 1)

到这里:

result = self.generate_move(tmpBoard, depth - 1, computerPlayer, humanPlayer, True, moveNumber + 1)

【讨论】:

    【解决方案2】:

    False 代替True 放在if maximizingPlayer 块中,并将True 代替False 放在else 子句中,用于递归调用generate_move 的倒数第二个参数似乎可以解决问题.

    即将 Minimax.py 的第 33 行的 False 更改为 True,并将第 44 行的 True 更改为 False。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-18
      • 1970-01-01
      相关资源
      最近更新 更多