Tic Tac Toe In Python!?

Aryan PalAryan Pal
12 min read

PROJECT-0️⃣1️⃣

TIC TAC TOE (in python without any external module)

THIS IS MY FIRST PYTHON PROJECT, AND I WANTED TO PRESERVE IT FOREVER IN MY BLOG POST. THIS WAY, IT MAY ALSO HELP OTHER PEOPLE WHO READ THIS BLOG POST.

I KNOW I COULD HAVE USED GITHUB TO STORE THIS CODE, BUT AS I'M A BEGINNER, I NEED TO LEARN A LOT ABOUT GITHUB BEFORE I CAN USE IT PROPERLY.

In this, we're gonna make a tic tac toe game that will run on terminal.

I started by printing a basic welcome line and a confirmation to begin.

I did this by storing the user's input in a variable named "ch", which is essentially an abbreviation for "choice", representing the decision to start the game. I implemented a while loop that runs as long as "ch" is equal to "Y" or "y". This loop allows us to restart the game after a match is over.

After that, I printed some basic rules for the game and the layout of the game board. Following the rules, I assigned two variables, "p1" and "p2", to prompt the names of the two players. CODE TILL HERE IS AS:

ch=input("welcome to TIC TAC TOE press Y to continue or any other key to exit: ")
while ch=="y" or ch=="Y":
        print("RULES: \n 1. Cross will have first chance \n 2. The first to make a straight line either vertical,horizontal or diagonal, will win!! ") 
        print(" 3. The layout for the game is as followed (PLEASE MEMORISE IT):")
        print()
        print(" 7 | 8 | 9 ")
        print("---|---|---")
        print(" 4 | 5 | 6 ")
        print("---|---|---")
        print(" 1 | 2 | 3 ")
        print()
        print(" 4. You have to the input the value of corresponding position in order to make a move")
        print()
        p1=input("Enter the player 1 name  (X) : ")
        p2=input("Enter the player 2 name  (O) : ")

Here you will see some blank print() statements. I used them to create one-line spaces between two consecutive lines of text to make it more presentable in the terminal.

Next, I created two lists to store the state of a position. Essentially, these lists store data indicating which player marked their move at which position (i.e., 1, 2, 3, etc.). For example, if player 1 marks an 'X' on position 5, then the value of index 5 in the list representing the state of 'X' will change from 0 to 1. Here, 0 means that neither 'X' nor 'O' has made a move to that position, and 1 means the opposite.

THE TWO LISTS ARE AS:

        xstate=[0,0,0,0,0,0,0,0,0,0]
        ostate=[0,0,0,0,0,0,0,0,0,0]

These lists have 10 items each. This is because I wanted the index of the list to be the same as the number for the position, and since there are a total of nine positions, I had to include at least 10 items in each list to cover indices up to 9 for the code to work properly. Initially, both of them will have all values as 0, as no one has made any moves yet.

BEFORE MOVING AHEAD, LET ME EXPLAIN ALL THE FUNCTIONS I DEFINED TO USE IN THIS PROJECT:

1.threeSum()

This function calculates the sum of three integer values, as the built-in sum function only allows two arguments and I needed one that supports three arguments.

        def threeSum(a,b,c):
                        return a+b+c

2.checkWin()

This function takes 'xstate' and 'ostate' as arguments and checks if any player has won, returning a specific value for each player who has won and another value if no one has won.

The function utilizes all possible arrangements (i.e., vertical, horizontal, and diagonal) of X and O that could result in a win. For example, a player can win if their symbol is on positions 7, 8, and 9. We have a list named "winPos" that stores all possible arrangements in a list of lists of indices of 'xstate' and 'ostate' that could lead to a win.

It begins a "for loop" iterating over the list "winPos" with the variable "i", which iterates through the arrangements. These arrangements are lists. Within the loop, it checks if the sum of states of X at these arrangements is equal to 3. If it is three, it means the player with symbol X has won. It will print the name of that player, congratulate them, and return the value "1" to the function. Similarly, it checks for the symbol O, and if O wins, it congratulates the player and returns the value of "0" to the function. If no one wins, no if statements will execute, and it will return the value "-1" to the function. Now, the code for this is as follows:

        def checkWin(xstate,ostate):
            winPos=[[7,8,9],[4,5,6],[1,2,3],[7,4,1],[8,5,2],[9,6,3],[7,5,3,],[1,5,9]]
            for i in winPos:
                if (threeSum(xstate[i[0]],xstate[i[1]],xstate[i[2]]))==3:
                    print(p1,"is winner CONGRATULATIONS!!!")
                    return 1

                if (threeSum(ostate[i[0]],ostate[i[1]],ostate[i[2]]))==3:
                        print(p2,"is winner CONGRATULATIONS!!!")
                        return 0
            return -1

For better understanding, let's consider an example: suppose we have symbol 'X' at positions 7, 8, and 9. So, the values of xstate[7], xstate[8], and xstate[9] are all 1. When the value of 'i' is [7, 8, 9], the values of xstate[i[0]], xstate[i[1]], and xstate[i[2]] are all 1, following this logic:

xstate[i[0]] = xstate[7] = 1

xstate[i[1]] = xstate[8] = 1

xstate[i[2]] = xstate[9] = 1

Their sum is 3, so the condition for the if statement is true, and the winner is declared with a return value of 1 to the function. Similarly, if the player with symbol 'O' has any one of the winning positions, which I earlier referred to as arrangements, the winner will be declared with a return value of 0 to the function. If no one is in a position to win, the value of -1 will be returned to the function.

3.gameLayout()

This function also takes 'xstate' and 'ostate' as arguments and prints the game board after each move made, with the updated move reflected on the board. CODE:

        def gameLayout(xstate,ostate):
                one="X" if xstate[1] else ("O" if ostate[1] else " ")
                two="X" if xstate[2] else ("O" if ostate[2] else " ")
                three="X" if xstate[3] else ("O" if ostate[3] else " ")
                four ="X" if xstate[4] else ("O" if ostate[4] else " ") 
                five="X" if xstate[5] else ("O" if ostate[5] else " ")
                six="X" if xstate[6] else ("O" if ostate[6] else " ")
                sev="X" if xstate[7] else ("O" if ostate[7] else " ")
                eight ="X" if xstate[8] else ("O" if ostate[8] else " ")
                nine="X" if xstate[9] else ("O" if ostate[9] else " ")
                print(f" {sev} | {eight} | {nine} ")
                print("---|---|---")
                print(f" {four} | {five} | {six} ")
                print("---|---|---")
                print(f" {one} | {two} | {three} ")

I used if statements to print the game board with the updated move. As you can see, there are three f-strings in the format of gameLayout, each containing different variables corresponding to their positions on the game board. Within each variable, we have if statements which print the symbol if its state is 1, indicating a move made by the player with that symbol.

The if statements are structured to first check the value of xstate at the particular position where the if statement is written. If xstate has a value of 1 at that position, indicating a move by player X, the condition for the if statement is considered True, resulting in an 'X' being printed at that position. If xstate is 0, indicating no move by player X, the code then checks if player O has made a move at that position by examining the value of ostate. If ostate has a value of 1, indicating a move by player O, an 'O' is printed at that position. Otherwise, if neither player has made a move at that position (ostate value is 0), a blank space is printed to represent an empty position.

For example, let's consider the variable named 'sev'. The interpreter first checks xstate[7]. If player X has made a move at position 7 and xstate[7] is 1, the condition for the if statement will print 'X' at position 7. If player X hasn't moved to position 7 (xstate[7] = 0), the condition for the if statement will be False, and it will not print 'X' at that position. Instead, it will execute the code after the else statement. The else statement then checks ostate[7]. If ostate[7] is 1, indicating a move by player O, 'O' is printed at position 7. If player O hasn't moved to position 7 (ostate[7] = 0), the condition for the if statement will be False, and it will not print the symbol 'O' at that position. Ultimately, if neither player has made a move at position 7, it will execute the last else statement, printing a blank space to represent an empty position.

Similarly, this process checks every variable for every position and prints the symbol that has made a move at that position, updating the game board accordingly.

Now that we have discussed all the functions defined for this program, I've defined a variable 'turn' to store the value 1 or 0. When the value is 1, it's player 1's turn (symbol X); when it's 0, it's player 2's turn (symbol O). Another variable 'n' stores the value 0, representing the number of moves both players combinely made that will accordingly increase whenever a player make its move. the maximum number of moves both players can make combinely is 9. If both players have made 9 moves and no one has won, the match is drawn. In this case, the program will prompt players if they want to restart the game or exit.

CODE:

        turn=1 # 1 for X and 0 for O
        n=0
        while n<9:


            if turn==1:
                print("chance of ",p1)
                value=int(input("enter the value to make move for X: "))
                xstate[value]=1
                turn=0
                n+=1

            else:
                print("chance of ",p2)
                value=int(input("enter the value to make move for O: "))
                ostate[value]=1
                turn=1
                n+=1
            gameLayout(xstate,ostate)

            checkw=checkWin(xstate,ostate) 

            if checkw!=-1:
                break
        else:
              print("MATCH DRAW") 
              ch=input("press Y to restart or any other key to exit: ")

Here, the while loop checks if "n" is smaller than 9, so that it exits the loop when a match is drawn. If the match is not drawn yet, the if statement checks if turn is equal to 1, which means it's player 1's turn (with symbol X). If it's true, it prompts that it's player 1's turn, asks for the position the player wants to make a move to, and stores this in a variable named "value". After this, it changes the value of the index of xstate equal to "value" to 1, changes the value of "turn" to 0 for player 2's turn, and increases the value of "n" by 1 to track that one move is done. If turn is not equal to 1, it executes the else statement, prompting that it's player 2's turn, asking for a move, and updating ostate accordingly.

After that, we call the function gameLayout(xstate, ostate) to print the game board with the most recent moves reflected on it, along with previous moves.

Now, let's consider an example: Suppose player 1 has previously made moves at positions 4, 8, and 7, and player 2 has made moves at positions 2, 3, and 5. So, the values of xstate[4], xstate[8], xstate[7], ostate[2], ostate[3], and ostate[5] are all 1. Our gameLayout() function will print 'X' at positions 4, 7, and 8, and 'O' at positions 2, 3, and 5. The board will look somewhat like this:

      | X | X |   |
      -------------
      | X | O |   |
      -------------
      |   | O | O |

Now, it's player 1's turn, and they make a move at a new position (i.e., 9). This updates the value of xstate for that position to 1, and the game board will be printed with all the previous moves along with this new move. The board will look like this:

      | X | X | X |
      -------------
      | X | O |   |
      -------------
      |   | O | O |

Now, the checkWin() function is called after the gameLayout() function. It checks if either player is in a position to win. Since player 1 is winning, the checkWin() function checks if 'X' is in a winning arrangement. Here, 'X' is on positions 7, 8, and 9, which makes the condition true. The function declares player 1 as the winner and returns the value 1.

The next if statement checks if the value of "checkw" is not equal to -1, which is true because "checkw" will be -1 only if no one has won. Here, player 1 has won, so the condition is true, and the second while loop stops looping because the break statement is executed. If no one wins and both players have made all 9 moves, the value of "n" is 9, and the while loop exits. The else statement is then executed, declaring that the match has ended in a draw and prompts players if they want to restart the game or exit. If the player enters "y" or "Y", the first while loop restarts the game. If the player enters any other key, "ch" will no longer be "y" or "Y", and the first while loop will not execute. In this case, the else statement will execute, ultimately prompting the game to exit with the message "Thank you, have a nice day." The else statement is:

else:

print('Thank you have a nice day.')

The exact code with proper indentation:

#this is a fun  project that aims an interactive game based on tic tac toe. 
#this game will have semi graphical interface on terminal.

ch=input("welcome to TIC TAC TOE press Y to continue or any other key to exit: ")
while ch=="y" or ch=="Y":
        print("RULES: \n 1. Cross will have first chance \n 2. The first to make a straight line either vertical,horizontal or diagonal, will win!! ") 
        print(" 3. The layout for the game is as followed (PLEASE MEMORISE IT):")
        print()
        print(" 7 | 8 | 9 ")
        print("---|---|---")
        print(" 4 | 5 | 6 ")
        print("---|---|---")
        print(" 1 | 2 | 3 ")
        print()
        print(" 4. You have to the input the value of corresponding position in order to make a move")
        print()
        p1=input("Enter the player 1 name  (X) : ")
        p2=input("Enter the player 2 name  (O) : ")



        xstate=[0,0,0,0,0,0,0,0,0,0]
        ostate=[0,0,0,0,0,0,0,0,0,0]

        def threeSum(a,b,c):
                        return a+b+c

        def checkWin(xstate,ostate):
            winPos=[[7,8,9],[4,5,6],[1,2,3],[7,4,1],[8,5,2],[9,6,3],[7,5,3,],[1,5,9]]
            for i in winPos:
                if (threeSum(xstate[i[0]],xstate[i[1]],xstate[i[2]]))==3:
                    print(p1,"is winner CONGRATULATIONS!!!")
                    return 1

                if (threeSum(ostate[i[0]],ostate[i[1]],ostate[i[2]]))==3:
                        print(p2,"is winner CONGRATULATIONS!!!")
                        return 0
            return -1

        def gameLayout(xstate,ostate):
                one="X" if xstate[1] else ("O" if ostate[1] else " ")
                two="X" if xstate[2] else ("O" if ostate[2] else " ")
                three="X" if xstate[3] else ("O" if ostate[3] else " ")
                four ="X" if xstate[4] else ("O" if ostate[4] else " ") 
                five="X" if xstate[5] else ("O" if ostate[5] else " ")
                six="X" if xstate[6] else ("O" if ostate[6] else " ")
                sev="X" if xstate[7] else ("O" if ostate[7] else " ")
                eight ="X" if xstate[8] else ("O" if ostate[8] else " ")
                nine="X" if xstate[9] else ("O" if ostate[9] else " ")
                print(f" {sev} | {eight} | {nine} ")
                print("---|---|---")
                print(f" {four} | {five} | {six} ")
                print("---|---|---")
                print(f" {one} | {two} | {three} ")



        turn=1 # 1 for X and 0 for O
        n=0
        while n<9:


            if turn==1:
                print("chance of ",p1)
                value=int(input("enter the value to make move for X: "))
                xstate[value]=1
                turn=0
                n+=1

            else:
                print("chance of ",p2)
                value=int(input("enter the value to make move for O: "))
                ostate[value]=1
                turn=1
                n+=1
            gameLayout(xstate,ostate)

            checkw=checkWin(xstate,ostate) 

            if checkw!=-1:
                break
        else:
              print("MATCH DRAW") 
              ch=input("press Y to restart or any other key to exit: ")

        if checkw!=-1:
              ch=input("press Y to restart or any other key to exit: ")
else:
    print('Thank you have a nice day.')

And that's how I made a Tic Tac Toe game in Python without using any external modules.

Thank you so much for reading till here. May your day go well.

👋 Hello, I'm Aryan Pal, a student and a content creator, aspired for tech and its community.

🥰 If you liked this article, consider sharing it.

1
Subscribe to my newsletter

Read articles from Aryan Pal directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Aryan Pal
Aryan Pal

Just another teenager with big dreams of becoming a successful in Tech field. But here's the exciting part: I absolutely LOVE what I do and what I want to achieve!