Monday, January 18, 2021

Tic Tac Toe Cording in Python

#####################################################################################################


#     TIC TAC TOE THE GAME YOU LOVED


# ----------------------------------------------------------------------------------------------------


#     this is the game tic tac toe the game you were playing as children it is fully funcitonal


#   with the capability of AI you can draw with it and have fun enjoy!


#     P.S. this program required pygame along side with python 3 to work install pygame


#     to your python 3 (e.g. C:\>pip install pygame) to make it work.


# ----------------------------------------------------------------------------------------------------


#     Copyright (C) Prageeth Niranjan 2019


#     Version 1.0.0


# ----------------------------------------------------------------------------------------------------


# HOW TO RUN: copy the code in this page and paste it on a text editor and name the file as tic_tac_toe.py


# then use command prompt to run c:\<dir path>\>python tic_tac_toe.py


# <dir path> is the path to tic_tac_toe.py file


#####################################################################################################



import pygame, random, sys, os, math, random


from enum import Enum


# width and hight of the screen


WIDTH = 400


HEIGHT = 400


# the game array


tic_tac_toe = [0, 0, 0, 0, 0, 0, 0, 0, 0]


# shift of player and compuer X and O


x_shift = 40


# score assined to the board


game_score = 1


player_score = game_score


computer_score = -game_score


# disply text position


text_x = 50


text_y = int(HEIGHT / 2 - 10)


# define values for X and O


CHARACTOR_FOR_X = 'x'


CHARACTOR_FOR_O = 'o'


# difine the Player Charactors


_player = CHARACTOR_FOR_X


_computer = CHARACTOR_FOR_O


# player turn


turn = _player


# Collors to be used


BLACK = (0, 0, 0)


WHITE = (255, 255, 255)


RED = (255, 0, 0)


GREEN = (0, 255, 0)


BLUE = (0, 0, 255)


YELLOW = (255, 255, 0)


# Display Message Settings


DISPLAY_MESSAGE_HEIGHT = 150


DISPLAY_MESSAGE_ALPHA = 200


BACKGROUND_COLOR = BLACK  # this varialbe set's the background color


screen = ""


myFont = ""


m_display = ""


gameOver = False



#################################################################################


# init pygame


#################################################################################


# this function handle the initialization of pygame it setup the environment


# so the screen can be use to draw the game objects


#################################################################################



def init_pygame():  # this function initialize the pygame


    global screen, myFont, m_display



pygame.init()  # initilze pygame


pygame.display.set_caption('TIC TAC TOE'# set pygame caption


myFont = pygame.font.SysFont('monospace', 30)  # get the font 'monospace' with size 30


screen = pygame.display.set_mode((WIDTH, HEIGHT))  # set the display windows width and height


pygame.display.update()  # update the display window


m_display = pygame.Surface((WIDTH, DISPLAY_MESSAGE_HEIGHT))  # make the message background


m_display.set_alpha(DISPLAY_MESSAGE_ALPHA)  # make the message background transparent


m_display.fill(BLACK)  # fill message background with black



###################################################################################


# game screen


###################################################################################


# this function is used to draw the game screen of tic tac toe


###################################################################################



def game_screen(COLOR):  # this is a function to draw the grid line of the screen and the moves made


    global screen, tic_tac_toe


    pygame.draw.line(screen, COLOR, (int(WIDTH / 3), 0), (int(WIDTH / 3), HEIGHT), 2)


    pygame.draw.line(screen, COLOR, (int(2 * WIDTH / 3), 0), (int(2 * WIDTH / 3), HEIGHT), 2)


    pygame.draw.line(screen, COLOR, (0, int(HEIGHT / 3)), (WIDTH, int(HEIGHT / 3)), 2)


    pygame.draw.line(screen, COLOR, (0, int(2 * HEIGHT / 3)), (WIDTH, int(2 * HEIGHT / 3)), 2)


    for i in range(0, 9):  # draw the player posisions


        if tic_tac_toe[i] == player_score:

            draw_charactor(i, BLUE, _player)


    for i in range(0, 9):  # draw the computer posisions


        if tic_tac_toe[i] == computer_score:

            draw_charactor(i, BLUE, _computer)



##################################################################################


# find pos


##################################################################################


# This function is used to find the position of the tic tac toe list


# relation to position clicked


##################################################################################



def find_pos(pos):  # find the mouse position related to the grid


    # pos = pygame.mouse.get_pos()


    x = pos[0] // (WIDTH / 3)


    y = pos[1] // (HEIGHT / 3)


    return int(y * 3 + x)



##################################################################################


# drawX


##################################################################################


# draw the X symbol on the screen given the clicked position


##################################################################################



def drawX(pos, COLOR):  # draw the X in the grid


    global screen


    x = pos % 3


    y = pos // 3


    xi = math.ceil(x * WIDTH / 3)


    yi = math.ceil(y * HEIGHT / 3)


    pygame.draw.line(screen, COLOR, (int(xi + x_shift), int(yi + x_shift)),

                     (int(xi + WIDTH / 3 - x_shift), int(yi + HEIGHT / 3 - x_shift)), 10)


    pygame.draw.line(screen, COLOR, (int(xi + x_shift), int(yi + HEIGHT / 3 - x_shift)),

                     (int(xi + WIDTH / 3 - x_shift), int(yi + x_shift)), 10)



##################################################################################


# drawO


##################################################################################


# draw the O symbol on the screen given the clicked position


##################################################################################



def drawO(pos, COLOR):  # draw the O in the grid


    global screen


    x = pos % 3


    y = pos // 3


    xi = math.ceil(x * WIDTH / 3 + WIDTH / 6)


    yi = math.ceil(y * HEIGHT / 3 + HEIGHT / 6)


    pygame.draw.circle(screen, COLOR, (xi, yi), math.ceil(WIDTH / 6 - x_shift), 10)



####################################################################################


# draw character


####################################################################################


# draw X or O depending on the character given


####################################################################################



def draw_charactor(pos, COLOR, charactor):  # Draw the charactor Acording to symbol


    if charactor == CHARACTOR_FOR_X:


        drawX(pos, COLOR)


    elif charactor == CHARACTOR_FOR_O:


        drawO(pos, COLOR)



#############№##############################################


# process input


#############################################################


# This function is used to process input for the game


# the mouse click is handle here and the click is recorded


############################################################



def process_input():  # process the input of the system


    global tic_tac_toe, turn, gameOver


    # this handle the keyboard & mouse events


    for event in pygame.event.get():


        if event.type == pygame.QUIT:  # if press quit


            pygame.quit()


            sys.exit()


        if event.type == pygame.MOUSEBUTTONDOWN and event.dict['button'] == 1# if left mouse button is pressed


            if turn == _player and not gameOver:  # if it is the player's turn


                if tic_tac_toe[find_pos(event.dict['pos'])] == 0:

                    tic_tac_toe[find_pos(event.dict['pos'])] = player_score


                turn = _computer



####################################################################################


# computer move


####################################################################################


# compute the moves of the computer the AI is handled here


####################################################################################



def computer_move(x_a):  # this function handle the AI


    for val in [2 * computer_score,

                2 * player_score]:  # -2 check for winning conditon and 2 for blocking the win of player


        if x_a[0] + x_a[4] + x_a[8] == val:  # check diaganaly /


            if x_a[0] == 0:


                return 0


            elif x_a[4] == 0:


                return 4


            elif x_a[8] == 0:


                return 8


        if x_a[2] + x_a[4] + x_a[6] == val:  # check diaganaly \


            if x_a[2] == 0:


                return 2


            elif x_a[4] == 0:


                return 4


            elif x_a[6] == 0:


                return 6


        for i in [0, 3, 6]:


            if x_a[i] + x_a[i + 1] + x_a[i + 2] == val:  # check Horizontaly


                if x_a[i] == 0:


                    return i


                elif x_a[i + 1] == 0:


                    return i + 1


                elif x_a[i + 2] == 0:


                    return i + 2


        for i in [0, 1, 2]:


            if x_a[i] + x_a[i + 3] + x_a[i + 6] == val:  # check vertically


                if x_a[i] == 0:


                    return i


                elif x_a[i + 3] == 0:


                    return i + 3


                elif x_a[i + 6] == 0:


                    return i + 6


    while not no_moves():  # if no wining or blocking situation make a random move


        pos = random.randint(0, 89) // 10


        if x_a[pos] == 0# if the posision is empty


            return pos



##################################################################################


# no moves


##################################################################################


# find if there is no more moves left


##################################################################################



def no_moves():  # to find out any moves left


    global tic_tac_toe


    for i in range(0, 9):


        if tic_tac_toe[i] == 0# if the position is empty


            return False


    return True



###################################################################################


# win


###################################################################################


# find if computer or player has win the game


###################################################################################



def win(x_a, player):  # find the winner


    global player_score, computer_score


    if player == _player:


        score = player_score * 3


    else:


        score = computer_score * 3


    if x_a[0] + x_a[4] + x_a[8] == score or x_a[2] + x_a[4] + x_a[6] == score or \

 \

            x_a[0] + x_a[1] + x_a[2] == score or x_a[3] + x_a[4] + x_a[5] == score or x_a[6] + x_a[7] + x_a[

        8] == score or \

 \

            x_a[0] + x_a[3] + x_a[6] == score or x_a[1] + x_a[4] + x_a[7] == score or x_a[2] + x_a[5] + x_a[

        8] == score:  # check if there is a wining situation



        return True


    else:


        return False



###################################################################################


# draw win


###################################################################################


# draw the winning lines


###################################################################################



def draw_win(x_a, COLOR):  # draw the winning lines


    global screen


    for val in [3 * computer_score, 3 * player_score]:


        if x_a[0] + x_a[4] + x_a[8] == val:

            pygame.draw.line(screen, COLOR, (0, 0), (WIDTH, HEIGHT), 4)


        if x_a[2] + x_a[4] + x_a[6] == val:

            pygame.draw.line(screen, COLOR, (0, HEIGHT), (WIDTH, 0), 4)


        for i, num in enumerate([0, 3, 6]):


            if x_a[num] + x_a[num + 1] + x_a[num + 2] == val:

                pygame.draw.line(screen, COLOR, (0, int(i * HEIGHT / 3 + HEIGHT / 6)),

                                 (WIDTH, int(i * HEIGHT / 3 + HEIGHT / 6)), 4)


        for num in [0, 1, 2]:


            if x_a[num] + x_a[num + 3] + x_a[num + 6] == val:

                pygame.draw.line(screen, COLOR, (int(num * WIDTH / 3 + WIDTH / 6), 0),

                                 (int(num * WIDTH / 3 + WIDTH / 6), HEIGHT), 4)



##################################################################################


# display message


##################################################################################


# this function use to display message to the game screen


##################################################################################



def display_messege(message, COLOR):  # This function use to deiplay message (WIN) to screen


    screen.blit(m_display, (0, int(HEIGHT / 2 - 80)))


    wins = myFont.render(message, 2, COLOR)


    screen.blit(wins, (text_x, text_y))



#################################################################################


# game


##################################################################################


# the main function of the game this is use to run the game


##################################################################################



def game():  # main game function


    global screen, tic_tac_toe, gameOver, turn, computer_score, myFont, m_display, BLUE, GREEN, WHITE, HEIGHT, WIDTH


    init_pygame()  # initialize the pygame settings


    # main game loop execution bigins hear


    while True:


        screen.fill(BACKGROUND_COLOR)


        process_input()


        game_screen(WHITE)


        if not gameOver:  # do this if game is not over


            if turn == _computer and not win(tic_tac_toe,

                                             _player) and not no_moves():  # if it is the computers turn do this


                tic_tac_toe[computer_move(tic_tac_toe)] = computer_score


                turn = _player


            gameOver = win(tic_tac_toe, _player) or win(tic_tac_toe, _computer)




        else:


            draw_win(tic_tac_toe, RED)


            if win(tic_tac_toe, _player):  # if player wins show message


                display_messege("player Wins!!!", GREEN)


            elif win(tic_tac_toe, _computer):  # if computer wins show message


                display_messege("Computer Wins!!", GREEN)


        if no_moves():  # if no more moves show message


            pygame.draw.line(screen, RED, (0, 0), (WIDTH, HEIGHT), 4)


            pygame.draw.line(screen, RED, (0, HEIGHT), (WIDTH, 0), 4)


            display_messege("No more moves!!", GREEN)


        pygame.display.update()



game()  # game bigins here