1

I am writing a code for a simple game of tic-tac-toe using lists. I have used multiple functions to display the game board, to check for a winner and to get position input for X and O. The main while loop of the game does not terminate once a player wins as I think I have programmed it to be. I am also aware that I have not yet added the condition to check if the game ends in a tie. I was not sure where the error was so I have given the entire code.

r1=['_','_','_']
r2=['_','_','_']
r3=['_','_','_']
n1=[1,2,3]
n2=[4,5,6]
n3=[7,8,9]
winner=False
def board():
    print('|',n1[0],n1[1],n1[2],'|')
    print('|',n2[0],n2[1],n2[2],'|')
    print('|',n3[0],n3[1],n3[2],'|')
    print()
    print('|',r1[0],r1[1],r1[2],'|')
    print('|',r2[0],r2[1],r2[2],'|')
    print('|',r3[0],r3[1],r3[2],'|')
def win():
    for i in range(0,3):
        if(r1[i]==r2[i] and r2[i]==r3[i]and (r1[i]=="X" or r1[i]=="O")):
            winner=r1[i]
            print(winner," wins")
            break
        elif(r1[0]==r1[1] and r1[1]==r1[2] and (r1[0]=="X" or r1[0]=="O")):
            winner=r1[0]
            print(winner," wins")
            break
        elif(r2[0]==r2[1] and r2[1]==r2[2] and (r2[0]=="X" or r2[0]=="O")):
            winner=r2[0]
            print(winner," wins")
            break
        elif(r3[0]==r3[1] and r3[1]==r3[2] and (r3[0]=="X" or r3[0]=="O")):
            winner=r3[0]
            print(winner," wins")
            break
        elif(r1[0]==r2[1] and r2[1]==r3[2] and (r1[0]=="X" or r1[0]=="O")):
            winner=r1[0]
            print(winner," wins")
            break
        elif(r1[2]==r2[1] and r2[1]==r3[0] and (r1[2]=="X" or r1[2]=="O")):
            winner=r1[2]
            print(winner," wins")
            break
        else:
            winner=False
        print(winner)
def play_x():
    x=0
    while x<1 or x>9:
        x=int(input('Enter play position for x'))
        if x in n1:
            k=n1.index(x)
            n1[k]='_'
            r1[k]="X"
        elif x in n2:
            k=n2.index(x)
            n2[k]='_'
            r2[k]='X'
        elif x in n3:
            k=n3.index(x)
            n3[k]='_'
            r3[k]='X'
        else:
            x=0
if winner!=False:
    return(0)
else:
    pass
def play_o():
    o=0
    while o<1 or o>9:
        o=int(input('Enter play position for o'))
        if o in n1:
            k=n1.index(o)
            n1[k]='_'
            r1[k]='O'
        elif o in n2:
            k=n2.index(o)
            n2[k]='_'
            r2[k]='O'
        elif o in n3:
            k=n3.index(o)
            n3[k]='_'
            r3[k]='O'
        else:
            o=0
    if winner!=False:
        return
    else:
        pass
board()
while True:
    play_x()
    board()
    win()
    if winner!=False:
        break
    else:
        play_o()
        board()
        win()
        if winner!=False:
            break

Game goes on after a player wins

Click the above link to see the output. Neither the return statement within the play_x /play_o function nor the break function in the while loop do not seem to terminate the code

Athish
  • 11
  • 1
  • 1
    `winner` inside your function is not the same variable as the `winner` outside the function. You could either make it global (not a good solution) or pass the winner back as a return value from the function (much better). – RufusVS Apr 03 '22 at 18:57

1 Answers1

0

I believe changing break to return might solve the issue, although I'm unsure. If that doesn't work, try changing the last bit to something like this:

def play_game():
    board()
    while winner == False:
        play_x()
        board()
        win()
        if winner == False:
            play_o()
            board()
            win()

if __name__ == "__main__":
    play_game()

This could still be refined a little more, but hopefully that helps :)

(as an aside, even though python will let you do this, it's usually bad practice to have a variable function as 2 different types. winner is pulling double duty as a boolean flag and a string. Consider making that two separate variables or changing your declaration of winner = "None")

Greystormy
  • 48
  • 8
  • changing break to return didn't seem to do the trick but the new function worked. Also a comment on my question said that I should declare "winner" as a global variable first but doing so isn't a good practice. I did that with original version of my code and it worked perfectly. Any idea why that is a bad practice? – Athish Apr 04 '22 at 05:01
  • Here's a good answer on why you should avoid declaring global variables unless it's needed: https://stackoverflow.com/questions/19158339/why-are-global-variables-evil – Greystormy Apr 24 '22 at 17:37