Tic Tac Toe - Code V3

From RoboWiki
Jump to: navigation, search

Return back to project page: Tic Tac Toe - Fedor Agarshev

Python code for the Tic Tac Toe project:

 
from hub import light_matrix, port, button, light, speaker
import motor,time, color_sensor




motor_up = port.F
motor_down = port.B
head_colorsensor = port.D
motor_up_speed = 1000
motor_down_speed = 200
player = 0
robot = 1


class TikTakToeWithRobot:
    degree_for_move_one_line = 30
    degree_for_move_one_row1 = 250
    degree_for_move_one_row2 = 225
    whose_move = ''
    robot_chip_color = 'violet'
    player_chip_color = 'black'
    tic_tac_toe_matrix = [[-1, -1, -1], [-1, -1, -1], [-1, -1, -1]]
    number_of_moves = 0

    def play(self):
        light_matrix.clear()
        light_matrix.show_image(3) #image HAPPY
        
        while True:
            while not button.pressed(button.RIGHT): # Wait for the right button to be pressed
                pass
            time.sleep_ms(2000)
            new_tic_tac_toe_matrix = self.get_new_tic_tac_toe_matrix()
            self.check_tic_tac_toe_matrix_for_player_move(new_tic_tac_toe_matrix)
            self.show_light_matrix()
            print(self.tic_tac_toe_matrix)
            win = evaluate(self.tic_tac_toe_matrix)
            if win == 10:
                light_matrix.write('I WIN!!!')
                time.sleep_ms(2000)
                return
            elif win == -10:
                light_matrix.write('You WIN!!!')
                time.sleep_ms(2000)
                return
            elif not isMovesLeft(self.tic_tac_toe_matrix):
                light_matrix.write('Draw')
                time.sleep_ms(2000)
                return
            # if self.win_check():
            #    return

            line_move, column_move = self.get_move()
            self.show_move(line_move, column_move)
            self.show_light_matrix()

            win = evaluate(self.tic_tac_toe_matrix)
            if win == 10:
                light_matrix.write('I WIN!!!')
                time.sleep_ms(2000)
                return
            elif win == -10:
                light_matrix.write('You WIN!!!')
                time.sleep_ms(2000)
                return
            elif not isMovesLeft(self.tic_tac_toe_matrix):
                light_matrix.write('Draw')
                time.sleep_ms(2000)
                return

    def show_light_matrix(self):
        light_matrix.clear()
        for line in range(3):
            for column in range(3):
                if self.tic_tac_toe_matrix[line][column] == player:
                    light_matrix.set_pixel(line, column, 80)
                elif self.tic_tac_toe_matrix[line][column] == robot:
                    light_matrix.set_pixel(line, column, 100)

    def get_new_tic_tac_toe_matrix(self):
        light_matrix.clear()
        new_tic_tac_toe_matrix = [[-1, -1, -1], [-1, -1, -1], [-1, -1, -1]]
        self.number_of_moves = 0
        for line in range(3):
            for column in range(3):
                color = color_sensor.color(head_colorsensor)
                print(color)
                if color == 0:
                    new_tic_tac_toe_matrix[line][column] = player
                    light_matrix.set_pixel(line, column, 80)
                    self.number_of_moves +=1
                elif color == 1:
                    new_tic_tac_toe_matrix[line][column] = robot
                    light_matrix.set_pixel(line, column, 100)
                    self.number_of_moves +=1
                else:
                    light_matrix.set_pixel(line, column, 0)

                if column == 0:
                    motor.run_for_degrees(motor_up, self.degree_for_move_one_row1 * -1, motor_up_speed)
                    time.sleep_ms(1000)
                elif column == 1:
                    motor.run_for_degrees(motor_up, self.degree_for_move_one_row2 * -1, motor_up_speed)
                    time.sleep_ms(1000)

            motor.run_for_degrees(motor_up, self.degree_for_move_one_row1 + self.degree_for_move_one_row2, motor_up_speed)
            time.sleep_ms(1000)
            if line != 2:
                motor.run_for_degrees(motor_down, self.degree_for_move_one_line * -1, motor_down_speed)
                time.sleep_ms(1000)

        motor.run_for_degrees(motor_down, self.degree_for_move_one_line + self.degree_for_move_one_line, motor_down_speed)
        time.sleep_ms(1000)
        return new_tic_tac_toe_matrix

    def check_tic_tac_toe_matrix_for_player_move(self, new_tic_tac_toe_matrix):
        self.tic_tac_toe_matrix = new_tic_tac_toe_matrix
        return

    def get_move(self):
        if self.number_of_moves == 0:
            return 0,0
        elif self.number_of_moves == 1:
            if self.tic_tac_toe_matrix[0][0] == -1:
                return 0,0
            elif self.tic_tac_toe_matrix[2][0] == -1:
                return 2,0
        elif self.number_of_moves == 2:
            if self.tic_tac_toe_matrix[1][1] == player:
                return 2,2
            if self.tic_tac_toe_matrix[0][1] == player or self.tic_tac_toe_matrix[1][0] == player or self.tic_tac_toe_matrix[1][2] == player or self.tic_tac_toe_matrix[2][1] == player:
                return 1,1
            else:
                if self.tic_tac_toe_matrix[2][2] == -1:
                    return 2,2
                elif self.tic_tac_toe_matrix[2][0] == -1:
                    return 2,0
                else :
                    return 0, 2
        return findBestMove(self.tic_tac_toe_matrix)


    def show_move(self, line, column):
        while not button.pressed(button.LEFT):
            for i in range(5, 10):
                light_matrix.set_pixel(line, column, 10 * i)
                time.sleep_ms(250)
            for i in range(0, 5):
                light_matrix.set_pixel(line, column, 100 - 10 * i)
                time.sleep_ms(250)
        self.tic_tac_toe_matrix[line][column] = robot
        light_matrix.set_pixel(line, column, 100)
        return


# This function returns true if there are moves
# remaining on the board. It returns false if
# there are no moves left to play.
def isMovesLeft(board):
    for i in range(3):
        for j in range(3):
            if (board[i][j] == -1):
                return True
    return False


# This is the evaluation function as discussed
# in the previous article ( http://goo.gl/sJgv68 )
def evaluate(b):
    # Checking for Rows for 1 or 0 victory.
    for row in range(3):
        if (b[row][0] == b[row][1] and b[row][1] == b[row][2]):
            if (b[row][0] == robot):
                return 10
            elif (b[row][0] == player):
                return -10

    # Checking for Columns for 1 or 0 victory.
    for col in range(3):

        if (b[0][col] == b[1][col] and b[1][col] == b[2][col]):

            if (b[0][col] == robot):
                return 10
            elif (b[0][col] == player):
                return -10

    # Checking for Diagonals for 1 or 0 victory.
    if (b[0][0] == b[1][1] and b[1][1] == b[2][2]):

        if (b[0][0] == robot):
            return 10
        elif (b[0][0] == player):
            return -10

    if (b[0][2] == b[1][1] and b[1][1] == b[2][0]):

        if (b[0][2] == robot):
            return 10
        elif (b[0][2] == player):
            return -10

    # Else if none of them have won then return 0
    return 0


# This is the minimax function. It considers all
# the possible ways the game can go and returns
# the value of the board
def minimax(board, depth, isMax):
    score = evaluate(board)

    # If Maximizer has won the game return his/her
    # evaluated score
    if (score == 10):
        return score

    # If Minimizer has won the game return his/her
    # evaluated score
    if (score == -10):
        return score

    # If there are no more moves and no winner then
    # it is a tie
    if (isMovesLeft(board) == False):
        return 0

    # If this maximizer's move
    if (isMax):
        best = -1000

        # Traverse all cells
        for i in range(3):
            for j in range(3):

                # Check if cell is empty
                if (board[i][j] == -1):
                    # Make the move
                    board[i][j] = robot

                    # Call minimax recursively and choose
                    # the maximum value
                    best = max(best, minimax(board,
                                            depth + 1,
                                            not isMax))

                    # Undo the move
                    board[i][j] = -1
        return best

    # If this minimizer's move
    else:
        best = 1000

        # Traverse all cells
        for i in range(3):
            for j in range(3):

                # Check if cell is empty
                if (board[i][j] == -1):
                    # Make the move
                    board[i][j] = player

                    # Call minimax recursively and choose
                    # the minimum value
                    best = min(best, minimax(board, depth + 1, not isMax))

                    # Undo the move
                    board[i][j] = -1
        return best


# This will return the best possible move for the player
def findBestMove(board):
    bestVal = -1000
    bestMove = (-1, -1)

    # Traverse all cells, evaluate minimax function for
    # all empty cells. And return the cell with optimal
    # value.
    for i in range(3):
        for j in range(3):

            # Check if cell is empty
            if (board[i][j] == -1):

                # Make the move
                board[i][j] = robot

                # compute evaluation function for this
                # move.
                moveVal = minimax(board, 0, False)

                # Undo the move
                board[i][j] = -1

                # If the value of the current move is
                # more than the best value, then update
                # best/
                print("The value of the Move is :", moveVal, "for", i, j)
                if (moveVal > bestVal):

                    bestMove = (i, j)
                    bestVal = moveVal


    print("The value of the best Move is :", bestVal)
    print()
    return bestMove

game = TikTakToeWithRobot()
game.play()