James
James

Reputation: 143

Tic Tac Toe isn't showing winner correctly with lists

In my tic tac toe game, after 4 turns, it declares X (the first player) to be the winner even if not. I don't know what im missing and it was working when just checking columns but now with rows it doesn't. I have a feeling it's a problem when I am calling the function with the letter but I'm not entirely sure.

moves = [["1", "2", "3"],
         ["1", "2", "3"],
         ["1", "2", "3"]]

def win(letter):
  if(moves[0][0] == letter and
     moves[1][0] == letter and
     moves[2][0] == letter):
    print("~~~ " + letter + " WON!!! CONGRATS!!!! ~~~")
    quit()
  elif(moves[0][1] == letter and
       moves[1][1] == letter and
       moves[2][1] == letter):
    print("~~~ " + letter + " WON!!! CONGRATS!!!! ~~~")
    quit()
  elif(moves[0][2] == letter and
       moves[1][2] == letter and
       moves[2][2] == letter ):
    print("~~~ " + letter + " WON!!! CONGRATS!!!! ~~~")
    quit()
  elif(moves[0][0] == letter and
       moves[0][1] == letter and
       moves[0][2]):
    print("~~~ " + letter + " WON!!! CONGRATS!!!! ~~~")
    quit()
  elif(moves[1][0] == letter and
       moves[1][1] == letter and
       moves[1][2]):
    print("~~~ " + letter + " WON!!! CONGRATS!!!! ~~~")
    quit()
  elif(moves[2][0] == letter and
       moves[2][1] == letter and
       moves[2][2]):
    print("~~~ " + letter + " WON!!! CONGRATS!!!! ~~~")
    quit()
def playerInput():
  player1 = input("Where do you want to place your X, player 1? (row number, space, number)")
  moves[int(player1[0]) - 1][int(player1[2]) - 1] = "X"
  player2 = input("Where do you want to place your O, player 2? (row number, space, number)")
  moves[int(player2[0]) - 1][int(player2[2]) - 1] = "O"
  boardDraw()
def boardDraw():
  print("1| "+moves[0][0]+" | "+moves[0][1]+" | "+moves[0][2]+" |")
  print(" |---+---+---|")
  print("2| "+moves[1][0]+" | "+moves[1][1]+" | "+moves[1][2]+" |")
  print(" |---+---+---|")
  print("3| "+moves[2][0]+" | "+moves[2][1]+" | "+moves[2][2]+" |")
  win("X")
  win("O")
  playerInput()

print("OK SO....\nPlayer 1 is X\nPlayer 2 is O\nGOOOOO!!")

boardDraw()

Upvotes: 0

Views: 94

Answers (2)

lenik
lenik

Reputation: 23508

You're clearly missing 2 winning cases:

moves[0][0] == moves[1][1] == moves[2][2]

and:

moves[0][2] == moves[1][1] == moves[2][0]

I'd rather rewrite your winning detection function as:

def win(letter) :
    for i in range(3) :  # rows
        if set(moves[i]) == set([letter]) :
            print( 'WIN' )
            quit()
    for x in zip(moves[0], moves[1], moves[2]) :  # columns
        if set(x) == set([letter]) :
            print( 'WIN' )
            quit()

    # you have completely missed the part below...
    if set(moves[i][i] for i in range(3)) == set([letter]) : # one diagonal
        print( 'WIN' )
        quit()
    if set(moves[i][3-i] for i in range(3)) == set([letter]) : # another diagonal
        print( 'WIN' )
        quit()

or even more compact:

def win(letter) :
    possible_wins = [ set(moves[i]) for i in rage(3) ] +  # rows
        [ set(x) for x in zip(moves[0], moves[1], moves[2]) ] +  # columns
        [ set(moves[i][i] for i in range(3)) ] +  # diagonal
        [ set(moves[i][3-i] for i in range(3)) ]  # another diagonal
    if any( p == set([letter]) for p in possible_wins ) :
        print( 'WIN' )
        quit()

Upvotes: 2

0x534f53
0x534f53

Reputation: 230

I'm assuming part of your problem has to do with the fact that in some of your if cluases, you check the first two squares or equal to letter, but not the third. Most objects in Python, except for things like None or 0 will be evaluated to True. So If there's a non-zero number in your array, or a character, it will be evaluated to True. This causes the program to think the player won when a line of only two things are formed.

Also, you six specific win conditions, and there are definitely more than the ones you specified to win in Tic Tac Toe. I would suggest a more logical (and readable) approach of consolidating the win scenarios together. For example, you can check all the horizontal and vertical win conditions in one loop:

for i in range(3):
    if ((moves[i][0] == moves[i][1] == moves[i][2] == letter) or
         (moves[0][i] == moves[1][i] == moves[2][i] == letter):
        # do win-condition stuff here

Finally, I would recommend checking for invalid moves, since your current code would just let the user over-write existing moves.

Upvotes: 2

Related Questions