0

我试图在我的井字游戏程序中制造一个“聪明”的对手。为此,我创建了一个“可能获胜”功能,它将决定下一回合是否有可能获胜。运行此代码时我的问题是,在 for 循环的每次迭代中,变量板似乎都发生了变化。

我想在每次迭代开始时将潜在板重置为原始板,这就是我在循环开始时包含 potential_board = board[:] 的原因。然后我编辑potential_board,但每次循环重复时,此变量都不会重置,实际上板也发生了变化。为什么是这样?

非常感谢!

import random,copy

board = [['o','o',' '],[' ',' ',' '],[' ',' ',' ']]
cols = [['o',' ',' '],['o','',''],['o','','']]

def possible_win(board,player):
    """ This function should predict whether a winning move is possible in
    the next turn. This could be done by simulating every possible next move
    and running check_win() on those positions.

    :param board,player: checks a win for the specified player
    :return:
    """
    spaces = empty_spaces(board)
    print('Spaces',spaces)

    winning_moves = []

    for space in spaces:

        potential_board = board[:]

        print('PBoard',potential_board)

        print(space[0],space[1])
        potential_board[space[0]][space[1]] = 'o'

        if check_win(potential_board,'o'):
            winning_moves.append(space)




    return winning_moves


def choose_space(board):

    a = True
    while a:

        col = int(input('Choose your column of 1,2,3: ')) - 1
        row = int(input('Choose your row of 1,2,3: ')) - 1

        if board[row][col] == ' ':
            board[row][col] = 'o'
            a = False

        else: print('Sorry, try again')

    return board


def empty_spaces(board):
    empty_spaces = []
    ind = 0
    for row in board:
        ind1 = 0
        for space in row:
            if space == ' ':
                empty_spaces.append((ind, ind1))
            ind1 += 1
        ind += 1
    return empty_spaces


def comp_choose_space(board):
    choice = random.choice(empty_spaces(board))
    board[choice[0]][choice[1]] = 'x'
    return board


def check_win(board,player):

    rows = board
    columns = construct_cols(board)

    for row in board:
        # if player fills row win = True
        a = ind =  0
        for space in row:
            if rows[board.index(row)][ind] != player: break
            else: a += 1
            ind += 1
        if a == 3:
            return True

    for col in columns:
        a = ind = 0
        for space in col:
            if rows[columns.index(col)][ind] != player:
                break
            else:
                a += 1
            ind += 1
        if a == 3:
            return True

    if rows[0][0] == player and rows[1][1] == player and rows[2][2] == player \
        or rows[0][2] == player and rows[1][1] == player and rows[2][0] == player:
        return True

    return False


def construct_cols(board):
    cols = [['','',''],['','',''],['','','']]
    for row in range(len(board)):
        for col in range(row):
            cols[col][row] = board[row][col] # sounds like this should work

    return cols

def print_board(board):
    for row in board:

        print('| {} {} {} |'.format(row[0],row[1],row[2]))

def main():
    turns = 0
    board = [[' ',' ',' '],[' ',' ',' '],[' ',' ',' ']]
    print_board(board)
    win = False
    while win == False and turns < 9:
        turns += 1
        board = choose_space(board)

        if check_win(board,'o'): win,winner = True,'won'

        board = comp_choose_space(board)


        if check_win(board,'x'): win,winner = True,'lost'

        print_board(board)

    if turns == 9: print('You drew!')
    else:
        print('{}, you {}'.format('Congratulations' if winner == 'won' else 'Sorry',winner))




print(possible_win(board,'o'))
# print(empty_spaces(board))

# print(check_win(board,'o'))
# print_board(board)
# print(comp_choose_space(board))

# main()

# Future project - make the computer smarter than just randomly choosing a space
# ie seeing how close i am to winning

编辑:通过使用 copy.deepcopy() 我设法解决了这个问题,但我不明白为什么这有效,而 copy.copy() 和 board[:] 不起作用?有人可以解释一下吗?

4

1 回答 1

1

这是copy.deepcopy为了什么。它将遍历结构,在其中创建每个可变对象的副本。使用切片[:]或浅层copy仅复制顶层,使每一行的列表共享。

基本上,如果我们从一个列表开始:

l = [a, b, c]

shallow = l[:]
shallow2 = copy(l)

deep = deepcopy(l)

这两个shallow副本只在 上 操作过,l没有在或上操作过。它们都具有价值,但它们是不同的列表。它们都引用相同的,和对象(从它们的角度来看,唯一的变化是有更多的引用)。abc[a, b, c]abc

deep副本更深入并复制了每个元素;[deepcopy(a), deepcopy(b), deepcopy(c)]无论这些值变成什么,它都是一个带有 shape 的新列表。

于 2018-07-31T10:37:12.237 回答