Beginner first project: tic-tac-toe

Hi, I am taking a course python essentials 1 in python institute. There is a final project in Module 4_tic-tac-toe. This is my try, but seems lots of bugs here…and room for improvement…

import random

def enter_move(board, moved):
    list = board
    list_moved = moved
    move = int(input("Enter your move: "))
    
    for i in range (len(list_moved)):
        if move == list_moved[i]:
            enter_move(board, moved)
        else:
            if (move == 1) or (move == 2) or (move == 3):
                col = move - 1
                list[0][col] = "O"
                print(*list, sep="\n")
                list_moved.append(move)
                victory_for(list, list_moved)
            elif (move == 4) or (move == 5) or (move == 6):
                col = move - 4
                list[1][col] = "O"
                print(*list, sep="\n")
                list_moved.append(move)
                victory_for(list, list_moved)
            elif (move == 7) or (move == 8) or (move == 9):
                col = move - 7
                list[2][col] = "O"
                print(*list, sep="\n")
                list_moved.append(move)
                victory_for(list, list_moved)
            else:
                print("discover bug here! ")
            

def victory_for(board, moved):
    list = board
    list_moved = moved
    
    if (len(list_moved) == 2) or (len(list_moved) == 4):
        draw_move(list, list_moved)
        
    elif (len(list_moved) == 3):
        enter_move(list, list_moved)
    elif (len(list_moved) == 5) or (len(list_moved) == 7):
        if (list[0][0] == "X" and list[0][1] == "X" and list[0][2] == "X") or (list[1][0] == "X" and list[1][1] == "X" and list[1][2] == "X") or (list[2][0] == "X" and list[2][1] == "X" and list[2][2] == "X"):
            print("Computer win! ")
        elif (list[0][0] == "X" and list[1][0] == "X" and list[2][0] == "X") or (list[0][1] == "X" and list[1][1] == "X" and list[2][1] == "X") or (list[0][2] == "X" and list[1][2] == "X" and list[2][2] == "X"):
            print("Computer win! ")
        elif (list[0][0] == "X" and list[1][1] == "X" and list[2][2] == "X") or (list[0][2] == "X" and list[1][1] == "X" and list[2][0] == "X"):
            print("Computer win! ")
        else:
            enter_move(list, list_moved)
            
    elif (len(list_moved) == 6) or (len(list_moved) == 8):
        if (list[0][0] == "O" and list[0][1] == "O" and list[0][2] == "O") or (list[1][0] == "O" and list[1][1] == "O" and list[1][2] == "O") or (list[2][0] == "O" and list[2][1] == "O" and list[2][2] == "O"):
            print("Player win! ")
        elif (list[0][0] == "O" and list[1][0] == "O" and list[2][0] == "O") or (list[0][1] == "O" and list[1][1] == "O" and list[2][1] == "O") or (list[0][2] == "O" and list[1][2] == "O" and list[2][2] == "O"):
            print("Player win! ")
        elif (list[0][0] == "O" and list[1][1] == "O" and list[2][2] == "O") or (list[0][2] == "O" and list[1][1] == "O" and list[2][0] == "O"):
            print("Player win! ")
        else:
            draw_move(list, list_moved)
    elif (len(list_moved) == 9):
        if (list[0][0] == "X" and list[0][1] == "X" and list[0][2] == "X") or (list[1][0] == "X" and list[1][1] == "X" and list[1][2] == "X") or (list[2][0] == "X" and list[2][1] == "X" and list[2][2] == "X"):
            print("Computer win! ")
        elif (list[0][0] == "X" and list[1][0] == "X" and list[2][0] == "X") or (list[0][1] == "X" and list[1][1] == "X" and list[2][1] == "X") or (list[0][2] == "X" and list[1][2] == "X" and list[2][2] == "X"):
            print("Computer win! ")
        elif (list[0][0] == "X" and list[1][1] == "X" and list[2][2] == "X") or (list[0][2] == "X" and list[1][1] == "X" and list[2][0] == "X"):
            print("Computer win! ")
        else:
            print("Draw, no one win the game! ")
            
    else:
        print("Discove bug, please fix it! ")
        

def draw_move(board, moved):
    list = board
    list_moved = moved
    
    move = int(random.randint(1,9))
    for i in range (len(list_moved)):
        if move == list_moved[i]:
            draw_move(board, moved)
    if (move == 1) or (move == 2) or (move == 3):
        col = move - 1
        list[0][col] = "X"
        print(f"Computer enter {move}! ")
        print(*list, sep="\n")
        list_moved.append(move)
        victory_for(list, list_moved)
    elif (move == 4) or (move == 5) or (move == 6):
        col = move - 4
        list[1][col] = "X"
        print(f"Computer enter {move}! ")
        print(*list, sep="\n")
        list_moved.append(move)
        victory_for(list, list_moved)
    elif (move == 7) or (move == 8) or (move == 9):
        col = move - 7
        list[2][col] = "X"
        print(f"Computer enter {move}! ")
        print(*list, sep="\n")
        list_moved.append(move)
        victory_for(list, list_moved)
    else:
        print("discover bug here! ")



board = [[1,2,3],[4,"X",6],[7,8,9]]
print(*board, sep="\n")
enter_move(board, [5])

The first thing I’d do, is to sort out the display, as it’s not very tidy.

This code simply fills in each available space with a O.

I don’t know for sure if what I have here is a sound base or not, because I’ve simply coded this off of the top of my head, so there could be a fundamental design error.

I’ll have a think about this and see if I can move it forward – it’ll be an interesting project for me, even if it’s of no help to you, but my hope is that it will be of some help for you.

def set_up():
    global row_one, row_two, row_three
    row_one = ['1', '2', '3']
    row_two = ['4', 'X', '6']
    row_three = ['7', '8', '9']


def display():
    print()
    print(*row_one)
    print(*row_two)
    print(*row_three)
    print()


def start():
    while True:
        display()
        o = input("> ")
        if o == 'stop':
            exit("End of game.")
        if o == '1' and o in row_one:
            position = row_one.index(o)
            row_one[position] = 'O'
        elif o == '2' and o in row_one:
            position = row_one.index(o)
            row_one[position] = 'O'
        elif o == '3' and o in row_one:
            position = row_one.index(o)
            row_one[position] = 'O'
        elif o == '4' and o in row_two:
            position = row_two.index(o)
            row_two[position] = 'O'
        elif o == '6' and o in row_two:
            position = row_two.index(o)
            row_two[position] = 'O'
        elif o == '7' and o in row_three:
            position = row_three.index(o)
            row_three[position] = 'O'
        elif o == '8' and o in row_three:
            position = row_three.index(o)
            row_three[position] = 'O'
        elif o == '9' and o in row_three:
            position = row_three.index(o)
            row_three[position] = 'O'
        else:
            print("Illegal move!")

set_up()
start()

To add: I have written a grid_check() function that can be run after the display(). So it will go like this:

def start():
    while True:
        display()
        result = grid_check()
        if result:
            exit(f"{result} win!")
        o = input("> ")
...

The function being:

def grid_check():
    winner = False
    if 'O' in row_one:
        score = 0
        for index, O_pos in enumerate(row_one, 1):
            if O_pos == 'O':
                score += index
                if score == 6:
                    winner = 'You'
    if 'O' in row_two:
        score = 1
        col = row_two.index('O')
        if row_one[col] == 'O':
            score += 1
        if row_three[col] == 'O':
            score += 1
        if score == 3:
            winner = 'You'

    if 'O' in row_three:
        score = 0
        for index, O_pos in enumerate(row_three, 1):
            if O_pos == 'O':
                score += index
                if score == 6:
                    winner = 'You'
    return winner

There’s still some way to go before it’s a working game, but I think you’ll be able to see where I’m going with this.

I think that you’ve over complicated things with the nested list objects.
Keep in mind: Flat is better than nested. So, only nest arrays if you absolutely need to.

I’ll not add anything more at this stage, because it’s your project and you’ll learn more by working this out for yourself, but if you do need some more help, then feel free to ask.

From The Zen of Python, by Tim Peters
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.

Just a few of the principles that I try to adhere to.