Tic Tac Toe Game in Python

Words
750
Reading
4 min
Listen
Play
5y

What's up HIVE Community, 👋👋 For quite some time now I have been procrastinating getting started with sharing some different beginner programming projects.

I decided to start with sharing this small Python Project I was working on yesterday. It is pretty straightforward, probably some of you have tried the implementing the game out in different programming languages.

I will provide the image files at the end of the post for anyone interested in aggregating the different code blocks and giving the game a try.

I am currently working on my Python skills, will be sharing more projects in the community for anyone also learning Python.

image.png

Tic-Tac-Toe | Python

Steps To Build a Python Tic Tac Toe Game

  1. Create the display window for the game.
  2. Draw the grid on the canvas where to play the Tic Tac Toe Game.
  3. Draw a status bar below the canvas to show which player's turn it is and who wins the game.
  4. Reset the game when a person wins or both players draw.

1. Initializing the Game Components

  • Start by importing the pygame and time library.
import pygame as pg,sys
from pygame.locals import *
import time
  • The time library provides us with the time.sleep() method to pause the game.
  • Also initialize all the Global Variables to be used in the reset of the code.
#initialize the global variables

XO = 'x'
winner = None
draw = False
width = 400
height = 400
white = (255, 255, 255)
line_color = (10,10,10)

#TicTacToe 3x3 board
TTT = [[None]*3,[None]*3,[None]*3]
  • TTT is the main 3×3 Tic Tac Toe board. The height and width of the canvas where to play the game are 400×400.

2. Intializing the Display Window

  • Use pygame to initialize a new window on where to play the game.
pg.init()
fps = 30
CLOCK = pg.time.Clock()
  • The pg.display.set_mode() initializes the display, reference it with the
    screen variable. This screen variable will be used to draw something on the display.
screen = pg.display.set_mode((width, height+100),0,32)
  • The pg.display.set_caption() method is used to set a name that will appear at
    the top of the display window.
pg.display.set_caption("Tic Tac Toe")

3. Loading and Transforming images

The game requires 3 Images:

  • Opening Image which loads when the game start or resets.
  • X Image which will draw Xwhen mouse clicks on the game grid.
  • O Image which will draw O when mouse clicks on the game grid.
#Loading the Images
opening = pg.image.load('opening.png')
x_img = pg.image.load('x.png')
o_img = pg.image.load('o.png')

The images have to be resized to fit in the display window previously initialized.

#Resizing images
x_img = pg.transform.scale(x_img, (80,80))
o_img = pg.transform.scale(o_img, (80,80))
opening = pg.transform.scale(opening, (width, height+100))

4. Defining The Necessary Functions

game_opening() Function that Starts and Restarts the game

  • pygame provides the function blit() which allows drawing an image on top of another image.

  • Draw the opening image, after which the display has to be always updated using pg.display.update()

  • Using time.sleep(1) wait for 1 second and fill the screen with white color

  • To make the 3x3 grid, draw 2 horizonatal and vertical lines on the white background.

# Function that starts and restarts the game
def game_opening():
    screen.blit(opening,(0,0))
    pg.display.update()
    time.sleep(1)
    screen.fill(white)
    
    # Drawing vertical lines
    pg.draw.line(screen,line_color,(width/3,0),(width/3, height),7)
    pg.draw.line(screen,line_color,(width/3*2,0),(width/3*2, height),7)
    
    # Drawing horizontal lines
    pg.draw.line(screen,line_color,(0,height/3),(width, height/3),7)
    pg.draw.line(screen,line_color,(0,height/3*2),(width, height/3*2),7)
    draw_status()

draw_status() Function

  • The function draws a black rectangle where the update status updates, showing which player’s turn is it and whether the game ends or draws.
def draw_status():
    global draw

    if winner is None:
        message = XO.upper() + "'s Turn"
    else:
        message = winner.upper() + " won!"
    if draw:
        message = 'Game Draw!'

    font = pg.font.Font(None, 30)
    text = font.render(message, 1, (255, 255, 255))

    # copy the rendered message onto the board
    screen.fill ((0, 0, 0), (0, 400, 500, 100))
    text_rect = text.get_rect(center=(width/2, 500-50))
    screen.blit(text, text_rect)
    pg.display.update()

check_win() Function

  • The function checks the Tic Tac Toe board to see all the marks of
    ‘X’ and ‘O’.
  • It calculates whether a player has won the game or not. They can
    either win when the player has marked 3 consecutive marks in a row, column
    or diagonally.
  • This function is called every time when a mark ‘X’ or
    ‘O’ is drawn on the board.
def check_win():
    global TTT, winner,draw

    # check for winning rows
    for row in range (0,3):
        if ((TTT [row][0] == TTT[row][1] == TTT[row][2]) and(TTT [row][0] is not None)):
            # this row won
            winner = TTT[row][0]
            pg.draw.line(screen, (250,0,0), (0, (row + 1)*height/3 -height/6),\
                              (width, (row + 1)*height/3 - height/6 ), 4)
            break

    # check for winning columns
    for col in range (0, 3):
        if (TTT[0][col] == TTT[1][col] == TTT[2][col]) and (TTT[0][col] is not None):
            # this column won
            winner = TTT[0][col]
            #draw winning line
            pg.draw.line (screen, (250,0,0),((col + 1)* width/3 - width/6, 0),\
                          ((col + 1)* width/3 - width/6, height), 4)
            break

    # check for diagonal winners
    if (TTT[0][0] == TTT[1][1] == TTT[2][2]) and (TTT[0][0] is not None):
        # game won diagonally left to right
        winner = TTT[0][0]
        pg.draw.line (screen, (250,70,70), (50, 50), (350, 350), 4)
       

    if (TTT[0][2] == TTT[1][1] == TTT[2][0]) and (TTT[0][2] is not None):
        # game won diagonally right to left
        winner = TTT[0][2]
        pg.draw.line (screen, (250,70,70), (350, 50), (50, 350), 4)
    
    if(all([all(row) for row in TTT]) and winner is None ):
        draw = True
    draw_status()

drawXO(row, col) Function

  • The function takes the row and column where the mouse is
    clicked and then it draws the ‘X’ or ‘O’ mark.
  • Calculate the x and y coordinates of the starting point from where to draw the png image of the mark.
def drawXO(row, col):
    global TTT, XO

    if row == 1:
        posx = 30
        
    if row == 2:
        posx = width/3 + 30

    if row == 3:
        posx = width/3*2 + 30

    if col == 1:
        posy = 30

    if col == 2:
        posy = height/3 + 30

    if col == 3:
        posy = height/3*2 + 30
    
    TTT[row-1][col-1] = XO

    if (XO == 'x'):
        screen.blit(x_img,(posy, posx))
        XO = 'o'
    else:
        screen.blit(o_img,(posy, posx))
        XO = 'x'
    
    pg.display.update()

userClick() Function

  • The function is triggered every time the user presses the mouse button.
  • When the user clicks the mouse, first take the x and y coordinates of where the mouse is clicked on the display window and then if that place is not occupied draw the ‘XO’ on the canvas.
  • Check if the player wins or not after drawing ‘XO’ on the board.
def userClick():

    # Get coordinates of mouse click
    x,y = pg.mouse.get_pos()

    # Get column of mouse click
    if (x < width / 3):
        col = 1
    elif (x < width/3 * 2 ):
        col = 2
    elif (x < width):
        col = 3
    else:
        col = None

    # Get row of mouse click
    if (y < height/3):
        row = 1
    elif (y < height / 3 * 2):
        row = 2
    elif (y < height):
        row = 3
    else:
        row = None
    
    # Print row and col
    if (row and col and TTT [row-1][col-1] is None):
        global XO
        
        # Draw the X or O on screen
        drawXO(row, col)
        check_win()

reset_game() Function

The function restarts the game and also
resets all the variables to the beginning of the game.

def reset_game():
    global TTT, winner, XO, draw

    time.sleep(3)
    XO = 'x'
    draw = False
    game_opening()
    winner = None
    TTT = [[None] * 3, [None] * 3, [None] * 3]

game_opening()

5. The last part: Loop the game infinitely

  • To start the game, invoke game_opening() function.

  • Then, run an infinite loop and continuously check for any event made by the user.

    • If the user presses mouse button, the MOUSEBUTTONDOWN event will be captured and then trigger the userClick() function.
    • If the user wins or the game draws, reset the game by invoking reset_game() function.
  • In each iteration the display is updated, having set the frames per second to 30.

while(True):
    for event in pg.event.get():
        if event.type == QUIT:
            pg.quit()
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:

            # the user clicked; place an X or O
            userClick()
            
            if (winner or draw):
                reset_game()

    pg.display.update()
    CLOCK.tick(fps)

🥳🥳 The game is complete and ready to play.

The expected output on running the code. 👇

image.png

image.png

As promised here are the image files necessary for successful running of the game. 👇👇

o.png

x.png

opening.png



Inspiration and Image files from Tech Vidvan

See you in my next update! Cheers ✌️




Tic Tac Toe Game in Python | Ecency