连接4用python AI alpha-beta-pruning(Recursion / MemoryError)实现?

时间:2017-07-03 09:59:08

标签: python algorithm python-3.x alpha-beta-pruning

我正在尝试使用AI创建名为Connect Four的游戏,它在python中使用alpha-beta修剪算法。以下是我设法做的代码:

    # -*- coding: utf-8 -*-

import sys

class ConnectFour:
    def __init__(self):
        self.board  = [[],[],[],[],[],[]]
        for i in range(7):
            for j in range(6):
                self.board[j].append(" ")
        self.moves = 0
        self.colstack = [0,0,0,0,0,0,0]
        self.node = 0
        self.move = 0

    def PrintGameBoard(self):
        print('  0   1   2   3   4   5   6')
        for i in range(5, -1, -1):
            print('|---|---|---|---|---|---|---|')
            print("| ",end="")
            for j in range(7):
                print(self.board[i][j],end="")
                if j != 6:
                    print(" | ",end="")
                else:
                    print(" |")
        print('`---------------------------´')

    def CanPlay(self, col):
        return self.colstack[col] < 6

    def Play(self, col, board):
        board[self.colstack[col]][col] = 2
        self.colstack[col] += 1
        self.moves += 1
        return board

    def IsWinning(self, currentplayer):
        for i in range(6):
            for j in range(4):
                if self.board[i][j] == currentplayer and self.board[i][j+1] == currentplayer and self.board[i][j+2] == currentplayer and self.board[i][j+3] == currentplayer:
                    return True
        for i in range(3):
            for j in range(7):
                if self.board[i][j] == currentplayer and self.board[i+1][j] == currentplayer and self.board[i+2][j] == currentplayer and self.board[i+3][j] == currentplayer:
                    return True     
        for i in range(3):
            for j in range(4):
                if self.board[i][j] == currentplayer and self.board[i+1][j+1] == currentplayer and self.board[i+2][j+2] == currentplayer and self.board[i+3][j+3] == currentplayer:
                    return True
        for i in range(3,6):
            for j in range(4):
                if self.board[i][j] == currentplayer and self.board[i-1][j+1] == currentplayer and self.board[i-2][j+2] == currentplayer and self.board[i-3][j+3] == currentplayer:
                    return True
        return False

    def AlphaBeta(self, alpha, beta):
        self.node += 1
        if self.moves == 42:
            return 0
        for col in range(7):
            if self.CanPlay(col) and self.IsWinning(2):
                return (43 - self.moves)/2  
        max = (41 - self.moves)/2
        if beta > max:
            beta = max
            if alpha >= beta:
                return beta
        for col in range(7):
            if self.CanPlay(col):
                self.board[self.colstack[col]][col] = 2
                self.move = col
                score = -self.AlphaBeta(-alpha, -beta)
                if score >= beta:
                    return score
                elif score > alpha:
                    alpha = score
                self.board[self.colstack[col]][col] = " "

    def Solve(self, table, week=False):
        self.node = 0
        self.board = table
        if week:
            self.AlphaBeta(-1, 1)
            self.board = self.Play(self.move, table)
            return self.board
        else:
            self.AlphaBeta(-21, 21)
            self.board = self.Play(self.move, table)
            return self.board

    def PlayerMove(self, table):
        self.board  = table
        try:
            allowedmove = False
            while not allowedmove:
                print("Choose a column where you want to make your move (0-6): ",end="")
                col =input()
                if self.CanPlay(int(col)):
                    self.board[self.colstack[int(col)]][int(col)] = 1
                    self.moves += 1
                    self.colstack[int(col)] += 1
                    allowedmove = True
                else:
                    print("This column is full")
        except (NameError, ValueError, IndexError, TypeError, SyntaxError) as e:
            print("Give a number as an integer between 0-6!")
        else:
            return self.board

def PlayerMark():
    print("Player 1 starts the game")
    mark = ''
    while not (mark == "1" or mark == "2"):
        print('Do you want to be 1 or 2: ',end="")
        mark = input()
    if mark == "1":
        return 1
    else:
        return 2

def PlayAgain():
    print('Do you want to play again? (yes or no) :',end="")
    return input().lower().startswith('y')

def main():
    sys.setrecursionlimit(2000)
    print("Connect4")
    while True:
        mark = PlayerMark()
        connectfour = ConnectFour()
        if mark==1:
            print("You are going to start the game\r\n\r\n")
        else:
            print("Computer (negamax) starts the game")
        gameisgoing = True
        table  = [[],[],[],[],[],[]]
        for i in range(7):
            for j in range(6):
                table[j].append(" ")
        while gameisgoing:
            connectfour.PrintGameBoard()
            if mark == 1:
                table = connectfour.PlayerMove(table)
                if connectfour.IsWinning(1):
                    connectfour.PrintGameBoard()
                    print('You won the game!')
                    gameisgoing = False
                else:
                    if connectfour.moves==42:
                        connectfour.PrintGameBoard()
                        print('Game is tie')
                        break
                    else:
                        mark = 2
            else:
                move = connectfour.Solve(table)
                if connectfour.IsWinning(2):
                    connectfour.PrintGameBoard()
                    print('Computer won the game')
                    gameisgoing = False
                else:
                    if connectfour.moves==42:
                        connectfour.PrintGameBoard()
                        print('Game is tie')
                        break
                    else:
                        mark = 1
        if not PlayAgain():
            print("Game ended")
            break

if __name__ == '__main__':
    main()

我不确定算法是否正常工作,但问题是我得到了RecursionError:相比之下,超出了最大重新调整深度。如果我增加recursionlimit,我会得到大约10000 MemoryError:Stack Overflow。我认为问题在于我的计算机处理的状态太多了。这就是为什么我将negamax算法改为alpha-beta修剪但似乎仍有许多状态。有没有一种有效的技术,算法搜索例如最大深度10和仍然计算机几乎是原则。我在等你的解决方案。

0 个答案:

没有答案