Skip to content

A simple game of Tic Tac Toe in Python (User vs CPU). Python libraries used: random

Notifications You must be signed in to change notification settings

WindJammer6/2.-Tic-Tac-Toe-Game-Python

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 

Repository files navigation

Tic-Tac-Toe-Game-Python-:x::o:

A simple game of Tic Tac Toe in Python (User vs CPU). Python libraries used: random


Special Thanks

Special thanks to harvestingmoon, for helping me check for the many bugs and solving them during this project :)


Thoughts on starting this project

My second programming project, in Python. My approach to this traditional python project is through dictionaries (key, value relationships), and replacing the numbered values based on the key the user typed in to 'X' and 'O' to indicate that is the spot the player has chosen.


Computer program used for coding: VS Code


Code description

Let's start with:

  1. Imported Libraries
  2. Defining the dictionary
  3. Self-defined functions
  4. Main code

1. Imported Libraries

import random

Importing the 'random' library.



2. Defining the dictionary

spots = {1: ' 1 ', 2: ' 2 ', 3: ' 3 ', 4: ' 4 ', 5: ' 5 ', 6: ' 6 ', 7: ' 7 ', 8: ' 8 ', 9: ' 9 '}

The 'spots' dictionary consists of 9 key value pair, representing a slot in the tic-tac-toe table, which the 'draw_board()' function uses to print out the table visually.



3. Self-defined functions

def user_play():
    while True:
        try: 
            n = input("Choose position: ")
            if spots[int(n)] in [' 1 ', ' 2 ', ' 3 ', ' 4 ',' 5 ', ' 6 ',' 7 ', ' 8 ',' 9 ']:
                break
        except Exception:
            print("That position is not available!")
    return n

The 'user_play()' function is to get the user's input, as well as checking if that input is the desirable input of an int 1 to 9. That would be the slot the user chose to put in, and the loop will also check if that slot is already filled by either the user or the computer already. If that spot the computer chose already has an 'X' or 'O' as its value, the while loop will prompt the user for another input, until a desired input is produced.

def computer_play():
    while True:
        try: 
            n = random.randint(1, 9)
            if spots[int(n)] in [' 1 ', ' 2 ', ' 3 ', ' 4 ',' 5 ', ' 6 ',' 7 ', ' 8 ',' 9 ']:
                break
        except Exception:
            print("That position is not available!")
    return n

The 'computer_play()' function is to get a random, computer-generated input, from the number 1 to 9 that would be the slots the computer chose to put in, as well as checking if that slot is already filled by either the user or the computer already. If that spot the computer chose already has an 'X' or 'O' as its value, the while loop will prompt the computer for another random input, until a desired input is produced.


The function then returns the generated input back to the main code.


def user_winner(spots):
    if spots[1] == ' O ' and spots[2] == ' O ' and spots[3] == ' O ':
        print("You won!")
        return True 
    if spots[4] == ' O ' and spots[5] == ' O ' and spots[6] == ' O ':
        print("You won!")
        return True 
    if spots[7] == ' O ' and spots[8] == ' O ' and spots[9] == ' O ':
        print("You won!")
        return True 
    if spots[1] == ' O ' and spots[5] == ' O ' and spots[9] == ' O ':
        print("You won!")
        return True 
    if spots[3] == ' O ' and spots[5] == ' O ' and spots[7] == ' O ':
        print("You won!")
        return True  
    if spots[1] == ' O ' and spots[4] == ' O ' and spots[7] == ' O ':
        print("You won!")
        return True 
    if spots[2] == ' O ' and spots[5] == ' O ' and spots[8] == ' O ':
        print("You won!")
        return True 
    if spots[3] == ' O ' and spots[6] == ' O ' and spots[9] == ' O ':
        print("You won!")
        return True
    return False

The 'user_winner()' function is to check every round if the user has won after user has given an input. There is 8 possible combinations for the user to win. If these 3 keys in the dictionary are filled with an 'O', then the user is declared a winner and returns True, else it returns False.


def CPU_winner(spots):
    if spots[1] == ' X ' and spots[2] == ' X ' and spots[3] == ' X ':
        print("You lost!")
        return True 
    if spots[4] == ' X ' and spots[5] == ' X ' and spots[6] == ' X ':
        print("You lost!")
        return True 
    if spots[7] == ' X ' and spots[8] == ' X ' and spots[9] == ' X ':
        print("You lost!")
        return True 
    if spots[1] == ' X ' and spots[5] == ' X ' and spots[9] == ' X ':
        print("You lost!")
        return True 
    if spots[3] == ' X ' and spots[5] == ' X ' and spots[7] == ' X ':
        print("You lost!")
        return True 
    if spots[1] == ' X ' and spots[4] == ' X ' and spots[7] == ' X ':
        print("You lost!")
        return True 
    if spots[2] == ' X ' and spots[5] == ' X ' and spots[8] == ' X ':
        print("You lost!")
        return True 
    if spots[3] == ' X ' and spots[6] == ' X ' and spots[9] == ' X ':
        print("You lost!")
        return True 
    return False

Similarly, the 'CPU_winner()' function is to check every round if the CPU has won after user has given an input. There is 8 possible combinations for the CPU to win. If these 3 keys in the dictionary are filled with an 'X', then the CPU is declared a winner and returns True, else it returns False.


def full_board():
    if (spots[1] == (' X ') or spots[1] == (' O ')) and (spots[2] == (' X ') or spots[2] == (' O '))  and (spots[3] == (' X ') or spots[3] == (' O '))  and (spots[4] == (' X ') or spots[4] == (' O '))  and (spots[5] == (' X ') or spots[5] == (' O '))  and (spots[6] == (' X ') or spots[6] == (' O '))  and (spots[7] == (' X ') or spots[7] == (' O '))  and (spots[8] == (' X ') or spots[8] == (' O '))  and (spots[9] == (' X ') or spots[9] == (' O ')) :
        return True
    return False

The 'full_board()' function is to check every round both after the user has made its move and the computer has made its move if the tic-tac-toe dictionary table has become full. If it is, this function will return True, else it returns False. (This number of conditions for the if statement is unnecessarily long... I believe there should be some way to shorten it)


def draw_board(spots):
    print(f"{spots[1]},{spots[2]},{spots[3]}\n{spots[4]},{spots[5]},{spots[6]}\n{spots[7]},{spots[8]},{spots[9]}")

The 'draw_board()' function basically prints out a visual look of the tic-tac-toe table using the dictionary key-value pairs. This makes it easy to switch the contents in each slot based on the user/CPU input and re-print it out visually when updating the board to the user.



spots = {1: ' 1 ', 2: ' 2 ', 3: ' 3 ', 4: ' 4 ', 5: ' 5 ', 6: ' 6 ', 7: ' 7 ', 8: ' 8 ', 9: ' 9 '}

The 'spots' dictionary consists of 9 key value pair, representing a slot in the tic-tac-toe table, which the 'draw_board()' function uses to print out the table visually.



4. Main code

def main(): 

    print('Welcome to a game of Tic Tac Toe! (User vs CPU)\n')
    print('Select a position by typing the corresponding number!')
    draw_board(spots)

    playing = True

    while playing:
        x = user_play()
        spots[int(x)] = ' O '
        draw_board(spots)

        if user_winner(spots) is True:
            break
            
        if full_board() is True:
            print("Its a tie!")
            break

        y = computer_play()
        spots[int(y)] = ' X '
        print(f"Computer chose: {y}")
        draw_board(spots)

        if CPU_winner(spots) is True:
            break

        if full_board() is True:
            print("Its a tie!")
            break

'while playing' sets a while loop of the game, where user input is taken (and checked at the same time in the 'user_play()' function), and replace the value of the key (user input) to 'O' and then drawing the updated board with the 'O'.

Then the code will check the user win condition. If True, the code will exit the loop and print user win. If False, nothing happens and the code continues.

Then the code will also check if the board is full. If all the key-value pairs in the 'spots' dictionaries are filled with 'X' and 'O', then it is a full board and code will print 'Its a tie!'

The computer input is now taken (and checked at the same time in the 'computer_play()' function), and replace the value of the key (computer input) to 'X' and then drawing the updated board as well as showing the user what number the computer has chosen.

Then the code will check the computer win condition. If True, the code will exit the loop and print user has lost. If False, nothing happens and the code continues.

Then the code will also check if the board is full. If all the key-value pairs in the 'spots' dictionaries are filled with 'X' and 'O', then it is a full board and code will print 'Its a tie!'

These lines of code will keep looping until the user/computer has won, or it is a full board.



Output

Welcome to a game of Tic Tac Toe! (User vs CPU)

Select a position by typing the corresponding number!
 1 , 2 , 3
 4 , 5 , 6
 7 , 8 , 9
Choose position: 1
 O , 2 , 3 
 4 , 5 , 6
 7 , 8 , 9
Computer chose: 9
 O , 2 , 3
 4 , 5 , 6
 7 , 8 , X
Choose position: 5
 O , 2 , 3 
 4 , O , 6
 7 , 8 , X
Computer chose: 7
 O , 2 , 3
 4 , O , 6
 X , 8 , X
Choose position: 8
 O , 2 , 3 
 4 , O , 6
 X , O , X
Computer chose: 3
 O , 2 , X
 4 , O , 6
 X , O , X
Choose position: 6
 O , 2 , X 
 X , O , X
Computer chose: 2
 O , X , X
 4 , O , O
 X , O , X
Choose position: 4
 O , X , X
 O , O , O
 X , O , X
You won!


Thoughts after the project

This project took me 3 days to complete as I struggled with the loops as I am still grasping the understanding of loops in programming, as well as creating conditions.

Furthermore, this expanded my knowledge on dictionaries, and the functionality of key-pair values.

This project also stretched the way on how I think as a programmer, such as being able to visualise the many scenarios that can occur in tic-tac-toe such as full board, and winning combinations, and account for them in my code.


To be improved:

  • Too many if loops to check for 'user_winner()', 'CPU_winner()', should be possible to shorten them. I have learnt that in coding that you should always try not to copy-paste your code and there is usually a way to shorten them e.g. into a loop, etc (based on what I know)
  • Like all code, more features can definitely be added to make the game more interactive like making the CPU smart, instead of making random choices on empty spaces on the board, making it easy for user to win.

Have a gif:

Semantic description of image

About

A simple game of Tic Tac Toe in Python (User vs CPU). Python libraries used: random

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages