Search code examples
python-3.xalgorithmtic-tac-toe

How to fix tic tac toe...it gives incorrect winner..(python)


I'm creating a simple tic-tac-toe game in the python shell...the program incorrectly assigns a winner no matter what i try to edit the code...I'm having a problem with my check() function

I tried scanning the vertical,then horizontal,then the diagonals of the gameboard after each player turn and then tell the winner if the first value matches with the other two...

i have also accounted errors for invalid input

Here's the full code:

import os
import time
board = [['-','-','-'],
         ['-','-','-'],
         ['-','-','-'],]

def markit(row,col,mark):
    try:
        if board[row-1][col-1]!='-':
            print("Already Marked!!")
            time.sleep(1)
        else:
            board[row-1][col-1]=mark
    except IndexError:
        print("Out of Range...Reverting back")
        time.sleep(1)
def reset():
    board = [['-','-','-'],
             ['-','-','-'],
             ['-','-','-'],]

def check():
    for i in range(len(board)):
        if board[i][i]==board[i-1][i-1] and board[i][i]!='-':
            print(board[i][i]," is a winner")
            time.sleep(1.5)
            y=input("Play Again?(y/n):")
            if y==y:
                reset()
            else:
                quit()
            break
    for i in range(len(board)):
        for j in range(len(board)):
            if board[j][i]==board[j][i-1] and board[j][i]!='-':
                print(board[j][i]," is a winner")
                time.sleep(1.5)
                y=input("Play Again?(y/n):")
                if y==y:
                    reset()
                else:
                    quit()
                break
    for i in range(len(board)):
        for j in range(len(board)):
            if board[i][j]==board[i][j-1] and board[i][j]!='-':
                print(board[i][j]," is a winner")
                time.sleep(1.5)
                y=input("Play Again?(y/n):")
                if y==y:
                    reset()
                else:
                    quit()
                break
while True:
    print("    1    2    3")
    for i in range(len(board)):
        print(i+1,board[i])      
    row=int(input("P1||Enter row:"))
    col=int(input("P1||Enter col:"))
    markit(row,col,mark='X')
    check()
    os.system('cls')
    print("    1    2    3")
    for i in range(len(board)):
        print(i+1,board[i])
    row=int(input("P2||Enter row:"))
    col=int(input("P2||Enter col:"))
    markit(row,col,mark='O') 
    check()
    os.system('cls')   

I expected to tell the winner properly but it tells a winner eventhough my first value doesn't match the other two.

and also if a player gives an invalid input...it returns an error and the match continues but he misses his turn!!...i also want to rectify this.


Solution

  • Briefly here are your mistakes.

    if board[i][j]==board[i][j-1] and board[i][j]!='-':
    

    Firstly, you dont need to check for board[i][j]!='-' at every instance. It would be sufficient to check if starting value in the row is not empty using if board[i][0] != '-': instead. Secondly, the line you wrote checks if 2 adjacent cells are equal in value, and if they are it calls the win. You need to check if all the 3 adjacent values are equal and then only call winner.

    To get this behaviour, one way would be to declare a boolean won. If any point, you get 2 adjacent values different, you set won = False and break.

    At the end of loop, if won == True you declare the winner and do things accordingly.

    Moreover, in your main method, you should invoke check() after printing the board, not before. Like this:

        row=int(input("P1||Enter row:"))
        col=int(input("P1||Enter col:"))
        markit(row,col,mark='X')
        os.system('cls')
        print("    1    2    3")
        for i in range(len(board)):
            print(i+1,board[i])
        check()
    

    I have fixed the horizontal check for you. You can try fixing the vertical and diagonal yourself.

    won = True
        for i in range(len(board)):
            if board[i][0] != '-':
                for j in range(len(board)-1):
                    if board[i][j]!=board[i][j+1]:
                        won = False
                        break
                if won:
                    print(board[i][i]," is a winner")
                    time.sleep(1.5)
                    y=input("Play Again?(y/n):")
                    if y=='y':
                        reset()
                    else:
                        quit()
                    return
                else:
                    won = True
        return
    

    To fix your marking method, take input inside your method markit() You can't use try-catch here because python lists are negative indexed as well.

    Use if conditions to ensure row/col is within the range. Below is a fix.

    def markit(mark):
        while True:
            row=int(input("P1||Enter row:"))
            col=int(input("P1||Enter col:"))
            if row <= 3 and row >= 1 and col <= 3 and col >= 1:
                if board[row-1][col-1]!='-':
                    print("Already Marked!!")
                else:
                    board[row-1][col-1]=mark
                    break