Hi guys I need some help with a tic tac toe game I made, the problem[s] is that it will not display that there is a tie and when you win it will run the computer move function and then it will say you have won.
It is something to do with the logic but I cannnot find where it is :'(

import random
board = []

def make_board(board):
    """Create a new board."""
    for square in range(9):
        board.append(square+1)
    return board

def display_board(board):
    """Display game board on screen."""
    print("\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])

def player_move(board):
    try:
        move = input()
        if board[int(move)-1] == "X" or board[int(move)-1] == "O":
            print("That space has already been taken.")
            player_move(board)
        board[int(move)-1] = "X"
    except TypeError:
        player_move(board)
    except ValueError:
        player_move(board)
    except IndexError:
        player_move(board)

def computer_move(board):
    move = random.randint(0, 8)
    if board[move] == "X" or board[move] == "O":
        computer_move(board)
    else:
        print("My move has been calculated:")
        board[move] = "O"

def winner(board):
    """Determine the game winner."""
    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]] != "":
            winner = board[row[0]]
            return winner
    if "" not in board:
        return ""
    return None

def congrat_winner(the_winner):
    """Congratulate the winner."""
    if the_winner != "":
        print(the_winner, " has won!\n") 
    else:
        print("It's a tie!\n")

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

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

    elif the_winner == "":
        print("You were most lucky, human, and somehow managed to tie me.  \n" \
              "Celebrate today... for this is the best you will ever achieve.")
    
def main():
    make_board(board)
    while not winner(board):
        winner(board)
        display_board(board)
        player_move(board)
        display_board(board)
        winner(board)
        computer_move(board)
    the_winner = winner(board)
    congrat_winner(the_winner)
    input("Press enter to exit: ")

main()

Thanks alot for any help received.
Btw I would not mind if you gave me some advice on the structuring of it as I know it is very poor.

Recommended Answers

All 2 Replies

"board" is global and a list, which is why you can pass it to a function but not catch the return and still have an updated board. Either pass and return the variable (the accepted method) or delete the variable in the function definition. This code can possibly reach a recursion limit.

if board[int(move)-1] == "X" or board[int(move)-1] == "O":
            print("That space has already been taken.")
            player_move(board)
        board[int(move)-1] = "X"
#
# a better way
def player_move(board):
    try:
        move = input("Enter an empty space's number ")
        ## will also loop if letters are input
        while move < "0" or move > "8" or board[int(move)-1] not in ["X", "O"]:
 
            print("That space has already been taken.")
            move = input("Enter an empty space's number ")
        board[int(move)-1] = "X"

The "tie" code is in the winner function.

## although the squares are numbers not "" but it is the same principle
    if "" not in board:
        return "game is a tie"

Testing for a win without letting another move be made first, and printing if it is a tie.

def main():
    make_board()
    display_board(board)
    the_winner = winner(board)
    while not the_winner:
        for next_turn in [player_move(board), computer_move(board)]:
            if not the_winner:     ## don't execute if previous move's result was a winner
                next_turn
                the_winner=winner(board)
                display_board(board)
    if the_winner not in ["X", "O"]:
        print "The game is a tie"  ## or congrat_winner("")
    else:
        congrat_winner(the_winner)
    input("Press enter to exit: ")

Also, player_move() and computer_move() should be one function which you pass either "X" or "O" to indicate who's moving.

for next_turn in ["X", "O"]:
            if not the_winner:     ## don't execute if previous move's result was a winner
                a_move(next_turn)

I still cannot get it to work with the code you suggested :/
The player move keeps on repeating "type a empty space's number"
when I return it to my original player move code(with still the main function you suggested)
the winner and tie detection still has the same problem as I had before.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.