Typing Game with Python and Turtle (Source Code Included)

Develop a typing game to improve keyboard skill as demonstrated in the following YouTube video.

Typing Game with Python and Turtle
Typing Game with Python and Turtle

At any moment ten random letters fall from the top of screen. When you hit a correct letter from keyboard, that letter disappears and is replaced by a new random letter dropping from the top. Also, your score will increase by 1. When you hit an incorrect letter, your score will decrease by 1.

Make these letters fall at random speeds and also let the speed increase gradually as time progresses. The game will end when a letter falls to the bottom of the screen.

You will need to use Turtle’s ontimer() and onkey() events to implement this project.

Source Code:

import turtle
import random

screen = turtle.Screen()
screen.setup(1000,1000)
screen.title('Typing Game - PythonTurtle.Academy')
screen.bgcolor('blue')
screen.tracer(0,0)
turtle.hideturtle()
turtle.up()
turtle.color('red')
score_turtle = turtle.Turtle()
score_turtle.color('red')
score_turtle.up()
score_turtle.hideturtle()
turtle.goto(350,400)
turtle.write('Score: ', align='center', font=('Courier',25,'normal'))

min_speed = 5
max_speed = 30
letters = []
speeds = []
pos = []
lts = []
n = 10
game_over = False
score = 0

def increase_difficulty():
    global min_speed, max_speed
    min_speed += 1
    max_speed += 1
    screen.ontimer(increase_difficulty,5000)

def draw_game_over():
    turtle.goto(0,0)
    turtle.color('red')
    turtle.write('GAME OVER', align='center', font=('Courier',50,'normal'))
    turtle.goto(0,-150)
    turtle.color('orange')
    turtle.write('Your Score is {}'.format(score), align='center', font=('Courier',40,'normal'))
    screen.update()

def draw_score():
    score_turtle.clear()
    score_turtle.goto(420,400)
    score_turtle.write('{}'.format(score),align='center',font=('Courier',25,'normal'))
    screen.update()
    
def draw_letters():
    global game_over
    for i in range(len(letters)):
        lts[i].clear()
        lts[i].goto(pos[i])
        lts[i].write(letters[i],align='center',font=('courier',20,'normal'))
        pos[i][1] -= speeds[i]
        if pos[i][1]<-500:
            game_over = True
            draw_game_over()
            return
    screen.update()
    screen.ontimer(draw_letters,50)

def f(c): # handle keyboard press
    global score
    if c in letters:
        score += 1
        k = letters.index(c)
        while True:
            l = chr(ord('a')+random.randrange(26))
            if l not in letters:
                letters[k] = l
                break            
        pos[k] = [random.randint(-450,450),500]        
        speeds[k] = random.randint(min_speed,max_speed)
    else: score -= 1
    draw_score()
        
for _ in range(n):
    lts.append(turtle.Turtle())
    while True:
        l = chr(ord('a')+random.randrange(26))
        if l not in letters:
            letters.append(l)
            break
    speeds.append(random.randint(min_speed,max_speed))
    pos.append([random.randint(-450,450),500])
    
for i in range(n):
    lts[i].speed(0)
    lts[i].hideturtle()
    lts[i].up()
    lts[i].color('yellow')
    
draw_letters()
increase_difficulty()

screen.onkey(lambda: f('a'), 'a')
screen.onkey(lambda: f('b'), 'b')
screen.onkey(lambda: f('c'), 'c')
screen.onkey(lambda: f('d'), 'd')
screen.onkey(lambda: f('e'), 'e')
screen.onkey(lambda: f('f'), 'f')
screen.onkey(lambda: f('g'), 'g')
screen.onkey(lambda: f('h'), 'h')
screen.onkey(lambda: f('i'), 'i')
screen.onkey(lambda: f('j'), 'j')
screen.onkey(lambda: f('k'), 'k')
screen.onkey(lambda: f('l'), 'l')
screen.onkey(lambda: f('m'), 'm')
screen.onkey(lambda: f('n'), 'n')
screen.onkey(lambda: f('o'), 'o')
screen.onkey(lambda: f('p'), 'p')
screen.onkey(lambda: f('q'), 'q')
screen.onkey(lambda: f('r'), 'r')
screen.onkey(lambda: f('s'), 's')
screen.onkey(lambda: f('t'), 't')
screen.onkey(lambda: f('u'), 'u')
screen.onkey(lambda: f('v'), 'v')
screen.onkey(lambda: f('w'), 'w')
screen.onkey(lambda: f('x'), 'x')
screen.onkey(lambda: f('y'), 'y')
screen.onkey(lambda: f('z'), 'z')

screen.listen()
screen.mainloop()

Continuous Clock with Python Turtle (Source Code)

In a previous project you animated a clock. Improve the clock by making all hands move continuously.

Source Code:

import turtle
import datetime
import math

screen = turtle.Screen()
screen.title('Continuous Clock - PythonTurtle.Academy')
screen.bgcolor('sky blue')
screen.setup(1000,1000)
screen.setworldcoordinates(-1000,-1000,1000,1000)
screen.tracer(0,0)


class clock:
    def __init__(self,hour,minute,second):
        self.hour, self.minute, self.second = hour, minute, second
        self.microsecond = 0
        self.face = turtle.Turtle()
        self.hand = turtle.Turtle()
        self.face.hideturtle()
        self.hand.hideturtle()

    def draw(self):
        self.draw_face()
        self.draw_hand()
        
    def draw_face(self):
        self.face.clear()
        self.face.up()
        self.face.goto(0,-700)
        self.face.pensize(4)
        self.face.down()
        self.face.fillcolor('white')
        self.face.begin_fill()
        self.face.circle(700,steps=100)
        self.face.end_fill()
        self.face.up()
        self.face.goto(0,0)
        self.face.dot(10)
        self.face.pensize(2)
        for angle in range(0,360,6):
            self.face.up()
            self.face.goto(0,0)
            self.face.seth(90-angle)
            self.face.fd(620)
            self.face.down()
            self.face.fd(30)
            
        self.face.pensize(3)
        for angle in range(0,360,30):
            self.face.up()
            self.face.goto(0,0)
            self.face.seth(90-angle)
            self.face.fd(600)
            self.face.down()
            self.face.fd(50)
            
        self.face.pensize(4)
        for angle in range(0,360,90):
            self.face.up()
            self.face.goto(0,0)
            self.face.seth(90-angle)
            self.face.fd(580)
            self.face.down()
            self.face.fd(70)
        
    def draw_hand(self):    
        self.hand.clear()       
        self.hand.up()
        self.hand.goto(0,0)
        self.hand.seth(90-math.floor(((self.hour%12)*60*60*1000000+self.minute*60*1000000+self.second*1000000+self.microsecond)/3600000000*30))
        self.hand.down()
        self.hand.color('black')
        self.hand.pensize(6)
        self.hand.fd(300)

        self.hand.up()
        self.hand.goto(0,0)
        self.hand.seth(90-math.floor((self.minute*60*1000000+self.second*1000000+self.microsecond)/60000000*6))
        self.hand.down()
        self.hand.color('black')
        self.hand.pensize(4)
        self.hand.fd(400)

        self.hand.up()
        self.hand.color('red')
        self.hand.goto(0,0)
        self.hand.dot(5)
        self.hand.seth(90-(self.second*1000000+self.microsecond)/1000000*6)
        self.hand.down()
        self.hand.pensize(2)
        self.hand.fd(570)

def animate():
    global c
    d = datetime.datetime.now()
    c.hour, c.minute, c.second, c.microsecond = d.hour, d.minute, d.second, d.microsecond
    c.draw_hand()
    screen.update()
    screen.ontimer(animate,100)
    
d = datetime.datetime.now()
c = clock(d.hour,d.minute,d.second)
c.draw_face()
screen.update()
animate()

Clock with Python Turtle (Source Code)

Define a ‘clock’ class with Python and use the datetime library to draw an animated clock shown.

Source Code:

import turtle
import datetime
screen = turtle.Screen()
screen.title('Clock - PythonTurtle.Academy')
screen.setup(1000,1000)
screen.setworldcoordinates(-1000,-1000,1000,1000)
screen.tracer(0,0)
screen.bgcolor('sky blue')

class clock:
    def __init__(self,hour,minute,second):
        self.hour, self.minute, self.second = hour, minute, second
        self.face = turtle.Turtle()
        self.hand = turtle.Turtle()
        self.face.hideturtle()
        self.hand.hideturtle()

    def draw(self):
        self.draw_face()
        self.draw_hand()
        
    def draw_face(self):
        self.face.clear()
        self.face.up()
        self.face.goto(0,-700)
        self.face.pensize(5)
        self.face.down()
        self.face.fillcolor('white')
        self.face.begin_fill()
        self.face.circle(700)
        self.face.end_fill()
        self.face.up()
        self.face.goto(0,0)
        self.face.dot(10)
        self.face.pensize(2)
        for angle in range(0,360,6):
            self.face.up()
            self.face.goto(0,0)
            self.face.seth(90-angle)
            self.face.fd(620)
            self.face.down()
            self.face.fd(30)
        self.face.pensize(4)
        for angle in range(0,360,30):
            self.face.up()
            self.face.goto(0,0)
            self.face.seth(90-angle)
            self.face.fd(600)
            self.face.down()
            self.face.fd(50)
        
    def draw_hand(self):    
        self.hand.clear()       
        self.hand.up()
        self.hand.goto(0,0)
        self.hand.seth(90-self.hour%12*360//12)
        self.hand.down()
        self.hand.color('black')
        self.hand.pensize(6)
        self.hand.fd(300)

        self.hand.up()
        self.hand.goto(0,0)
        self.hand.seth(90-self.minute*6)
        self.hand.down()
        self.hand.color('black')
        self.hand.pensize(4)
        self.hand.fd(400)

        self.hand.up()
        self.hand.color('red')
        self.hand.goto(0,0)
        self.hand.dot(5)
        self.hand.seth(90-self.second*6)
        self.hand.down()
        self.hand.pensize(2)
        self.hand.fd(600)

def animate():
    global c
    d = datetime.datetime.now()
    c.hour, c.minute, c.second = d.hour, d.minute, d.second
    c.draw_hand()
    screen.update()
    screen.ontimer(animate,1000)
    
d = datetime.datetime.now()
c = clock(d.hour,d.minute,d.second)
c.draw_face()
screen.update()
animate()

Animation of Sierpinski Triangle Tree with Turtle (Source Code)

Animate the transition from Sierpinski Triangle tree to Fractal tree as shown. This project is related to Sierpinski Triangle and Fractal Tree.

Source Code:

import turtle
turtle.title('Sierpinski Tree Animation - PythonTurtle.Academy')
turtle.setworldcoordinates(-2000,-2000,2000,2000)
screen = turtle.Screen()
screen.tracer(0,0)
turtle.speed(0)
turtle.hideturtle()

def sierpinski_tree(x,y,length,tilt,angle,n):
    if n==0: return
    turtle.up()
    turtle.goto(x,y)
    turtle.seth(tilt)
    turtle.down()
    turtle.fd(length)
    sierpinski_tree(turtle.xcor(),turtle.ycor(),length/2,turtle.heading(),angle,n-1)
    
    turtle.up()
    turtle.goto(x,y)
    turtle.seth(tilt+angle)
    turtle.down()
    turtle.fd(length)
    sierpinski_tree(turtle.xcor(),turtle.ycor(),length/2,turtle.heading(),angle,n-1)

    turtle.up()
    turtle.goto(x,y)
    turtle.seth(tilt-angle)
    turtle.down()
    turtle.fd(length)
    sierpinski_tree(turtle.xcor(),turtle.ycor(),length/2,turtle.heading(),angle,n-1)

def animate():
    global angle
    turtle.clear()
    sierpinski_tree(0,-250,1000,90,angle,7)
    screen.update()
    angle = 120 if angle <= 20 else angle-2
    screen.ontimer(animate,50)

angle = 120
animate()
screen.mainloop()

AI Tic-Tac-Toe with Minimax Tree (Source Code Included)

Use minimax tree search algorithm with alpha-beta pruning to write AI Tic-Tac-Toe player. You may also want to add randomness to your AI player so that it won’t play the same move every time. Here is more detail information on minimax tree and alpha-beta pruning. Your program should play against a human player. Therefore, you need to use onclick() function to handle mouse click events.

Tic-Tac-Toe with Minimax Tree

Source Code:

import turtle
import copy
import random

screen = turtle.Screen()
screen.setup(800,800)
screen.title("Tic Tac Toe - PythonTurtle.Academy")
screen.setworldcoordinates(-5,-5,5,5)
screen.bgcolor('light gray')
screen.tracer(0,0)
turtle.hideturtle()

def draw_board():
    turtle.pencolor('green')
    turtle.pensize(10)
    turtle.up()
    turtle.goto(-3,-1)
    turtle.seth(0)
    turtle.down()
    turtle.fd(6)
    turtle.up()
    turtle.goto(-3,1)
    turtle.seth(0)
    turtle.down()
    turtle.fd(6)
    turtle.up()
    turtle.goto(-1,-3)
    turtle.seth(90)
    turtle.down()
    turtle.fd(6)
    turtle.up()
    turtle.goto(1,-3)
    turtle.seth(90)
    turtle.down()
    turtle.fd(6)

def draw_circle(x,y):
    turtle.up()
    turtle.goto(x,y-0.75)
    turtle.seth(0)
    turtle.color('red')
    turtle.down()
    turtle.circle(0.75, steps=100)

def draw_x(x,y):
    turtle.color('blue')
    turtle.up()
    turtle.goto(x-0.75,y-0.75)
    turtle.down()
    turtle.goto(x+0.75,y+0.75)
    turtle.up()
    turtle.goto(x-0.75,y+0.75)
    turtle.down()
    turtle.goto(x+0.75,y-0.75)
    
def draw_piece(i,j,p):
    if p==0: return
    x,y = 2*(j-1), -2*(i-1)
    if p==1:
        draw_x(x,y)
    else:
        draw_circle(x,y)
    
def draw(b):
    draw_board()
    for i in range(3):
        for j in range(3):
            draw_piece(i,j,b[i][j])
    screen.update()

# return 1 if player 1 wins, 2 if player 2 wins, 3 if tie, 0 if game is not over
def gameover(b):
    if b[0][0]>0 and b[0][0] == b[0][1] and b[0][1] == b[0][2]: return b[0][0]
    if b[1][0]>0 and b[1][0] == b[1][1] and b[1][1] == b[1][2]: return b[1][0]
    if b[2][0]>0 and b[2][0] == b[2][1] and b[2][1] == b[2][2]: return b[2][0]
    if b[0][0]>0 and b[0][0] == b[1][0] and b[1][0] == b[2][0]: return b[0][0]
    if b[0][1]>0 and b[0][1] == b[1][1] and b[1][1] == b[2][1]: return b[0][1]
    if b[0][2]>0 and b[0][2] == b[1][2] and b[1][2] == b[2][2]: return b[0][2]
    if b[0][0]>0 and b[0][0] == b[1][1] and b[1][1] == b[2][2]: return b[0][0]
    if b[2][0]>0 and b[2][0] == b[1][1] and b[1][1] == b[0][2]: return b[2][0]
    p = 0
    for i in range(3):
        for j in range(3):
            p += (1 if b[i][j] > 0 else 0)
    if p==9: return 3
    else: return 0
    
def play(x,y):
    global turn
    if turn=='x': return
    
    i = 3-int(y+5)//2
    j = int(x+5)//2 - 1
    if i>2 or j>2 or i<0 or j<0 or b[i][j]!=0: return
    if turn == 'x': b[i][j], turn = 1, 'o'
    else: b[i][j], turn = 2, 'x'
    draw(b)
    r = gameover(b)
    if r==1:
        screen.textinput("Game over!","X won!")
    elif r==2:
        screen.textinput("Game over!","O won!")
    elif r==3:
        screen.textinput("Game over!", "Tie!")
    if r>0: turtle.bye()
    _,move = max_node(b,-2,2)
    b[move[0]][move[1]] = 1
    draw(b)
    r = gameover(b)
    if r==1:
        screen.textinput("Game over!","X won!")
    elif r==2:
        screen.textinput("Game over!","O won!")
    elif r==3:
        screen.textinput("Game over!", "Tie!")
    if r>0: turtle.bye()
    turn = 'o'
    
b = [ [ 0,0,0 ], [ 0,0,0 ], [ 0,0,0 ] ]    
draw(b)
turn = 'x'
screen.onclick(play)
#turtle.mainloop()

def max_node(b,alpha,beta):
    r = gameover(b)
    if r==1: return 1,None
    elif r==2: return -1,None
    elif r==3: return 0,None

    score = -2
    # find all possible next moves
    pm = list()
    for i in range(3):
        for j in range(3):
            if b[i][j] == 0: pm.append((i,j))
    random.shuffle(pm)
    for (i,j) in pm:
        if b[i][j] == 0:
            nb = copy.deepcopy(b)
            nb[i][j] = 1
            cs,_ = min_node(nb,alpha,beta)
            if score<cs:
                score=cs
                move = (i,j)
            alpha = max(alpha,cs)
            if alpha>=beta: return score,move
    return score,move

def min_node(b,alpha,beta):
    r = gameover(b)
    if r==1: return 1,None
    elif r==2: return -1,None
    elif r==3: return 0,None

    score = 2
    # find all possible next moves
    pm = list()
    random.shuffle(pm)
    for i in range(3):
        for j in range(3):
            if b[i][j] == 0: pm.append((i,j))
    for (i,j) in pm:
        if b[i][j] == 0:
            nb = copy.deepcopy(b)
            nb[i][j] = 2
            cs,_ = max_node(nb,alpha,beta)
            if score>cs:
                score=cs
                move = (i,j)
            beta = min(beta,cs)
            if alpha>=beta: return score,move
    return score,move

_,move = max_node(b,-2,2)
b[move[0]][move[1]] = 1
draw(b)
turn = 1
screen.mainloop()    

Related Projects:

Connect 4 with Python Turtle (Source Code Included)

Write a connect 4 program with Python and Turtle graphics. Your game should be able to let two human players play against each other and declare winner or tie when the game ends. You need to use onclick() event to handle the mouse click.

Connect 4 with Python Turtle

Source Code:

import turtle
import time

screen = turtle.Screen()
screen.setup(800,800)
screen.setworldcoordinates(-500,-500,500,500)
screen.title("Connect 4 - PythonTurtle.Academy")
turtle.speed(0)
turtle.hideturtle()
screen.tracer(0,0)
score = turtle.Turtle()
score.up()
score.hideturtle()

ROWS = 6
COLS = 7
STARTX = -450
STARTY = -450*ROWS/COLS
WIDTH = -2*STARTX
HEIGHT = -2*STARTY

def draw_rectangle(x,y,w,h,color):
    turtle.up()
    turtle.goto(x,y)
    turtle.seth(0)
    turtle.down()
    turtle.fillcolor(color)
    turtle.begin_fill()
    turtle.fd(w)
    turtle.left(90)
    turtle.fd(h)
    turtle.left(90)
    turtle.fd(w)
    turtle.left(90)
    turtle.fd(h)
    turtle.left(90)
    turtle.end_fill()

def draw_circle(x,y,r,color):
    turtle.up()
    turtle.goto(x,y-r)
    turtle.seth(0)
    turtle.down()
    turtle.fillcolor(color)
    turtle.begin_fill()
    turtle.circle(r,360,150)
    turtle.end_fill()

def draw_board():
    draw_rectangle(STARTX,STARTY,WIDTH,HEIGHT,'light blue')

def draw_pieces():
    global board
    row_gap = HEIGHT/ROWS
    col_gap = WIDTH/COLS
    Y = STARTY + row_gap / 2;
    for i in range(ROWS):
        X = STARTX + col_gap/2
        for j in range(COLS):
            if board[i][j] == 0:
                draw_circle(X,Y,row_gap/3,'white')
            elif board[i][j] == 1:
                draw_circle(X,Y,row_gap/3,'black')
            else:
                draw_circle(X,Y,row_gap/3,'red')
            X += col_gap
        Y += row_gap

def draw():
    draw_board()
    draw_pieces()
    screen.update()
    
def game_over_lastmove(bb,turn,r,c):
    # check horizontals
    cnt = 1
    i = c+1
    while i<COLS and bb[r][i]==turn: cnt, i = cnt+1, i+1
    i = c-1
    while i>=0 and bb[r][i]==turn: cnt, i = cnt+1, i-1
    if cnt>=4: return turn
    
    # check vertical
    if r>=3 and bb[r-1][c]==turn and bb[r-2][c]==turn and bb[r-3][c]==turn: return turn

    # check diag 2
    cnt = 1
    i = 1
    while r+i<ROWS and c+i<COLS and bb[r+i][c+i]==turn: cnt, i = cnt+1, i+1
    i = -1
    while r+i>=0 and c+i>=0 and bb[r+i][c+i]==turn: cnt, i = cnt+1, i-1
    if cnt>=4: return turn

    # check diag 1
    cnt = 1
    i = 1
    while r+i<ROWS and c-i>=0 and bb[r+i][c-i]==turn: cnt, i = cnt+1, i+1
    i = -1
    while r+i>=0 and c-i<COLS and bb[r+i][c-i]==turn: cnt, i = cnt+1, i-1
    if cnt>=4: return turn
    
    for i in range(COLS):
        if bb[ROWS-1][i] == 0:
            return -2
    return 0

# place piece in col for turn
def place_piece(bb,turn,col):
    for i in range(ROWS):
        if bb[i][col] == 0:
            bb[i][col] = turn
            return i

def init_board():
    global board
    for i in range(ROWS):
        row = []
        for j in range(COLS):
            row.append(0)
        board.append(row)
    
def place_piece_and_draw(bb,turn,col):
    row = place_piece(bb,turn,col)
    row_gap = HEIGHT/ROWS
    col_gap = WIDTH/COLS
    Y = STARTY + row_gap*row + row_gap / 2;
    X = STARTX + col_gap*col + col_gap/2
    i = row
    j = col
    if board[i][j] == 0:
        draw_circle(X,Y,row_gap/3,'white')
    elif board[i][j] == 1:
        for k in range(5):
            draw_circle(X,Y,row_gap/3,'white')
            screen.update()
            time.sleep(0.05)
            draw_circle(X,Y,row_gap/3,'black')
            screen.update()
            time.sleep(0.05)
    else:
        for k in range(5):
            draw_circle(X,Y,row_gap/3,'white')
            screen.update()
            time.sleep(0.05)
            draw_circle(X,Y,row_gap/3,'red')
            screen.update()
            time.sleep(0.05)
    return row

def play(x,y):
    global turn,working
    if working: return
    working = True
    cols = [ 900/7*i-450+900/14 for i in range(7) ]
    for i in range(len(cols)):
        if abs(x-cols[i]) < 900/14*2/3 and board[ROWS-1][i]==0:
            rn = place_piece_and_draw(board,turn,i)
            r = game_over_lastmove(board,turn,rn,i)
            if r==0:
                screen.textinput('Game over','tie')
            elif r==1:
                screen.textinput('Game over','player 1 won')
            elif r==-1:
                screen.textinput('Game over','player 2 won')
            if r!=-2: screen.bye()
            turn = -turn
    working = False

board = []
init_board()
draw_board()
draw_pieces()
turn=1
working=False
screen.onclick(play)
screen.mainloop()

Game of SIM with Python Turtle (Source Code Included)

Game of SIM was invented in 1969 by Gustavus Simmons. In this two player (red and blue) game, each player takes turn to connect two vertices of a hexagon with the player’s color (either red or blue). The first player who draws all three sides of the triangle with the player’s color loses the game. There is always a winner for this game.

Write a Game of SIM with Python and Turtle graphics. Your game should be able to declare the winner when the game ends. You will need to use onclick() even of Turtle graphics.

Game of SIM with Python Turtle

Source Code:

import turtle
import math

screen = turtle.Screen()
screen.setup(800,800)
screen.title("Game of SIM - PythonTurtle.Academy")
screen.setworldcoordinates(-1.5,-1.5,1.5,1.5)
screen.tracer(0,0)
turtle.hideturtle()

def draw_dot(x,y,color):
    turtle.up()
    turtle.goto(x,y)
    turtle.color(color)
    turtle.dot(15)

def gen_dots():
    r = []
    for angle in range(0,360,60):
        r.append((math.cos(math.radians(angle)),math.sin(math.radians(angle))))
    return r

def draw_line(p1,p2,color):
    turtle.up()
    turtle.pensize(3)
    turtle.goto(p1)
    turtle.down()
    turtle.color(color)
    turtle.goto(p2)
    
def draw_board():
    global selection
    
    for i in range(len(dots)):
        if i in selection: draw_dot(dots[i][0],dots[i][1],turn)
        else: draw_dot(dots[i][0],dots[i][1],'dark gray')
        
def draw():
    draw_board()
    for i in range(len(red)):
        draw_line((math.cos(math.radians(red[i][0]*60)),math.sin(math.radians(red[i][0]*60))),\
                  (math.cos(math.radians(red[i][1]*60)),math.sin(math.radians(red[i][1]*60))),\
                  'red')
    for i in range(len(blue)):
         draw_line((math.cos(math.radians(blue[i][0]*60)),math.sin(math.radians(blue[i][0]*60))),\
                  (math.cos(math.radians(blue[i][1]*60)),math.sin(math.radians(blue[i][1]*60))),\
                  'blue')      
    screen.update()

def play(x,y):
    global selection,turn,red,blue
    
    for i in range(len(dots)):
        dist = (dots[i][0]-x)**2 + (dots[i][1]-y)**2
        if dist<0.001:
            if i in selection: selection.remove(i)
            else: selection.append(i)
            break
    if len(selection)==2:
        selection=(min(selection),max(selection))
        if selection not in red and selection not in blue:
            if turn=='red':
                red.append(selection)
            else:
                blue.append(selection)
            turn = 'red' if turn=='blue' else 'blue'
        selection = []
    draw()
    r = gameover(red,blue)
    if r!=0:
        screen.textinput('game over',r+' won!')
        turtle.bye()

def gameover(r,b):
    if len(r)<3: return 0
    r.sort()
    for i in range(len(r)-2):
        for j in range(i+1,len(r)-1):
            for k in range(j+1,len(r)):
                if r[i][0]==r[j][0] and r[i][1]==r[k][0] and r[j][1]==r[k][1]: return 'blue'
    if len(b)<3: return 0
    b.sort()
    for i in range(len(b)-2):
        for j in range(i+1,len(b)-1):
            for k in range(j+1,len(b)):
                if b[i][0]==b[j][0] and b[i][1]==b[k][0] and b[j][1]==b[k][1]: return 'red'
    return 0

selection = []
turn = 'red'
dots = gen_dots()
red = [ ]
blue = [ ]
draw()
screen.onclick(play)
turtle.mainloop()

Tic Tac Toe (Source Code Included)

Design a two player tic-tac-toe game with Python Turtle. You will need to use onclick() event to let two human players play against each other.

Tic-Tac-Toe of Python Turtle

Source Code:

import turtle

screen = turtle.Screen()
screen.setup(800,800)
screen.title("Tic Tac Toe - PythonTurtle.Academy")
screen.setworldcoordinates(-5,-5,5,5)
screen.bgcolor('light gray')
screen.tracer(0,0)
turtle.hideturtle()

def draw_board():
    turtle.pencolor('green')
    turtle.pensize(10)
    turtle.up()
    turtle.goto(-3,-1)
    turtle.seth(0)
    turtle.down()
    turtle.fd(6)
    turtle.up()
    turtle.goto(-3,1)
    turtle.seth(0)
    turtle.down()
    turtle.fd(6)
    turtle.up()
    turtle.goto(-1,-3)
    turtle.seth(90)
    turtle.down()
    turtle.fd(6)
    turtle.up()
    turtle.goto(1,-3)
    turtle.seth(90)
    turtle.down()
    turtle.fd(6)

def draw_circle(x,y):
    turtle.up()
    turtle.goto(x,y-0.75)
    turtle.seth(0)
    turtle.color('red')
    turtle.down()
    turtle.circle(0.75, steps=100)

def draw_x(x,y):
    turtle.color('blue')
    turtle.up()
    turtle.goto(x-0.75,y-0.75)
    turtle.down()
    turtle.goto(x+0.75,y+0.75)
    turtle.up()
    turtle.goto(x-0.75,y+0.75)
    turtle.down()
    turtle.goto(x+0.75,y-0.75)
    
def draw_piece(i,j,p):
    if p==0: return
    x,y = 2*(j-1), -2*(i-1)
    if p==1:
        draw_x(x,y)
    else:
        draw_circle(x,y)
    
def draw(b):
    draw_board()
    for i in range(3):
        for j in range(3):
            draw_piece(i,j,b[i][j])
    screen.update()

# return 1 if player 1 wins, 2 if player 2 wins, 3 if tie, 0 if game is not over
def gameover(b):
    if b[0][0]>0 and b[0][0] == b[0][1] and b[0][1] == b[0][2]: return b[0][0]
    if b[1][0]>0 and b[1][0] == b[1][1] and b[1][1] == b[1][2]: return b[1][0]
    if b[2][0]>0 and b[2][0] == b[2][1] and b[2][1] == b[2][2]: return b[2][0]
    if b[0][0]>0 and b[0][0] == b[1][0] and b[1][0] == b[2][0]: return b[0][0]
    if b[0][1]>0 and b[0][1] == b[1][1] and b[1][1] == b[2][1]: return b[0][1]
    if b[0][2]>0 and b[0][2] == b[1][2] and b[1][2] == b[2][2]: return b[0][2]
    if b[0][0]>0 and b[0][0] == b[1][1] and b[1][1] == b[2][2]: return b[0][0]
    if b[2][0]>0 and b[2][0] == b[1][1] and b[1][1] == b[0][2]: return b[2][0]
    p = 0
    for i in range(3):
        for j in range(3):
            p += (1 if b[i][j] > 0 else 0)
    if p==9: return 3
    else: return 0
    
def play(x,y):
    global turn
    i = 3-int(y+5)//2
    j = int(x+5)//2 - 1
    if i>2 or j>2 or i<0 or j<0 or b[i][j]!=0: return
    if turn == 'x': b[i][j], turn = 1, 'o'
    else: b[i][j], turn = 2, 'x'
    draw(b)
    r = gameover(b)
    if r==1:
        screen.textinput("Game over!","X won!")
    elif r==2:
        screen.textinput("Game over!","O won!")
    elif r==3:
        screen.textinput("Game over!", "Tie!")
    
b = [ [ 0,0,0 ], [ 0,0,0 ], [ 0,0,0 ] ]    
draw(b)
turn = 'x'
screen.onclick(play)
turtle.mainloop()