为什么我的 check_if_tie() 函数在 TicTacToe 中不起作用?

Why does my check_if_tie() function not working in TicTacToe?

所以我已经为我的 TicTacToe 获得了这个 Python 代码。一切正常,除非没有获胜者,程序必须 return 'Tie' 并且即使棋盘已经填满,它也会继续要求 X 和 O。我假设问题出在 check_if_tie() 函数中,但我无法弄清楚。

# -------Global variables--------

# If game is still going
game_still_going = True


# Who won? Or tie
winner = None
# Whose turn it is
current_player = 'X'

# The board displaying function
board = [' '] * 10


def display_board():
    print(' ' + board[6] + ' | ' + board[7] + ' | ' + board[8])
    print('---+-'   '--+---  ')
    print(' ' + board[3] + ' | ' + board[4] + ' | ' + board[5])
    print('---+-'   '--+---  ')
    print(' ' + board[0] + ' | ' + board[1] + ' | ' + board[2])

# Checks if game is over


def check_if_game_over():
    check_if_tie()
    check_if_win()


# Checks if there is a winner


def check_if_win():
    global winner

    if check_row():
        winner = check_row()
    elif check_columns():
        winner = check_columns()
    elif check_diagonals():
        winner = check_columns()
    else:
        winner = None
    return


def check_row():
    global game_still_going
    row1 = board[6] == board[7] == board[8] != " "
    row2 = board[3] == board[4] == board[5] != " "
    row3 = board[0] == board[1] == board[2] != " "
    if row1 or row2 or row3:
        game_still_going = False
    if row1:
        return board[6]
    elif row2:
        return board[3]
    elif row3:
        return board[0]

    return


def check_columns():
    global game_still_going
    column1 = board[6] == board[3] == board[0] != " "
    column2 = board[7] == board[4] == board[1] != " "
    column3 = board[8] == board[5] == board[2] != " "
    if column1 or column2 or column3:
        game_still_going = False
    if column1:
        return board[6]
    elif column2:
        return board[7]
    elif column3:
        return board[8]
    return


def check_diagonals():
    global game_still_going
    diagonal1 = board[6] == board[4] == board[2] != " "
    diagonal2 = board[0] == board[4] == board[8] != " "
    if diagonal1 or diagonal2:
        game_still_going = False
    elif diagonal1:
        return board[6]
    elif diagonal2:
        return board[0]
    return


def check_if_tie():
    global game_still_going
    if ' ' not in board:
        game_still_going = False
    return


def flip_player():
    global current_player
    if current_player == 'X':
        current_player = 'O'
    elif current_player == 'O':
        current_player = 'X'
    return


# Whose turn it is to play


def handle_turn(player):
    print(player + "'s turn")
    position = int(input('Please write your position from 1 - 9: ')) - 1
    if position not in [0,1,2,3,4,5,6,7,8,9]:
        return input('Invalid position. Please write 1-9: ')
    board[position] = player
    display_board()


# Main gameplay function
def play_game():
    global winner
    # Displays initial board
    display_board()
    # Loop running the game
    while game_still_going:

        handle_turn(current_player)
        flip_player()
        check_if_game_over()

    if winner == 'X' or winner == 'O':
        print(winner + ' won.')
    elif winner:
        print('Tie')


play_game()

我能想到的最简单的建议是使用一个变量来保存剩余可用方块的数量,并在每轮之后递减它。一旦达到0,如果没有获胜,则必须平局。

# -------Global variables--------

# If game is still going
game_still_going = True


# Who won? Or tie
winner = None
# Whose turn it is
current_player = 'X'

# The board displaying function
board = [' '] * 10

#board spaces
board_spaces = 9

def display_board():
    print(' ' + board[6] + ' | ' + board[7] + ' | ' + board[8])
    print('---+-'   '--+---  ')
    print(' ' + board[3] + ' | ' + board[4] + ' | ' + board[5])
    print('---+-'   '--+---  ')
    print(' ' + board[0] + ' | ' + board[1] + ' | ' + board[2])

# Checks if game is over


def check_if_game_over():
    check_if_win()
    check_if_tie()


# Checks if there is a winner


def check_if_win():
    global winner

    if check_row():
        winner = check_row()
    elif check_columns():
        winner = check_columns()
    elif check_diagonals():
        winner = check_columns()
    else:
        winner = None
    return


def check_row():
    global game_still_going
    row1 = board[6] == board[7] == board[8] != " "
    row2 = board[3] == board[4] == board[5] != " "
    row3 = board[0] == board[1] == board[2] != " "
    if row1 or row2 or row3:
        game_still_going = False
    if row1:
        return board[6]
    elif row2:
        return board[3]
    elif row3:
        return board[0]

    return


def check_columns():
    global game_still_going
    column1 = board[6] == board[3] == board[0] != " "
    column2 = board[7] == board[4] == board[1] != " "
    column3 = board[8] == board[5] == board[2] != " "
    if column1 or column2 or column3:
        game_still_going = False
    if column1:
        return board[6]
    elif column2:
        return board[7]
    elif column3:
        return board[8]
    return


def check_diagonals():
    global game_still_going
    diagonal1 = board[6] == board[4] == board[2] != " "
    diagonal2 = board[0] == board[4] == board[8] != " "
    if diagonal1 or diagonal2:
        game_still_going = False
    elif diagonal1:
        return board[6]
    elif diagonal2:
        return board[0]
    return


def check_if_tie():
    global game_still_going
    global winner
    global board_spaces
    if winner == None and board_spaces == 0:
        game_still_going = False
    return


def flip_player():
    global current_player
    if current_player == 'X':
        current_player = 'O'
    elif current_player == 'O':
        current_player = 'X'
    return


# Whose turn it is to play


def handle_turn(player):
    print(player + "'s turn")
    position = int(input('Please write your position from 1 - 9: ')) - 1
    if position not in [0,1,2,3,4,5,6,7,8,9]:
        return input('Invalid position. Please write 1-9: ')
    board[position] = player
    display_board()
    board_spaces -= 1


# Main gameplay function
def play_game():
    global winner
    # Displays initial board
    display_board()
    # Loop running the game
    while game_still_going:

        handle_turn(current_player)
        flip_player()
        check_if_game_over()

    if winner == 'X' or winner == 'O':
        print(winner + ' won.')
    elif winner:
        print('Tie')


play_game()

你在这段代码中遇到了很多问题,大部分问题都可以通过避免使用全局变量来避免。

当您使用全局变量时,您会更改全局状态,这使得很难理解正在发生的事情。您拥有的功能 return 只不过是改变游戏结束与否的状态。

一个简单的更改是让您 check_ 方法 return 一个实际的布尔值,并在循环中使用该值来检查您是平局还是获胜。

如果您没有平局或获胜,则表示游戏尚未结束。因此,您不需要存储全局值,当然也不必在其他任何地方修改平局或胜利的状态。

让您的功能尽可能简单。我经常这么说,但想想你是怎么玩游戏的。

在一个游戏中,您有 2 个玩家和 1 个棋盘,您可以在其中任意位置设置值。

每回合增加一个棋子,直到游戏以平局或胜利结束。

每次添加棋子时,您都可以查看游戏状态。如果没有完成那么你可以切换当前播放器并输入一个新的曲子并重复。

None 其中需要全局状态,您始终可以将游戏板传递给您的方法...

在你的情况下,这样做很简单:

def is_tie():
    return ' ' not in board

def is_win():
    ... is_win logic
    return result


while not is_tie() or not is_win():
    ... game logic

更进一步,您必须像这样将游戏状态作为参数传递,而不是全局变量:

def is_tie(game):
    return ' ' not in game.board

更进一步,在棋盘中输入一个新棋子将 return 一个新状态。因此,与其修改当前状态,不如使用如下所示的主循环:

game = Game()

while True:
    position = game.prompt_choice()
    if not game.position_available(position)
        # loop again to select a new position
        continue

    game = game.execute_turn(position)

    if game.is_done()
        break
    else:
        # if game not done switch player and move to next turn
        game = game.switch_player()

# current game player is winner
game.print_winner()

很棒的是,如果您想 "replay" 游戏,您只需在再次循环之前保存游戏状态。每个 "game" 被 returned 是前一个游戏对象的修改版本,因此您永远不会修改实际对象。