当前位置: 首页 > 知识库问答 >
问题:

python-用于井字游戏的极小值算法,通过用相同的符号填充每个空白来更新电路板

端木夕
2023-03-14

我一直在努力通过编程小游戏来提高对python的理解,比如tic tac toe。我从头开始创建了一个游戏的副本,但后来我开始寻找一种为游戏创建合理人工智能的方法。我决定用极大极小来实现这个目标。我找到了一本关于算法的教程,并试图为游戏制作它。

然而,当代码运行时,在人工智能的第一轮。棋盘上剩下的每一个空位都填充了相同的符号,迫使获胜,使游戏无法玩。

由于我对这个算法不熟悉,也没有经验,我从youtube教程中提取了代码,并对其进行了编辑,使其能够用于游戏。

这是密码

import random
import time
import sys
from sys import maxsize




#converts numbers from the board to X O and "" for printing out the board 
def numToSymbol(board):
    visual = board
    for i in range(0, 9):
        if visual[i] == -1:
            visual[i]= "X"
        elif visual[i] == 1:
            visual[i] = "O"
        elif visual[i] == 0:
            visual[i] = " "
    return visual


def symbolToNum(visual):
    board = visual
    for i in range(0, 9):
        if board[i] == "X":
            board[i] = -1
        elif board[i] == "O":
            board[i] = 1
        elif board[i] == " ":
            board[i] = 0
    return board


# prints the board, first coverting numbers throught numtoSymbol
def drawBoard():
    visual = numToSymbol(board)
    print(
        "|"+ str(visual[0]) + "|" + str(visual[1]) + "|" + str(visual[2]) + "| \n"
        "-------\n"
        "|"+ str(visual[3]) + "|" + str(visual[4]) + "|" + str(visual[5]) + "| \n"
        "-------\n"
        "|"+ str(visual[6]) + "|" + str(visual[7]) + "|" + str(visual[8]) + "| \n"
        "-------")
    symbolToNum(visual)


# checks the possible options for 3 in a row and if any are all held by one side returns true
def checkWin(board, winConditions, ai):
    if ai == True:
        win = 3
    if ai == False:
        win = -3
    for row in winConditions:
        checkA = board[row[0]]
        checkB = board[row[1]]
        checkC = board[row[2]]
        if checkA + checkB + checkC == int(win):
           return True

    return False

def checkDraw(board):
    emptyTile = 9
    for tile in board:
        if tile != 0:
            emptyTile -= 1
    if emptyTile == 0:
        completion(2)

def availableMoves(board, bonus):
    availableSlots = []
    for position in range(0,9):
        if board[position] == 0:
            availableSlots.append(position + bonus)
    return availableSlots



def playerTurn(board, remainingTurns):
    board = board
    checkDraw(board)
    visual =drawBoard()
    print("pick one of the available slots \n")
    availableSlots = availableMoves(board, 1)
    print(availableSlots)
    choice = int(input('Select a tile from those shown above:\n')) -1
    while  True:    
        if 0 <= choice <= 8:
            if board[choice] == 0:
                board[choice] = -1
                break
            else:
                choice = int(input('Select a tile from those shown above which has not already been selected:\n')) -1
        else:
            choice = int(input('Select a tile from those shown above:\n')) -1
    visual = drawBoard()
    if checkWin(board, winConditions, False) == True:
        completion(0)
    else:
        aiTurn(board, remainingTurns - 1)


class Node(object):

    def __init__(self,  remainingTurns, playerNum, board, value = 0):
        self.depth = remainingTurns
        self.playerNum = playerNum
        self.board = board
        self.value = value
        self.moves = availableMoves(self.board, 0)
        self.children = []
        self.createChildren()

    def availableMoves(self, board):
        self.availableSlots = []
        for position in range(0,9):
            if board[position] == 0:
                availableSlots.append(position)
        return self.availableSlots

    def winCheck(self, state, playerNum):
        self.winConditions = [[0, 1, 2],[3, 4, 5],[6, 7, 8],[0, 3, 6],[1, 4, 7],[2, 5, 8],[0, 4, 8],[2, 4, 6]]
        self.win = 3
        for row in self.winConditions:
            self.checkA = self.state[row[0]]
            self.checkB = self.state[row[1]]
            self.checkC = self.state[row[2]]
            if self.checkA + self.checkB + self.checkC == int(self.win * self.playerNum):
               return True
        return False

    def createChildren(self):
        if self.depth > 0:
            for i in self.moves:
                self.state = self.board
                self.state[i] = self.playerNum
                print(board)
                self.children.append(Node(self.depth - 1, self.playerNum * -1, self.state, self.realVal(self.state, self.playerNum) ))


    def realVal(self, value, playerNum):
        value = self.winCheck(self.state, self.playerNum)
        if value == True:
            return maxsize * self.playerNum
        else:
            return 0




def minimax(node, depth, playerNum):
    if depth == 0 or abs(node.value) == maxsize:
        return node.value

    bestValue = maxsize * -playerNum

    for i in range(len(node.children)):
        child = node.children[i]
        val = minimax(child, depth - 1, -playerNum)
        if (abs(maxsize * playerNum - val) < abs(maxsize * playerNum - bestValue)):
            bestValue = val
    return bestValue


def aiTurn(board, remainingTurns):
    checkDraw(board)
    print('Waiting for ai')
    time.sleep(2)
    board = board
    state = board
    currentPlayer = 1
    tree = Node(remainingTurns, currentPlayer, state)
    bestChoice = -100
    bestValue = maxsize * -1
    for i in range(len(tree.children)):
        n_child = tree.children[i]
        i_val = minimax(n_child, remainingTurns, -currentPlayer,)
        if (abs(currentPlayer * maxsize - i_val) <= abs(currentPlayer * maxsize - bestValue)):
            bestValue = i_val
            bestChoice = i
    print(bestChoice)
    print(board)
    #choice = minimax(tree, remainingTurns, 1)
    board[bestChoice] = 1
    print(board)
    if checkWin(board, winConditions, True) == True:
        completion(1)
    else:
        playerTurn(board, remainingTurns - 1)



def completion(state):
    if state == 1:
        print('The computer has won this game.')
        choice = str(input('press y if you would like to play another game; Press n if you would not \n'))
        if choice == 'y' or choice == 'Y':
            playGame()
        else:
            sys.exit()
    if state == 0:
        print('you win!')
        choice = str(input('press y if you would like to play another game; Press n if you would not \n'))
        if choice == 'y' or choice == 'Y':
            playGame()
        else:
            sys.exit()
    if state == 2:
        print('you drew')
        choice = str(input('press y if you would like to play another game; Press n if you would not \n'))
        if choice == 'y' or choice == 'Y':
            playGame()
        else:
            sys.exit()        




def playGame():
    global board
    board = [0,0,0,0,0,0,0,0,0]

    global winConditions
    winConditions = [
                [0, 1, 2],
                [3, 4, 5],
                [6, 7, 8],
                [0, 3, 6],
                [1, 4, 7],
                [2, 5, 8],
                [0, 4, 8],
                [2, 4, 6]
                ]


    global remainingTurns
    remainingTurns = 9
    playerFirst = random.choice([True, False])

    if playerFirst == True:
        playerTurn(board, remainingTurns)
    else:
        aiTurn(board, remainingTurns)


if __name__ == '__main__':
    playGame() 

这是上述代码的输出

[1, 0, 0, 0, 0, 0, 0, 0, 0]
[1, -1, 0, 0, 0, 0, 0, 0, 0]
[1, -1, 1, 0, 0, 0, 0, 0, 0]
[1, -1, 1, -1, 0, 0, 0, 0, 0]
[1, -1, 1, -1, 1, 0, 0, 0, 0]
[1, -1, 1, -1, 1, -1, 0, 0, 0]
[1, -1, 1, -1, 1, -1, 1, 0, 0]
[1, -1, 1, -1, 1, -1, 1, -1, 0]
[1, -1, 1, -1, 1, -1, 1, -1, 1]
[1, -1, 1, -1, 1, -1, 1, -1, -1]
[1, -1, 1, -1, 1, -1, 1, 1, -1]
[1, -1, 1, -1, 1, -1, 1, 1, 1]
[1, -1, 1, -1, 1, -1, -1, 1, 1]
[1, -1, 1, -1, 1, -1, -1, -1, 1]
[1, -1, 1, -1, 1, -1, -1, -1, -1
[1, -1, 1, -1, 1, 1, -1, -1, -1]
[1, -1, 1, -1, 1, 1, 1, -1, -1]
[1, -1, 1, -1, 1, 1, 1, 1, -1]
[1, -1, 1, -1, 1, 1, 1, 1, 1]
[1, -1, 1, -1, -1, 1, 1, 1, 1]
[1, -1, 1, -1, -1, -1, 1, 1, 1]
[1, -1, 1, -1, -1, -1, -1, 1, 1]
[1, -1, 1, -1, -1, -1, -1, -1, 1
[1, -1, 1, -1, -1, -1, -1, -1, -
[1, -1, 1, 1, -1, -1, -1, -1, -1
[1, -1, 1, 1, 1, -1, -1, -1, -1]
[1, -1, 1, 1, 1, 1, -1, -1, -1]
[1, -1, 1, 1, 1, 1, 1, -1, -1]
[1, -1, 1, 1, 1, 1, 1, 1, -1]
[1, -1, 1, 1, 1, 1, 1, 1, 1]
[1, -1, -1, 1, 1, 1, 1, 1, 1]
[1, -1, -1, -1, 1, 1, 1, 1, 1]
[1, -1, -1, -1, -1, 1, 1, 1, 1]
[1, -1, -1, -1, -1, -1, 1, 1, 1]
[1, -1, -1, -1, -1, -1, -1, 1, 1
[1, -1, -1, -1, -1, -1, -1, -1,
[1, -1, -1, -1, -1, -1, -1, -1,
[1, 1, -1, -1, -1, -1, -1, -1, -
[1, 1, 1, -1, -1, -1, -1, -1, -1
[1, 1, 1, 1, -1, -1, -1, -1, -1]
[1, 1, 1, 1, 1, -1, -1, -1, -1]
[1, 1, 1, 1, 1, 1, -1, -1, -1]
[1, 1, 1, 1, 1, 1, 1, -1, -1]
[1, 1, 1, 1, 1, 1, 1, 1, -1]
[1, 1, 1, 1, 1, 1, 1, 1, 1]
8
[1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1]
The computer has won this game.

有什么建议吗?

共有1个答案

越国源
2023-03-14

问题在于当你初始化你的节点时,你只是复制board的引用:

self.board = board

而你应该复制这些值

self.board = board[::]

否则,所有节点对象都指向同一块板:全局板。

 类似资料:
  • 为了更好地理解minimax算法是如何工作的,我一直在做一个tic-tac-toe程序。以下实现无法正常工作,因为计算机可能会丢失游戏。如果程序运行正常,理论上这是不可能的。。。 我是否在实施极大极小值或采取最佳行动时犯了错误? 我以前从未实现过算法: s 评价函数 极小极大 找到最好的办法 非常感谢。

  • 所以我为我的课做了一个抽动练习作业。我已经成功地创建了一个简单的Tic Tac Toe程序,但不知何故,检查绘制的方法有时并不正确。如果所有东西都填满了,但没有赢家,那就是平局。但如果除第0行第1列外,其他所有内容都已填满,则即使该框仍为空白,它仍将显示“Draw”。如果你不明白我的意思,就试着把所有的东西都填满,但不是赢,即使最后一个框没有填满,它也会说“平局”。我在代码中做错了什么????驱动

  • 问题内容: 我已经用Java编写了一个井字游戏,而我目前确定游戏结束的方法说明了游戏结束的以下可能情况: The board is full, and no winner has yet been declared: Game is a draw. Cross has won. Circle has won. 不幸的是,这样做的目的是从表中读取一组预定义的方案。考虑到一个棋盘上只有9个空格,这并不

  • 我正在制作一个名为SOS的游戏。这是一款3x3的棋盘游戏,与Tic Tac Toe的概念相同,但在这款游戏中,玩家无法选择是以X还是O的身份进行游戏,游戏中唯一的规则是形成“SOS”。 我们的项目应该在所有职位被填补后终止,每个组成的“SOS”将被添加到组成“SOS”的玩家中。 我的问题是关于得分。在第一行输入SOS后,即,我尝试在第二行第一列输入“O”,玩家2将递增。它不应该递增,因为它不满足我

  • 本文向大家介绍基于jsp的井字游戏实例,包括了基于jsp的井字游戏实例的使用技巧和注意事项,需要的朋友参考一下 做一款回忆童年的游戏,这款游戏代码比较简单,主要是掌握算法的原理,但是也有一些需要注意的地方。 游戏界面 进入正题。项目的效果图如下: 游戏有一个开始界面可供选择玩家的角色,然后选择先手是哪一方,接着开始游戏。选择界面做了一个遮罩层,里面提供给用户选择,选择之后便把遮罩层隐藏并开始游戏。

  • 我想将字符串拆分为固定长度,例如,拆分20个字符,如果拆分后长度小于20个字符,则用最多20个字符的空格填充字符串。 我使用上面的代码按相等大小进行拆分。