Tic Tac Toe - Code

From RoboWiki
Revision as of 16:27, 4 June 2023 by Robot (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

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

Python code for the Tic Tac Toe project:

 
from spike import PrimeHub, LightMatrix, Button, StatusLight, ForceSensor, MotionSensor, Speaker, ColorSensor, App, DistanceSensor, Motor, MotorPair
from spike.control import wait_for_seconds, wait_until, Timer

hub = PrimeHub()

hub.light_matrix.show_image('HAPPY')
wait_for_seconds(2)

motor_up = Motor('F')
motor_down = Motor('B')
head_colorsensor = ColorSensor('D')
motor_up.set_default_speed(100)
motor_down.set_default_speed(10)
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 = [['', '', ''], ['', '', ''], ['', '', '']]
    number_of_moves = 0

    def play(self):
        hub.light_matrix.off()
        while True:
            hub.right_button.wait_until_pressed()
            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:
                hub.light_matrix.write('I WIN!!!')
                return
            elif win == -10:
                hub.light_matrix.write('You WIN!!!')
                return
            elif not isMovesLeft(self.tic_tac_toe_matrix):
                hub.light_matrix.write('Draw')
                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:
                hub.light_matrix.write('I WIN!!!')
                return
            elif win == -10:
                hub.light_matrix.write('You WIN!!!')
                return
            elif not isMovesLeft(self.tic_tac_toe_matrix):
                hub.light_matrix.write('Draw')
                return
            # if self.win_check():
            #    return

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

    def get_new_tic_tac_toe_matrix(self):
        new_tic_tac_toe_matrix = [['', '', ''], ['', '', ''], ['', '', '']]
        self.number_of_moves = 0
        for line in range(3):
            for column in range(3):
                color = head_colorsensor.get_color()
                print(color)
                if color == "black":
                    new_tic_tac_toe_matrix[line][column] = player
                    hub.light_matrix.set_pixel(line, column, 80)
                    self.number_of_moves +=1
                elif color == "violet":
                    new_tic_tac_toe_matrix[line][column] = robot
                    hub.light_matrix.set_pixel(line, column, 100)
                    self.number_of_moves +=1
                else:
                    hub.light_matrix.set_pixel(line, column, 0)

                if column == 0:
                    motor_up.run_for_degrees(self.degree_for_move_one_row1 * -1)
                elif column == 1:
                    motor_up.run_for_degrees(self.degree_for_move_one_row2 * -1)

            motor_up.run_for_degrees(self.degree_for_move_one_row1 + self.degree_for_move_one_row2)
            if line != 2:
                motor_down.run_for_degrees(self.degree_for_move_one_line * -1)

        motor_down.run_to_position(340)
        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] == player or self.tic_tac_toe_matrix[0][2] == player or self.tic_tac_toe_matrix[2][0] == player or self.tic_tac_toe_matrix[2][2] == player:
            #     return 2,1
            # else:
            if self.tic_tac_toe_matrix[0][0] == '':
                return 0,0
            elif self.tic_tac_toe_matrix[2][0] == '':
                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] == '':
                    return 2,2
                elif self.tic_tac_toe_matrix[2][0] == '':
                    return 2,0
                else :
                    return 0, 2
        return findBestMove(self.tic_tac_toe_matrix)


    def show_move(self, line, column):
        while not hub.left_button.was_pressed():
            for i in range(5, 10):
                hub.light_matrix.set_pixel(line, column, 10 * i)
                wait_for_seconds(0.25)
            for i in range(0, 5):
                hub.light_matrix.set_pixel(line, column, 100 - 10 * i)
                wait_for_seconds(0.25)
        self.tic_tac_toe_matrix[line][column] = robot
        hub.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] == ''):
                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] == ''):
                    # 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] = ''
        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] == ''):
                    # 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] = ''
        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] == ''):

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

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

                # Undo the move
                board[i][j] = ''

                # 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()