A Tic tac toe program#

def create_board():
  return [[' ', ' ', ' '], [' ', ' ', ' '], [' ', ' ', ' ']]
def display_board(board):
  board_str = ""
  for i in range(0, 3):
    board_str += ' '
    for j in range(0, 3):
      board_str += str(board[i][j])
      if j != 2:
        board_str += " | "      
    board_str += '\n'
    if i != 2 :    
      board_str += "-----------\n"    
  print(board_str)
def evaluate_board(board): 

    has_empty_cell = False
    for i in range(0, 3):
      for j in range(0, 3):
        if board[i][j] ==  ' ':
          has_empty_cell = True
          break

    if not has_empty_cell:
      return 'Draw'

    players = ['X', 'O']
    for player in players:

      # winning row wise
      for i in range(0, 3):
        is_winning = True
        for j in range(0, 3):
          is_winning = is_winning and board[i][j] == player
        if is_winning:
          return player

      # winning column wise
      for j in range(0, 3):
        is_winning = True
        for i in range(0, 3):
          is_winning = is_winning and board[i][j] == player
        if is_winning:
          return player

      # winning cross
      if board[0][0] == player and board[1][1] == player and board[2][2] == player:
        return player

      if board[0][2] == player and board[1][1] == player and board[2][0] == player:
        return player

    return None
def tictactoe(strategy):
  board = create_board()

  while True:

    display_board(board)

    row = input("Row: ")
    if row == 'q':
      break

    col = input("Column: ")
    if col == 'q':
      break

    row = int(row)-1
    col = int(col)-1

    if board[row][col] == ' ':
      board[row][col] = 'X'
      #display_board(board)

      result = evaluate_board(board)
      if result:
        display_board(board)
        print('Winner: ', result)
        break

      # the machines turn...
      best_row, best_col, best_score = strategy(board)
      board[best_row][best_col] = 'O'

      result = evaluate_board(board)
      if result:
        display_board(board)
        print('Winner: ', result)
        break    

    else:
      print('Cell is already taken! Try again...')      

  print('Exited.')
def copy_board(board):
  return [board[0].copy(), board[1].copy(), board[2].copy()]
def strategy_greedy(board): 
  best_i = None
  best_j = None
  for i in range(0, 3):
    for j in range(0, 3):
      if board[i][j] == ' ':
        best_i = i
        best_j = j

        board_o = copy_board(board)              
        board_o[i][j] = 'O'  
        
        result = evaluate_board(board_o)
        if result is not None and result == 'O':
            return i, j, None
  return best_i, best_j, None
#@title
tictactoe(strategy_greedy)
   |   |  
-----------
   |   |  
-----------
   |   |  
---------------------------------------------------------------------------
StdinNotImplementedError                  Traceback (most recent call last)
Cell In[7], line 2
      1 #@title
----> 2 tictactoe(strategy_greedy)

Cell In[4], line 8, in tictactoe(strategy)
      4 while True:
      6   display_board(board)
----> 8   row = input("Row: ")
      9   if row == 'q':
     10     break

File ~/env/uni/lib/python3.8/site-packages/ipykernel/kernelbase.py:1190, in Kernel.raw_input(self, prompt)
   1188 if not self._allow_stdin:
   1189     msg = "raw_input was called, but this frontend does not support input requests."
-> 1190     raise StdinNotImplementedError(msg)
   1191 return self._input_request(
   1192     str(prompt),
   1193     self._parent_ident["shell"],
   1194     self.get_parent("shell"),
   1195     password=False,
   1196 )

StdinNotImplementedError: raw_input was called, but this frontend does not support input requests.
def strategy_one_move(board): 
  best_i = None
  best_j = None
  best_score = float('-inf')
  # play all possible computation with O and find the most favorable position
  for i in range(0, 3):
    for j in range(0, 3):
      if board[i][j] == ' ':
        board_o = copy_board(board)              
        board_o[i][j] = 'O'  
        
        result = evaluate_board(board_o)
        if result is not None and result == 'O':
            return i, j, 1e6

        # play all possible computation with X and compute the score
        # the score gives us how favorable the position for O: how many
        # winning chances are there and whether the position is lost. 
        score = 0
        for k in range(0, 3):
          for l in range(0, 3):
            if board_o[k][l] == ' ':   
              board_x = copy_board(board_o)            
              board_x[k][l] = 'X'
              result = evaluate_board(board_x)
              if result is not None:
                if (result == 'O'):
                  score += 1
                elif (result == 'Draw'):
                  score += 0
                elif (result == 'X'):
                  score += -1e6
        
        print(i+1, j+1, score) 

        if score > best_score:
          best_score = score
          best_i = i
          best_j = j

  return best_i, best_j, best_score
tictactoe(strategy_one_move) # play 3,3 -> 2,2 -> 1,3
   |   |  
-----------
   |   |  
-----------
   |   |  

Row: 3
Column: 3
1 1 0
1 2 0
1 3 0
2 1 0
2 2 0
2 3 0
3 1 0
3 2 0
 O |   |  
-----------
   |   |  
-----------
   |   | X

Row: 2
Column: 2
1 2 0
1 3 0
2 1 0
2 3 0
3 1 0
3 2 0
 O | O |  
-----------
   | X |  
-----------
   |   | X

Row: 1
Column: 3
2 1 -2000000.0
2 3 -1000000.0
3 1 -1000000.0
3 2 -2000000.0
 O | O | X
-----------
   | X | O
-----------
   |   | X

Row: 3
Column: 1
 O | O | X
-----------
   | X | O
-----------
 X |   | X

Winner:  X
Exited.
def strategy_recursive(board, depth=0): 

  # 1. evaluate position and return if this is an end position
  result = evaluate_board(board)
  if result is not None:
    if (result == 'O'):
      return None, None, 1
    elif (result == 'Draw'):
      return None, None, 0      
    elif (result == 'X'):
      return None, None, -1e6

  # 2. expand: play all possible computation with O
  best_i = None
  best_j = None
  best_score = float('-inf')
  for i in range(0, 3):
    for j in range(0, 3):
      if board[i][j] == ' ':
        board_o = copy_board(board)              
        board_o[i][j] = 'O'  
        
        result = evaluate_board(board_o)
        if result is not None and result == 'O':
            return i, j, 1

        # play all possible computation with X and compute the score
        # the score gives us how favorable the position for O: how many
        # winning chances are there and whether the position is lost. 
        score = 0
        for k in range(0, 3):
          for l in range(0, 3):
            if board_o[k][l] == ' ':   
              board_x = copy_board(board_o)            
              board_x[k][l] = 'X'

              # Instead of this:
              # result = evaluate_board(board_x)

              # recursive call to get the score for the next possible moves
              _, _, step_score = strategy_recursive(board_x, depth+1)
              score += step_score

        if depth == 0: # some analytics
          print(i+1, j+1, score)  

        if score > best_score:
          best_score = score
          best_i = i
          best_j = j

  return best_i, best_j, best_score
tictactoe(strategy_recursive)
   |   |  
-----------
   |   |  
-----------
   |   |  

Row: q
Exited.
2
2