Best Python Projects for Kids in 2021: Tic Tac Toe with Python

Use the turtle libraries to code a basic tic-tac-toe game! This uses functions and variables to create the game which makes for good practice.

Table of Content


General Project Information:

Experience needed in python: Beginner-Intermediate

Challenge level: Intermediate - Hard

Core Concepts: Functions, Coordinates On A 2D Plane, 2D Arrays

Prerequisites: Variables, Loops, Basic Turtle Concepts, Conditional Statements

Using these concepts you will learn how to turn a simple everyday game into a video game!


Project Demo:



Features To consider:

  1. Creating a grid
  2. Drawing the x’s and o’s
  3. Keeping track of turns
  4. Checking if a player has won
  5. Checking where the player clicked on the screen
  6. Resetting the game if its a tie

Steps:

Step 1 Drawing The Board:

First we have to draw the grid. You have to write a function to draw the grid, You can use the turtle goto function to do this, one line will look something like this.

up()
goto(x1, y1)
down()
goto(x2, y2)

We want to make the grid 400x400 in size. 

You can then call the function right after the function.

Hint: The first like looks like this

up()
goto(-67, 200)
down()
goto(-67, -200)

Solution:

def grid():
 up()
 goto(-67, 200)
 down()
 goto(-67, -200)

 up()
 goto(67, 200)
 down()
 goto(67, -200)

 up()
 goto(-200, -67)
 down()
 goto(200, -67)

 up()
 goto(-200, 67)
 down()
 goto(200, 67)

Step 2 Drawing The X:

Next we need to make a function to draw an x, the function will have two arguments, x and y. You can also use the goto function to draw this. The x and y will refer to the bottom left corner of the square you are drawing in.

Hint 1: One square is 133x133.

Hint 2: You will need to put x + 133 and y + 133 in your code somewhere.

Solution:

def drawx(x, y):
 up()
 goto(x, y)
 down()
 goto(x + 133, y + 133)

 up()
 goto(x, y + 133)
 down()
 goto(x + 133, y)
 up()

Step 3: Drawing The O:

We now can move on to drawing the o. This function will also have two arguments, x and y. These will aso point to the bottom left corner.

Hint 1: Turtle has a circle function.

Hint 2: You will need x + 67 and y + 5 in your code.

Solution:

def drawo(x, y):
 up()
 goto(x + 67, y + 5)
 down()
 circle(62)

Step 4: Tracking Player Turns:

Now that we have all of the code to draw on the screen we have to make it useful, so lets add a way to keep track of whose turn it is. We can create a Boolean Dictionary to keep track of what players turn it is because there are only two players.

state = {'player': False}
players = [drawx, drawo]


This will create a state variable which is an “array” with an index called ‘player’ which is set to false, it will also create an array of functions called players. The two functions in it are the drawx() and drawo() functions. We will use these to pick what shape to draw then a player clicks the screen.

Player x = False/0

Player o = True/1

state = {'player': False} #false = x true = o
players = [drawx, drawo]

Step 5: Clicking A Square:

When a player clicks the screen we need to do a few things

  1. Figure out whose turn it is
  2. Find the bottom left corner of the square clicked
  3. Draw a x/o in that square
  4. Switch whose turn it is

First we need a new variable which will be the draw function needed.

Hint: Use players and the int value of state


Next we need a function to find the bottom left corner of the square, we will have the coordinate of the place clicked to find the square.

Hint 1: We can use this function to find the value for x or y

def floor(value):
    Return ((value) // 133) * 133 - 200


Hint 2: If you floor() both x and y you will get the bottom left corner

After that we need to draw an x or o in that square, you can use the variable you created earlier with the new x and y values you got.

Finally you can switch the player's turns, use your state variable to change the players turns.

Hint: You can set a bool to not itself.

def tap(x, y):
 x = floor(x)
 y = floor(y)
 draw = players[int(state['player'])]
 draw(x, y)
 state['player'] = not state['player']


Step 6: Looping The Code:

At the end of your code you can use the done() function to loop the code we have written.

done()


Step 7: Making A 2D Array To Store The Board:

 Next in order to judge who won the game we have to create a 2D array to store the value of each spot on the grid, each spot should be initialized to ‘-’.

board = [['-', '-', '-'], ['-', '-', '-'], ['-', '-', '-']]


Step 8: Adding X’s And O’s To The Array:

We now need to add each players moves to the array, in order to do that we must know all of the floored values for the x and y axis, the floored values look like this


Using this we can use if statements in the draw functions to add each move to the array.

Hint: Overwriting the x and y values with the correct index will help when adding to the array

Solution:

def drawx(x, y):
 line(x, y, x + 133, y + 133)
 line(x, y + 133, x + 133, y)

 if x == -200.0:
   x = 0
 elif x == -67.0:
   x = 1
 elif x == 66.0:
   x = 2

 if y == -200.0:
   y = 0
 elif y == -67.0:
   y = 1
 elif y == 66.0:
   y = 2

 board[x][y] = 'x'


Step 9: Making A Function To Check Who Won:

Using if statements inside of a for loop may help find every combination of lines of 3. You can also have one if statement for each combination, when you find a player that has 3 in a row then return the letter of the winner. This will be placed in the tap function near the end, it won't return anything if there is no winner.

Hint 1: You will need to compare 3 values against each other, also make sure they aren't blank spaces.

Hint 2: It may look something like this for a diagonal line

if board[0][0] == board[1][1] and board[1][1] == board[2][2] and board[2][2] != '-':

Solution:

def hasPlayerWon():
 for i in range(3):
   if board[i][0] == board[i][1] and board[i][1] == board[i][2] and board[i][2] != '-':
     clearscreen()
     return board[i][0]
   elif board[0][i] == board[1][i] and board[1][i] == board[2][i] and board[2][i] != '-':
     clearscreen()
     return board[0][i]
  
 if board[0][0] == board[1][1] and board[1][1] == board[2][2] and board[2][2] != '-':
   clearscreen()
   return board[0][0]
 elif board[2][0] == board[1][1] and board[1][1] == board[0][2] and board[0][2] != '-':
   clearscreen()
   return board[2][0]


Step 10: Drawing The Winners Letter:

Where you call the function you will need to check who won and then clear the board if there isn't a winner. Otherwise you should call your draw function in the middle of the screen.

Hint: Using an if statement to check if it returns an x or o then calling the respective draw function is a good idea. You can use clearscreen() to clear the previous drawings.

def tap(x, y):
 x = floor(x)
 y = floor(y)
 draw = players[int(state['player'])]
 draw(x, y)
 if hasPlayerWon() == 'x':
   drawx(-67, -67)
 elif hasPlayerWon() == 'o':
   drawo(-67, -67)
 state['player'] = not state['player']

Step 11: Restarting On A Tie:

Finally we can add the last function, a function that will check if the board is full of x’s and o’s, if it is it will clear the screen and redraw the grid, then it will also reset the board array. It will be called from inside the tap function right after you check if someone won.

Hint 1: You can use a for loop to check if each part of the board array has a ‘-’ if it does return.

Hint 2: You can use a double for loop to set each part of the board array to a ‘-’ if the board is full

Solution:

def CheckBoardFull():
 for i in range(3):
   if board[i][0] == '-' or board[i][1] == '-' or board[i][2] == '-':
     return
   elif board[0][i] == '-' or board[1][i] == '-' or board[2][i] == '-':
     return
 for i in range(3):
   for k in range(3):
     board[i][k] = '-'
 clear()
 grid()



Sign up and get a 60-minute free assessment class

Get Started