-3

The problem is that it is not detecting a draw and just hangs if noone wins. I understand that it isn't a good practice to paste the whole script here and ask for help but I'm all out of ideas. I got this TicTacToe script off of github and am trying to implement random moves between two AI players (both making only random moves).

    import random
    import time


class Tic(object):
 winning_combos = (
    [0, 1, 2], [3, 4, 5], [6, 7, 8],
    [0, 3, 6], [1, 4, 7], [2, 5, 8],
    [0, 4, 8], [2, 4, 6])

    winners = ('X-win', 'Draw', 'O-win')

    def __init__(self, squares=[]):
        if len(squares) == 0:
            self.squares = [" " for i in range(9)]
        else:
            self.squares = squares

def show(self):
    for element in [self.squares[i:i + 3] for i in range(0, len(self.squares), 3)]:
        print(element)

def available_moves(self):
    """what spots are left empty?"""
    return [k for k, v in enumerate(self.squares) if v is " "]

def available_combos(self, player):
    """what combos are available?"""
    return self.available_moves() + self.get_squares(player)

def complete(self):
    """is the game over?"""
    if " " not in [v for v in self.squares]:
        return True
    if self.winner() != " ":
        return True
    return False

def X_won(self):
    return self.winner() == 'X'

def O_won(self):
    return self.winner() == 'O'

def tied(self):
    return self.complete() is True and self.winner() is " "

def winner(self):
    for player in ('X', 'O'):
        positions = self.get_squares(player)
        for combo in self.winning_combos:
            win = True
            for pos in combo:
                if pos not in positions:
                    win = False
            if win:
                return player

    return " "

def get_squares(self, player):
    """squares that belong to a player"""
    return [k for k, v in enumerate(self.squares) if v == player]

def make_move(self, position, player):
    """place on square on the board"""
    self.squares[position] = player


def determine(board, player):
    a = -2
    choices = []
    if len(board.available_moves()) == 9:
        return 4
    for move in board.available_moves():
        board.make_move(move, player)
        board.make_move(move, " ")
        if val > a:
            a = val
            choices = [move]
        elif val == a:
            choices.append(move)
    return random.choice(choices)


def get_enemy(player):
    if player == 'O':
        return 'X'
    return 'O'


board = Tic()

count = 0
player = 'X'

while not board.complete():
        if board.complete():
            break
        while count == 0:
            player_move = int(random.randint(1, 9))
            if player_move not in board.available_moves():
                continue
            board.make_move(player_move, player)

            player = get_enemy(player)
            count += 1

        while count == 1:
            computer_move = int(random.randint(1, 9))
            if computer_move not in board.available_moves():
                continue
            board.make_move(computer_move, player)

            count -= 1

        if board.complete():
            break


if board.complete():
        print("winner is", board.winner())
        final_win = "winner is " + board.winner()
        log = open("log_for_orig.txt", "a")
        log.write(final_win + "\n" + "\n")
KradleGod
  • 1
  • 1
  • 1
    Try cutting down on your code to come up with a [mcve]. That will help you narrow down the problem, and help us give you suggestions. – Praveen Aug 19 '16 at 01:31

2 Answers2

1

This is a very poor way to select an available move:

while count == 0:
    player_move = int(random.randint(1, 9))
    if player_move not in board.available_moves():
        continue

It will work OK when there are lots of available moves. But when there are very few available moves, it may take a long time for random.randint() to pick one of them, so your program may seem to hang.

The random module provides a function for selecting an element from a list directly.

if count == 0:
    player_move = random.choice(board.available_moves())

See How to randomly select an item from a list?

Community
  • 1
  • 1
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

Player block

    while count == 0:
        player_move = int(random.randint(1, 9))
        if player_move not in board.available_moves():
            continue

Computer block

    while count == 1:
        computer_move = int(random.randint(1, 9))
        if computer_move not in board.available_moves():
            continue

Problem lies in above two blocks of code.

In the first block, when count is 0, and player_move is not in available moves, then you are skipping by doing continue, so count still remains 0, which will make it enter in same first block and this pattern continues until unless player changes his move. You should basically prompt user to change his move rather than continuing.

Same applies for second block of code as well. As computer is playing, you should deal it in much better way.

be_good_do_good
  • 4,311
  • 3
  • 28
  • 42
  • The player move doesn't come from the user, it comes from `random.randint(1, 9)`. It looks like the idea is that it should keep picking a move until it finds one that's available. Then it will get past this and execute the code that changes `count`. – Barmar Aug 19 '16 at 01:35
  • @Barmar then I feel that you should move getting player move part to separate function and then keep calling it rather than letting it go through entire while loop. Much better way is to pick randomly from board.available_moves() rather than from `int(random.randint(1, 9))` – be_good_do_good Aug 19 '16 at 01:43