#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Jan 20 13:43:26 2020

@author: sairaman

****** TIC - TAC - TOE ******

This game is designed to be played between a Player vs. the Computer

Functions: 
    disp(arr) - which takes a 3x3 board array and prints it as the game board
    mapping(c) - maps the user char input to the appropriate location on the 3x3 board array
    winChk(arr) -  takes the input of the 3x3 board array and checks the status of the game (win/loss/draw)
    computer_choice - which determines what the computer's choice for each turn:
        The Logic Loop of the computer's choice of play is as follows: 
            Check if Victory can be attained in the next move, if yes, take it;
            if not, check if opponent can attain victory in the next move, if yes, block it;
            if not, (choose an empty cell by the following logic)
                if computer is "O" (second player) then center spot is highest preferred 
                else, 
                choose a cell in the below (decreasing) order of preference
                any corner spot
                any edge spot 
                center spot (if computer is 'X')
            
        Note that by this logic, the player can never win the game. The Computer always wins / draws the game
        
        PS: The logic for the computer's moves is very simplistic and hence can be instructive in this manner. 
            For a game like Chess this would not be possible, as there significantly more possibilities.
            A more neat way to code this up would be to let the computer find the next best move by through recursion.    
    
The logical flow of the game loop is as follows: 
    Display Board
    User Input / Computer Input
    Computer Input / User Input 
    Check for end of Game
    
    
    
    

*****************************
"""

def disp(arr):
    
    """
    *** A FUNCTION TO DISPLAY 3x3 Tic-Tac-Toe Board ***
    """
    print("\n")
    print("|",arr[0][0],"|",arr[0][1],"|",arr[0][2],"|","\n")
    print("|",arr[1][0],"|",arr[1][1],"|",arr[1][2],"|","\n")
    print("|",arr[2][0],"|",arr[2][1],"|",arr[2][2],"|","\n")
    print("\n")
    
def mapping(c):
    
    """
    *** A FUNCTION TO MAP INPUTS TO THE GRID ***
    The input is designed to be rhomnbus on the QWERTY-keyboard using the characters from characeter Q to character C
    """
    
    if c.lower()=='q':
        return 0,0
    elif c.lower()=='w':
        return 0,1
    elif c.lower()=='e':
        return 0,2
    elif c.lower()=='a':
        return 1,0
    elif c.lower()=='s':
        return 1,1
    elif c.lower()=='d':
        return 1,2
    elif c.lower()=='z':
        return 2,0
    elif c.lower()=='x':
        return 2,1
    elif c.lower()=='c':
        return 2,2
    else:
        return

def winChk(arr):
    """
    The function that checks if the Game is over
    """
    
    """ Row Check for victory """
    
    for i in range(3):
        if arr[i][0]==arr[i][1]==arr[i][2] and arr[i][0]!="_":
            return arr[i][1]
    
    """ Col Check for victory """
    
    for j in range(3):
        if arr[0][j]==arr[1][j]==arr[2][j] and arr[0][j]!="_":
            return arr[0][j]
    
    """ Diagonal Check for Victory """
    
    if arr[0][0]==arr[1][1]==arr[2][2] and arr[1][1]!="_":
        return arr[1][1]
    
    if arr[0][2]==arr[1][1]==arr[2][0] and arr[1][1]!="_":
        return arr[1][1]  

    """ Draw Check """
    not_yet_over = 0
    for i in range(3):
        for j in range(3):
            if arr[i][j]=="_":
                not_yet_over = 1
                break
                
    """ No Victory Yet """ 
    return not_yet_over


def computer_choice(arr,letter):
    
    """
    A Funtion to determine the optimal choice that the computer has to make 
    
    In this design, the computer will always WIN or DRAW the game
    
    """
    
    # duplicating the board to test
    arr2=arr

    # if victory available in next step take it
    for i in range(3):
        for j in range(3):
            if arr[i][j]=="_":
                arr2[i][j]=letter
                if winChk(arr2)==letter:
                    return i,j
                else:
                    arr2[i][j]="_"
                    continue
    
    # block victory of opponent 
    if letter=="X":
        playerLet="O"
    else:
        playerLet="X"
        
    for i in range(3):
        for j in range(3):
            if arr[i][j]=="_":
                arr2[i][j]=playerLet
                if winChk(arr2)==playerLet:
                    return i,j
                else:
                    arr2[i][j]="_"
                    continue
            
    
    # if the computer is "O" - center is the first best choice    
    if letter == "O":
        #center
        a,b=mapping('s')
        if arr[a][b]=="_":
            return a,b

    # choose any cell preference starting from corners

    #corners
    for choice in ['q','e','z','c']: 
        a,b=mapping(choice)
        if (arr[a][b]=="_"):
            return a,b
    #center
    a,b=mapping('s')
    if arr[a][b]=="_":
        return a,b
    #sides
    for choice in ['a','w','d','x']: 
        a,b=mapping(choice)
        if (arr[a][b]=="_"):
            return a,b
    
    
    
def main():
          
    arr = []
    
    print("\nThe input mechanism for this game is designed in the following way: \n")    
    arr.append(["q","w","e"])
    arr.append(["a","s","d"])
    arr.append(["z","x","c"])
    disp(arr)
    print("You will thus be inputting the location pf your choice by using the Qwerty keyboard using the first 9-characters -- between q & c ")
    
    inp="n"
    while(inp.lower()!="y"):
        inp = input("Got it?? (Y/N) --> " )
    
    arr = []

    arr.append(["_","_","_"])
    arr.append(["_","_","_"])
    arr.append(["_","_","_"])
    
    allowed = ['q','w','e','a','s','d','z','x','c']
    
    i=1
    res=1
    inp = 'a'
    while(inp!="0" and inp.lower()!="x" and inp.lower()!="o"):
        inp = input("Do you want to be X or O? (X ALWAYS GOES FIRST) --> " )
    
    if inp == 0:
        compLet="X"
    elif inp.upper() == "X":
        compLet="O"
    else:
        compLet="X"
        
    while(res==1):
        
        disp(arr)
        
        if i==1: # X's Turn
            if compLet=="O":
                inp = input("Where do you want the X? --> ")
                if inp.lower() in allowed:
                    a,b=mapping(inp)
                    if(arr[a][b]=="_"):
                        arr[a][b]="X"
                    else:
                        print("Can't input to that location - its already filled")
                        continue
                    i=2
                else:
                    print("Invalid Input")
                    continue
            else:
                a,b = computer_choice(arr,compLet)
                arr[a][b]="X"
                i=2

        else: # O's Turn
            if compLet=="X":
                inp = input("Where do you want the O? --> ")
                if inp.lower() in allowed:
                    a,b=mapping(inp)
                    if(arr[a][b]=="_"):
                        arr[a][b]="O"
                    else:
                        print("Can't input to that location - its already filled")
                        continue
                    i=1
                else:
                    print("Invalid Input")
                    continue
                
            else:
                a,b = computer_choice(arr,compLet)
                arr[a][b]="O"
                i=1
        
        res = winChk(arr)
    
    disp(arr)
    if res==0:
        print("Guess that was draw")
    else:
        print("Player-"  +res + " won the game")


if __name__ == '__main__':
    main()