pythonmachine-learningartificial-intelligencetic-tac-toeheuristics

Error in Heuristics Tic-Tac-Toe Python code - string index out of range


from random import choice
import numpy as np

combo_indices = [
    [0,1,2],
    [3,4,5],
    [6,7,8],
    [0,3,6],
    [1,4,7],
    [2,5,8],
    [0,4,8],
    [2,4,6]
]

EMPTY_SIGN = '.'
AI_SIGN = 'X'
OPPONENT_SIGN = 'O'


def all_moves_from_board(board, sign):
    move_list = []
    for i,v in enumerate(board):
        if v == EMPTY_SIGN:
            move_list.append(board[:1] + sign + board[i+1:])
    return move_list

def game_won_by(board):
    for index in combo_indices:
        if board[index[0]] == board[index[1]] == board[index[2]] != EMPTY_SIGN:
            return board[index[0]]
    return EMPTY_SIGN


def filter_wins(move_list, ai_wins, opponent_wins):
    for board in move_list:
        won_by = game_won_by(board)
        if won_by == AI_SIGN:
            ai_wins.append(board)
            move_list.remove(board)
        elif won_by == OPPONENT_SIGN:
            opponent_wins.append(board)
            move_list.remove(board)    
    
def init_utility_matrix(board):
    return [0 if cell == EMPTY_SIGN else -1 for cell in board]

def generate_add_score(utilities, i , j, k):
    def add_score(points):
        if utilities[i] >= 0:
            utilities[i] += points
        if utilities[j] >= 0:
            utilities[j] += points
        if utilities[k] >= 0:
            utilities[k] += points 
    return add_score

def utility_matrix(board):
    utilities = init_utility_matrix(board)
    for [i,j,k] in combo_indices:
        add_score = generate_add_score(utilities, i, j, k)
        triple = [ board[i], board[j], board[k]]
        if triple.count(EMPTY_SIGN) == 1:
            if triple.count(AI_SIGN) == 2:
                add_score(1000)
            elif triple.count(OPPONENT_SIGN) == 2:
                add_score(100)
        elif triple.count(EMPTY_SIGN) == 2 and triple.count(AI_SIGN) == 1:
            add_score(10)
        elif triple.count(EMPTY_SIGN) == 3:
            add_score(1)
    return utilities


def best_moves_from_board(board, sign):
    move_list =[]
    utilities = utility_matrix(board)
    max_utility = max(utilities)
    for i,v in enumerate(board):
        if utilities[i] == max_utility:   
            move_list.append(board[:i] + sign + board[i+1:])
    return move_list

def all_moves_from_board_list(board_list, sign):
    move_list = []
    get_moves = best_moves_from_board if sign == AI_SIGN else all_moves_from_board
    for board in board_list:
        move_list.extend(get_moves(board, sign))
    return move_list

            
def count_possibilities():
    board = EMPTY_SIGN*9
    move_list = [board]
    ai_wins = []
    opponent_wins = []
    for i in range(9):
        print(' step ' + str(i) + '. Moves: ' + str(len(move_list)))
        sign = AI_SIGN if i%2==0 else OPPONENT_SIGN
        move_list = all_moves_from_board_list(move_list, sign)
        filter_wins(move_list, ai_wins, opponent_wins)
    print('First player wins: ' + str(len(ai_wins)))
    print('Second player wins: ' + str(len(opponent_wins)))
    print('Draw: ' + str(len(move_list)))
    print('Total: ' + str(len(ai_wins) + len(opponent_wins) + len(move_list) ))


count_possibilities()
        
    
    
    
    
    
    
    
    
    
    

This is my code above...

i am getting this error:-


IndexError                                Traceback (most recent call last)
Input In \[3\], in \<cell line: 107\>()
103     print('Draw: ' + str(len(move_list)))
104     print('Total: ' + str(len(ai_wins) + len(opponent_wins) + len(move_list) ))
\--\> 107 count_possibilities()

Input In \[3\], in count_possibilities()
98     sign = AI_SIGN if i%2==0 else OPPONENT_SIGN
99     move_list = all_moves_from_board_list(move_list, sign)
\--\> 100     filter_wins(move_list, ai_wins, opponent_wins)
101 print('First player wins: ' + str(len(ai_wins)))
102 print('Second player wins: ' + str(len(opponent_wins)))

Input In \[3\], in filter_wins(move_list, ai_wins, opponent_wins)
34 def filter_wins(move_list, ai_wins, opponent_wins):
35     for board in move_list:
\---\> 36         won_by = game_won_by(board)
37         if won_by == AI_SIGN:
38             ai_wins.append(board)

Input In \[3\], in game_won_by(board)
27 def game_won_by(board):
28     for index in combo_indices:
\---\> 29         if board\[index\[0\]\] == board\[index\[1\]\] == board\[index\[2\]\] != EMPTY_SIGN:
30             return board\[index\[0\]\]
31     return EMPTY_SIGN

IndexError: string index out of range

while calling the game_won_by function and then checking the if state for indexes 0,1,2 for board iteration it is showing string index out of range...

Please help anyone...

Error resolution :- String index out of range


Solution

  • In function all_moves_from_board I think it should be

    move_list = []
        for i, v in enumerate(board):
            if v == EMPTY_SIGN:
                move_list.append(board[:i] + sign + board[i + 1:])
    
        return move_list
    

    You accidentally wrote the first slicing of the board index to 1. I have not checked whether the code is working as it's intended to or not but now it runs and generates an output:

     step 0. Moves: 1
     step 1. Moves: 1
     step 2. Moves: 8
     step 3. Moves: 24
     step 4. Moves: 144
     step 5. Moves: 83
     step 6. Moves: 214
     step 7. Moves: 148
     step 8. Moves: 172
    First player wins: 504
    Second player wins: 12
    Draw: 91
    Total: 607