Schönen Tag. Ich lese gerade Michael Dawsons Buch Python für den absoluten Anfänger . Ich habe diesen Code für Kapitel 6 und wenn ich den Code ausgeführt habe und das gerade "X" im Board habe, wird der Gewinner nicht zurückgegeben. Das Programm wird fortgesetzt, bis alle Leerzeichen entweder mit "X" oder "O" markiert sind. Hier ist mein Code:

#!/usr/bin/python3
X = "X"
O = "O"
EMPTY = " "
TIE = "TIE"
NUM_SQUARES = 9

def display_instruct():
    print(
          """
          Welcome to the greatest intellectual challenge of all time: Tic-Tac-Toe.
          This will be a showdown between your human brain and my silicon processor.

          You will make your move known by entering a number, 0 - 8. The number
          will correspond to the board position as illustrated:

                                      0 | 1 | 2
                                     -----------
                                      3 | 4 | 5
                                     -----------
                                      6 | 7 | 8

            Prepare your self, human. The ultimate battle is about to begin. \n
            """)

def ask_yes_no(question):
    response = None
    while response not in ("y", "n"):
        response = input(question).lower()
    return response

def ask_number(question, low, high):
    response = None
    while response not in range(low, high):
        response = int(input(question))
    return response

def pieces():
    go_first = ask_yes_no("Do you require the first move? (y/n): ")
    if go_first == "y":
        print( "\nThen take the first move. You will need it. ")
        human = X
        computer = O
    else:
        print("\nYour bravery will be your undoing... I will go first.")
        computer = X
        human = O
    return computer, human

def new_board():
    board = []
    for square in range(NUM_SQUARES):
        board.append(EMPTY)
    return board

def display_board(board):
    print("\n\t", board[0], "|", board[1], "|", board[2])
    print("\t", "---------")
    print("\t", board[3], "|", board[4], "|", board[5])
    print("\t", "---------")
    print("\t", board[6], "|", board[7], "|", board[8], "\n")

def legal_moves(board):
    moves = []
    for square in range(NUM_SQUARES):
        if board[square] == EMPTY:
            moves.append(square)
    return moves

def winner(board):
    WAYS_TO_WIN = ((0, 1, 2),
                   (3, 4, 5),
                   (6, 7, 8),
                   (0, 3, 6),
                   (1, 4, 7),
                   (2, 5, 8),
                   (0, 4, 8),
                   (2, 4, 6))

    for row in WAYS_TO_WIN:
        if board[row[0]] == board[row[1]] == board[row[2]] != EMPTY:
            winner = board[row[0]]
            return winner

        if EMPTY not in board:
            return TIE

        return None

def human_move(board, human):
    """Get human move."""
    legal = legal_moves(board)
    move = None
    while move not in legal:
        move = ask_number("Where will you move? (0 - 8): ", 0, NUM_SQUARES)
        if move not in legal:
            print("\nThat square is already occupied, foolish human. Choose another.\n")
    print("Fine....")
    return move

def computer_move(board, computer, human):
    """Make computer move."""
    #make a copy to work with since function will be changing list.
    board = board[:]
    BEST_MOVES = (4, 0, 2, 6, 8, 1, 3, 5, 7)
    print("I shall take square number")

    # if computer can win, take that move
    for move in legal_moves(board):
        board[move] = computer
        if winner(board) == computer:
            print(move)
            return move
        board[move] = EMPTY

    # if human can win, block that move
    for move in legal_moves(board):
        board[move] = human
        if winner(board) == human:
            print(move)
            return move
        # done checking this move, undo it
        board[move] =  EMPTY

    # since no one ca win on next move, pick best open square
    for move in BEST_MOVES:
        if move in legal_moves(board):
            print(move)
            return move

def next_turn(turn):
    if turn == X:
        return 0
    else:
        return X

def congrat_winner(the_winner, computer, human):
    if the_winner != TIE:
        print(the_winner, "won!\n")
    else:
        print("It's a tie!\n")
    if the_winner == computer:
        print("As I predicted, human, I am triumphant once more. \n" \
              "Proof that computers are superior to humans in all regards.\n")

    elif the_winner == human:
        print("No, no! It cannot be! Somehow you tricked me, human. \n" \
              "But never again! I, the computer, so swears it\n!")

    elif the_winner == TIE:
              print("You were most lucky, human, and somehow managed to tie me. \n" \
                    "Celebrate today... for this is the best you will ever achieve.\n")

def main():
    display_instruct()
    computer, human = pieces()
    turn = X
    board = new_board()
    display_board(board)

    while not winner(board):
        if turn == human:
            move = human_move(board, human)
            board[move] = human
        else:
            move = computer_move(board, computer, human)
            board[move] = computer

        display_board(board)
        turn = next_turn(turn)

    the_winner = winner(board)
    congrat_winner(the_winner, computer, human)

main()

input("Press enter to exit")
2
John Cruz 22 Aug. 2015 im 08:50

3 Antworten

Beste Antwort

Die Funktion, die nach einem Sieg oder Unentschieden sucht, ist falsch. Derzeit haben Sie Folgendes:

def winner(board):
    WAYS_TO_WIN = ((0, 1, 2),
                   (3, 4, 5),
                   (6, 7, 8),
                   (0, 3, 6),
                   (1, 4, 7),
                   (2, 5, 8),
                   (0, 4, 8),
                   (2, 4, 6))

    for row in WAYS_TO_WIN:
        if board[row[0]] == board[row[1]] == board[row[2]] != EMPTY:
            winner = board[row[0]]
            return winner

        if EMPTY not in board:
            return TIE

        return None

Beachten Sie, dass sich return None in der Schleife befindet, sodass Sie None zurückgeben, wenn die erste Zeile nicht übereinstimmt. Es sei denn, die Karte ist voll. In diesem Fall geben Sie TIE korrekt zurück, es sei denn, Sie hätten nach einer vollen Karte suchen können, bevor Sie versucht haben, Zeilen abzugleichen.

Wir können die Funktion korrigieren, indem wir return None erneut einrücken, damit sie nach der Schleife ausgeführt wird. Außerdem ist es sinnvoll, die Prüfung TIE vor die Schleife zu verschieben.

def winner(board):
    if EMPTY not in board:
        return TIE

    WAYS_TO_WIN = ((0, 1, 2),
                   (3, 4, 5),
                   (6, 7, 8),
                   (0, 3, 6),
                   (1, 4, 7),
                   (2, 5, 8),
                   (0, 4, 8),
                   (2, 4, 6))

    for row in WAYS_TO_WIN:
        if board[row[0]] == board[row[1]] == board[row[2]] != EMPTY:
            winner = board[row[0]]
            return winner

    return None

Lassen Sie uns überprüfen, was diese Funktion bewirkt. Wir beginnen mit der Suche nach einer Vollpension. Dann überlegen wir uns, wie wir gewinnen können. Wenn keiner von ihnen übereinstimmt, geben wir None zurück.

Es gibt noch ein Problem in Ihrem Code:

def next_turn(turn):
    if turn == X:
        return 0
    else:
        return X

Damit der spätere Test if turn == human: in allen Fällen ordnungsgemäß funktioniert, muss der Wert von turn entweder X oder O sein, nicht X oder {{ X5}}. Dies ist die schnelle Lösung:

def next_turn(turn):
    if turn == X:
        return O
    else:
        return X

Der bessere Weg, um dieses Problem zu beheben, besteht darin, eine Variable mit dem Namen O zu vermeiden.

3
Michael Laszlo 22 Aug. 2015 im 06:39

Verstehen Sie, dass Sie bereits Ihre Antwort haben, aber einen Ratschlag - versuchen Sie, Ihre Funktionen isoliert zu testen.

In Ihrem Fall hatten Sie bereits die Vermutung, dass ein Problem mit Ihrer winner -Funktion aufgetreten ist. Ich habe dies direkt Ihrer Frage entnommen, in der Sie erwähnt haben, dass "der Gewinner nicht zurückgegeben wird".

Es gibt viele Ansätze zum Testen, aber lassen Sie es uns einfach halten und diese Funktion nutzen, sie in ein neues Python-Programm kopieren, einige Spielbretter darauf werfen und sehen, was passiert. Ich meine "sehen" wörtlich - Ihr bester Freund beim Testen ist print. Angenommen, wir ändern Ihre Funktion folgendermaßen:

def winner(board):
    print("winner function entered")
    WAYS_TO_WIN = ((0, 1, 2),
                   (3, 4, 5),
                   (6, 7, 8),
                   (0, 3, 6),
                   (1, 4, 7),
                   (2, 5, 8),
                   (0, 4, 8),
                   (2, 4, 6))

    for row in WAYS_TO_WIN:
        print("for loop entered")
        if board[row[0]] == board[row[1]] == board[row[2]] != EMPTY:
            winner = board[row[0]]
            return winner

        if EMPTY not in board:
            return TIE
        return None

Es mag allzu einfach erscheinen, aber wir bemerken sofort, dass die for-Schleife in allen Fällen immer nur einmal eingegeben wird. Mit einem kleinen Codeabschnitt, auf den Sie sich konzentrieren können, dauert es nicht lange, bis der Einrückungsfehler gefunden wird.

0
Matt P 22 Aug. 2015 im 12:01

Sie haben auch einen Einrückungsfehler in def(congrat_winner) gemacht

Der richtige Weg ist:

    def congrat_winner(the_winner, computer, human):

        if the_winner != TIE:
            print(the_winner, "won!\n")
        else:
            print("It's a tie!\n")

        if the_winner == computer:
            print("As I predicted, human, I am triumphant once more. \n" \
                  "Proof that computers are superior to humans in all regards.\n")

        elif the_winner == human:
            print("No, no! It cannot be! Somehow you tricked me, human. \n" \
                  "But never again! I, the computer, so swears it\n!")

        elif the_winner == TIE:
            print("You were most lucky, human, and somehow managed to tie me. \n" \
                  "Celebrate today... for this is the best you will ever achieve.\n")

Außerdem sollte das letzte elif durch else ersetzt werden:

    def congrat_winner(the_winner, computer, human):

        if the_winner != TIE:
            print(the_winner, "won!\n")
        else:
            print("It's a tie!\n")

        if the_winner == computer:
            print("As I predicted, human, I am triumphant once more. \n" \
                  "Proof that computers are superior to humans in all regards.\n")

        elif the_winner == human:
            print("No, no! It cannot be! Somehow you tricked me, human. \n" \
                  "But never again! I, the computer, so swears it\n!")

        else:
            print("You were most lucky, human, and somehow managed to tie me. \n" \
                  "Celebrate today... for this is the best you will ever achieve.\n")
0
or3stis 22 Aug. 2015 im 06:36