Tic-tac-toe in Python
Tags: beginners, python, tutorial, gamedev
Published: 2021-11-08 17:23:31

Today we are faced with the task of writing a game of tic-tac-toe on python. Recall that tic-tac-toe is a logical game for two players on a 3x3 square field.

To begin with, we will set the field. Our field will be a one-dimensional list with numbers from 1 to 9. To create it, we will use the **range()** function

```board = range(1,10)```

Now let's write a function that will output our field in the usual format

```def draw_board(board):
    print "-------------"
    for i in range(3):
        print "|", board[0+i*3], "|", board[1+i*3], "|", board[2+i*3], "|"
        print "-------------"```

It's time to allow users to enter data into our game. Writing the **take_input** function

```ef take_input(player_token):
    valid = False
    while not valid:
        player_answer = raw_input("Where do we put " + player_token+"? ")
        try:
            player_answer = int(player_answer)
except:
print "Incorrect input. Are you sure you entered a number?"
continue
        if player_answer >= 1 and player_answer <= 9:
            if (str(board[player_answer-1]) not in "XO"):
                board[player_answer-1] = player_token
                valid = True
            else:
print "This cell is already occupied"
        else:
            print "Incorrect input. Enter a number from 1 to 9 to be like."```

As you can see, the **take_input** function takes the **player_token** parameter - a cross or a toe, depending on whose turn it is now. We need to limit the user's choice to numbers from 1 to 9. To do this, we use the try/except and if/else constructs to make sure that the selected cell is not occupied. Note that the take_input function does not return any value, but only modifies the existing board list.

It remains to write a function for checking the playing field. Let's call this function **check_win**.

```def check_win(board):
    win_coord = ((0,1,2),(3,4,5),(6,7,8),(0,3,6),(1,4,7),(2,5,8),(0,4,8),(2,4,6))
    for each in win_coord:
        if board[each[0]] == board[each[1]] == board[each[2]]:
            return board[each[0]]
    return False```

Checking the results of the tic-tac-toe game is a fairly common programming task. As often happens, the same task in programming can be solved in several ways. In this case, we simply created a tuple with the winning coordinates and ran a for loop through it. If the symbols in all three specified cells are equal, we return the winning symbol, otherwise, we return the value False. At the same time, it is important to remember that not an empty string (our winning symbol) when converting it to a logical type, it will return True (we will need this in the future).

It remains to create the **main** function, in which we will put together all the described functions.

```def main(board):
    counter = 0
    win = False
    while not win:
        draw_board(board)
        if counter % 2 == 0:
            take_input("X")
        else:
            take_input("O")
        counter += 1
        if counter > 4:
            tmp = check_win(board)
            if tmp:
                print tmp, "won!"
                win = True
                break
        if counter == 9:
            print "drawn game!"
            break
    draw_board(board)def main(board):
    counter = 0
    win = False
    while not win:
        draw_board(board)
        if counter % 2 == 0:
            take_input("X")
        else:
            take_input("O")
        counter += 1
        if counter > 4:
            tmp = check_win(board)
            if tmp:
                print tmp, "won!"
                win = True
                break
        if counter == 9:
            print "drawn game!"
            break
    draw_board(board)```

The operation of the main function is extremely clear, except that lines 45 and 46 may cause misunderstanding. We are waiting for the counter variable to become greater than 4 to avoid a deliberately unnecessary call to the check_win function (no one can win for sure until the fifth movie). The tmp variable was created again in order not to call the check_in function once again, we just "remember" its value and, if necessary, use it on line 48. The benefits of this approach are not so noticeable when working with small amounts of data, but in general, such savings in processor time are good practice.

Now we can safely play by running the main(board)

Have a good game!