Tic Tac Toe Python Code with Graphics.py Module

Tic Tac Toe is a very common two player mind game. It is liked by people of all age groups. Its working is very simple. A play area of 3X3 boxes is defined. The player who first marks any row or column or diagonal of three boxes with his symbol(O or X) wins the game. It is not that difficult to code either. In this post we will share Tic Tac Toe Python Code with you and explain the logic of this code.

So, let’s begin by understanding how it is created.

Creating interface

The interface of Tic Tac Toe Python code is created by using the GraphWin, setBackground and Line methods available in graphics.py module.

Two vertical and two horizontal lines are drawn using Line object to create a # like surface.

Players can click in the boxes thus created and the position is recorded using getMouse method with GraphWin Object.

The top left and right bottom corners of all the nine boxes are stored in two arrays to define their boundaries

Tic Tac Toe Python Code- logic

When the player clicks in a box, these things happen

  • The point clicked in the window is recorded by using  getMouse method which returns a Point object. According to current player X or 0 is drawn at that position. The symbol is toggled to change to the turn of other player
  • This point is checked against the corner values of the boxes stored in two arrays arrf and arrt. According to the position of the box, its index(1-9) is appended to the array that stores the all the clicked boxes by current player. For two players two such arrays are maintained p1 and p2.
  • All possible winning combinations are generated using combinations and permutations methods of combinations and permutations modules.
  • The array that stores the clicked box indices by player is used to generate all the possible 3 digit combinations for that player.
  • Whenever a player has clicked more than 3 boxes it’s possible permutations are generated. All these are checked against all the possible winning combinations. If a combination generated for a player matches a winning combination, the winner is declared winner by drawing the Text object at the bottom of the game board.

Code

# A simple graphical Calculator Application in Python
from itertools import permutations
from itertools import combinations
from graphics import *

def getRes():
    #generate all the winning combinations and store in an array
    resArr=[]
    seq = permutations(['7','8','9'])
    for p in list(seq):
        tt=''.join(p)
        resArr.append(tt)
    seq = permutations(['6','5','4'])
    for p in list(seq):
        tt=''.join(p)
        resArr.append(tt)
    seq = permutations(['3','2','1'])
    for p in list(seq):
        tt=''.join(p)
        resArr.append(tt)
    seq = permutations(['1','4','7'])
    for p in list(seq):
        tt=''.join(p)
        resArr.append(tt)
    seq = permutations(['2','5','8'])
    for p in list(seq):
        tt=''.join(p)
        resArr.append(tt)
    seq = permutations(['3','6','9'])
    for p in list(seq):
        tt=''.join(p)
        resArr.append(tt)
    seq = permutations(['1','5','9'])
    for p in list(seq):
        tt=''.join(p)
        resArr.append(tt)
    seq = permutations(['3','5','7'])
    for p in list(seq):
        tt=''.join(p)
        resArr.append(tt)
    return resArr

def check(clkvals, rescombs):
    playArr=[]
    combi = permutations(clkvals, 3)
    #generate all the  combinations of boxes clicked by a player  
    for c in list(combi):
        tt=''.join(c)
        playArr.append(tt)
    #compare the player's combinations with all the winning combinations    
    for p in playArr:
        if(p in rescombs):
            #return true if a combination matches a winning combination
            return True
    

def main():
    #generate all the winning combinations and store in an array
    rescombs=getRes()
    # define window for the game board
    workArea = GraphWin('TicTacToe', 300, 350) # give title and dimensions
    workArea.setBackground('yellow')
    #horizontal lines
    ln=Line(Point(10,100),Point(280,100))
    ln.setWidth(3)
    ln.draw(workArea)
    ln=Line(Point(10,190),Point(280,190))
    ln.setWidth(3)
    ln.draw(workArea)
    #vertical lines
    ln=Line(Point(100,10),Point(100, 280))
    ln.setWidth(3)
    ln.draw(workArea)
    ln=Line(Point(190,10),Point(190,280))
    ln.setWidth(3)
    ln.draw(workArea)
    #variables
    arrf=[]
    arrt=[]
    cnt1=0
    cnt2=0
    x=10
    y=10
    i=0
    j=8
    p1=[' ']
    p2=[' ']
    pl="X"
    
    #loop to store boundaries
    while j>=0:
            arrf.append(Point(x,y))
            arrt.append(Point(x+90,y+90))
            x=x+90
            j=j-1
            i=i+1
            if (i==3):       
                x=10
                y=y+90
                i=0
    clk=True
    numv=""
    t1=Text(Point(1,1),p1)
    t2=Text(Point(1,1),p1)
    finres=False
    cnt=1
    inBox=False
    mid=Point(0,0)    

    #loop to check the range of coordinates where user clicked
    while cnt<=9:
        
        ch=workArea.getMouse()
        
        if (ch.x >arrf[0].x  and ch.x <arrt[0].x and ch.y >arrf[0].y  and ch.y<arrt[0].y):
            numv="9"
            mid=Point(arrf[0].x +45,arrf[0].y+45)
            inBox=True
        if (ch.x >arrf[1].x  and ch.x <arrt[1].x and ch.y >arrf[1].y  and ch.y<arrt[1].y):
            numv="8"
            mid=Point(arrf[1].x +45,arrf[1].y+45)
            inBox=True
        if (ch.x >arrf[2].x  and ch.x <arrt[2].x and ch.y >arrf[2].y  and ch.y<arrt[2].y):
            numv="7"
            mid=Point(arrf[2].x +45,arrf[2].y+45)
            inBox=True
        if (ch.x >arrf[3].x  and ch.x <arrt[3].x and ch.y >arrf[3].y  and ch.y<arrt[3].y):
            numv="6"
            mid=Point(arrf[3].x +45,arrf[3].y+45)
            inBox=True
        if (ch.x >arrf[4].x  and ch.x <arrt[4].x and ch.y >arrf[4].y  and ch.y<arrt[4].y):
            numv="5"
            mid=Point(arrf[4].x +45,arrf[4].y+45)
            inBox=True
        if (ch.x >arrf[5].x  and ch.x <arrt[5].x and ch.y >arrf[5].y  and ch.y<arrt[5].y):
            numv="4"
            mid=Point(arrf[5].x +45,arrf[5].y+45)
            inBox=True
        if (ch.x >arrf[6].x  and ch.x <arrt[6].x and ch.y >arrf[6].y  and ch.y<arrt[6].y):
            numv="3"
            mid=Point(arrf[6].x +45,arrf[6].y+45)
            inBox=True
        if (ch.x >arrf[7].x  and ch.x <arrt[7].x and ch.y >arrf[7].y  and ch.y<arrt[7].y):
            numv="2"
            mid=Point(arrf[7].x +45,arrf[7].y+45)
            inBox=True
        if (ch.x >arrf[8].x  and ch.x <arrt[8].x and ch.y >arrf[8].y  and ch.y<arrt[8].y):
            numv="1"
            mid=Point(arrf[8].x +45,arrf[8].y+45)
            inBox=True
        #put point
        if inBox:
            txt=Text(mid,pl)
            txt.setSize(36)
            txt.draw(workArea)
            inBox=False
            cnt=cnt+1
        #change symbol of the current player and check result
        if pl=="X":
            p1.append(numv)
            if len(p1)>=3:
                finres=check(p1,rescombs)
            if finres:
                t1=Text(Point(workArea.getWidth()/2,320),"Player "+pl+" wins")
                t1.setSize(20)
                t1.setTextColor("red")
                t1.draw(workArea)
                clk=False
                break
            pl="O"
        else:
            cnt2+=1
            p2.append(numv)
            if len(p2)>=3:
                finres=check(p2,rescombs)
            if finres:
                t1=Text(Point(workArea.getWidth()/2,320),"Player " +pl+ " wins")
                t1.setSize(20)
                t1.setTextColor("red")
                t1.draw(workArea)
                clk=False
                break
            pl="X"
       
   # If game is draw        
    if clk:
        t1=Text(Point(workArea.getWidth()/2,320),"Game Draw")
        t1.setSize(20)
        t1.setTextColor("red")
        t1.draw(workArea)
         

main()    

Display screens

2 Comments

  1. Filipe Ferreira dos Santos said:

    Thanks for sharing this funny code! XD

    I have some comments:

    1) The “X” and “O” symbols are not displayed in the middle of the squares;
    2) Is it easy to make the main game box with editable size by using the mouse, changing the size of the lines and other symbols accordingly?
    3) If there is a draw, the code actually does not display it. It keeps running until either player “X” or “O” wins;

    Do these bugs are actually related to my Linux Ubuntu 18.04.2 LTS system?

    Thank you for your attention!

    June 2, 2020
    Reply
    • admin said:

      Hello Filipe.
      Thanks for bringing attention to the bugs and finding it funny. The code is now updated by removing bugs mentioned in points 1 and 3. They were there:(. Nothing related to your Linux Ubuntu 18.04.2 LTS system. We will try your suggestions mentioned in second point and revert back to you. Keep correcting us in future as well.

      June 3, 2020
      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *