Search code examples
pythonpython-3.xtic-tac-toe

python tic tac toe game stop and value check function return error


I'm trying to run a simple tic tac toe game script in python. I use a list to track in which cell of the table there is a "X", an "Y" or nothing. to set the value you have to input the coordinate of the cell you want to play in and if the coordinate doesn't exist or it is already occupied, you get an error message and the game ask you to input again. the problem is that whenever i input a number, i get the error message and the program stop. I can't spot the error, can anyone help me? the cose is the following:

class Tris:
    def __init__(self, xo = True):
        self.tabella = [0, 0, 0,
                        0, 0, 0,
                        0, 0, 0]        # -this is the starting table
        self.xo = xo                    # -to check if it is "x" turn or "o" turn
        self.finito = False             # -to check if the game is unfinished



                                        # -just to print grafic style of the table: ignore that
    def print_tabella(self):
        giocatore = "X" if self.xo else "Y"
        tabella_convertita = self.tabella
        for n, i in enumerate(tabella_convertita):
            if i == 0:
                tabella_convertita[n] = " "
            elif i == 1:
                tabella_convertita[n] = "X"
            else:
                tabella_convertita[n] = "O"
        t1 = "|".join(str(i) for i in tabella_convertita[0:3])
        t2 = "|".join(str(i) for i in tabella_convertita[3:6])
        t3 = "|".join(str(i) for i in tabella_convertita[6:9])
        spazio_casella = "-+-+-"
        testo_segnaposto = """use following numbers to set X/O:
                    0|1|2
                    -+-+-
                    3|4|5
                    -+-+-
                    6|7|8"""
        turno_di = f"turn : {giocatore}"
        tab_finale = t1 + "\n" + spazio_casella + "\n" + t2 + "\n" + spazio_casella + "\n" + t3 + "\n"+ testo_segnaposto +"\n" + turno_di
        return tab_finale

    def controlla(self, casella):
        if casella.isalpha():       # check if the input is not numerical
            return False
        else:
            if not 0 <= int(casella) <= 8:      # the value must be between 0 and 8
                return False
            else:
                return self.tabella[int(casella)] == 0      # the cell must not be containing another symbol

    def is_winner(self): # check if there is a row, a column or a diagonal with the same symbol
        lista_righe = [[self.tabella[0], self.tabella[1], self.tabella[2]], [self.tabella[3], self.tabella[4], self.tabella[5]],
                         [self.tabella[6], self.tabella[7], self.tabella[8]]]
        lista_colonne = [[self.tabella[0], self.tabella[3], self.tabella[6]], [self.tabella[1], self.tabella[4], self.tabella[7]],
                         [self.tabella[2], self.tabella[5], self.tabella[8]]]
        lista_diagonali = [[self.tabella[0], self.tabella[4], self.tabella[8]], [self.tabella[2], self.tabella[4], self.tabella[6]], ]
        lista_vincite = [lista_colonne, lista_diagonali, lista_righe]
        winner = False
        for i in lista_vincite:
            for liste in i:
                if liste[0] == liste[1] and liste[1] == liste[2] and liste[0] != 0:
                    winner = True
                    break
        return winner



    def gioca(self):
        while self.finito == False:                                 # check if the game is finished
            if self.is_winner():                                    # check if there is a winner
                self.finito = True
                break
            print(self.print_tabella())                             # print the table in grafic form
            inp = input("choose a number to set X/O: ")
            if not self.controlla(inp):                             # check if the input is in valid form
                print("invalid number or cell already used")        # or if the chosen cell is available
            else:
                self.xo = not self.xo                               # to track if it is X turn or O turn
                if self.xo:
                    self.tabella[int(inp)] = 1
                else:
                    self.tabella[int(inp)] = 2

gioco_tris = Tris()
gioco_tris.gioca()

Solution

  • The problem is that print_tabella mutates tabella. When you do:

        tabella_convertita = self.tabella
    

    ... you are not creating a new list, but just a synonym for self.tabella. So whatever you do to tabella_convertita is happening to self.tabella: the numeric content gets replaced with characters.

    Instead do:

        tabella_convertita = self.tabella[:]