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.
Tic-Tac-Toe | Python
Steps To Build a Python Tic Tac Toe Game
- Create the display window for the game.
- Draw the grid on the canvas where to play the Tic Tac Toe Game.
- Draw a status bar below the canvas to show which player's turn it is and who wins the game.
- Reset the game when a person wins or both players draw.
1. Initializing the Game Components
- Start by importing the
pygame
andtime
library.
import pygame as pg,sys
from pygame.locals import *
import time
- The
time
library provides us with thetime.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 functionblit()
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 colorTo 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 theuserClick()
function. - If the user wins or the game draws, reset the game by invoking
reset_game()
function.
- If the user presses mouse button, the
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. ๐
As promised here are the image files necessary for successful running of the game. ๐๐
Inspiration and Image files from Tech Vidvan
See you in my next update! Cheers โ๏ธ
Thanks for sharing this in the programming community. I havenโt used pygame much but may eventually get round to jumping back in!
It is pretty fun to play around with, you should definitely give it a try.
Looks Interesting, will try to implement the code myself. Good Job๐
Thank you. It is definitely worth trying!
I am sure it is, as soon as my heart wants some programming I am definitely going to build that.