1

I have this Python program that plays tic tac toe between two human players. If Player A or Player B ever wins, it is announced and the program terminates. However, if the program ends in a draw, it will keep requesting user input.

I'm not sure how to check for a draw. Does it have to be within the while loop or does it require it's own separate function?

import sys

## Define and create tic tac toe gameboard
board = range(0,9)

def show_board():
    print board[0], '|', board[1], '|', board[2]
    print '---------'
    print board[3], '|', board[4], '|', board[5]
    print '---------'
    print board[6], '|', board[7], '|', board[8]

# Function used to check for winner
def line(char, box1, box2, box3):
    if board[box1] == char and board[box2] == char and board[box3] == char:
        return True

# Function used to automate process for checking every possible way to win
def all(char):
    # Horizontal check
    if line(char, 0, 1, 2):
        return True
    if line(char, 3, 4, 5):
        return True
    if line(char, 6, 7, 8):
        return True
    # Vertical check
    if line(char, 0, 3, 6):
        return True
    if line(char, 1, 4, 7):
        return True
    if line(char, 2, 5, 8):
        return True
    # Diagnol check
    if line(char, 0, 4, 8):
        return True
    if line(char, 2, 4, 6):
        return True

show_board()

# Initial while loop will ask for player A input and show the board as well
# check conditions to see whether or not player A wins. If player A wins,
# the program will terminate so it does not ask for player B input after.
while True:
    player_a = int(raw_input('Player A, please select a spot that is not taken \
(0-8): '))
    # Checks for empty spot and places an 'X' if it exists, otherwise
    # asks again.
    if board[player_a] != 'X' and board[player_a] != 'O':
        board[player_a] = 'X'
        show_board()
        # Check to see if Player A wins.
        if all('X') == True:
            print "Player A wins."
            sys.exit()
            break;

# While loop to ask for player B input and display the board as well as check
# the conditions as to whether or not player B wins. If player B wins, the
# program will terminate so it does not ask for player A input after.
        while True:
            player_b = int(raw_input('Player B, please select a spot that is \
not taken (0-8): '))
            # Checks for empty spot and places an 'O' if it exists, otherwise
            # asks again.
            if board[player_b] != 'O' and board[player_b] != 'X':
                board[player_b] = 'O'
                # Check to see if Player B wins.
                if all('O') == True:
                    show_board()
                    print "Player B wins."
                    sys.exit()
                    break;

                break;

    show_board()
tAU
  • 29
  • 4

2 Answers2

2

Without extensively going through the code, I can tell you that a draw is occurs after 9 turns, and only if both Player A and B do not receive a win on that final turn. For your simple program, what I would do is create a global variable called ELAPSED_TURNS or something of the sort, that increments each time a player enters a character, and then after checking both of the players' win conditions, and if there is no win, check ELAPSED_TURNS. If it is equal to 9, then the game must be a draw.

Andrew Lalis
  • 894
  • 3
  • 15
  • 26
  • I guess I am having difficulty with the placement. I'd initialize turns = 0 before the while loop. And then I'd increase the turn counter by 1 all the way at the end? However, trying this breaks the code and it just keeps asking for player B input. – tAU Aug 01 '15 at 00:54
  • Initialize turns = 0 at the very start of your program, and increment turns if neither A or B has won that round, and then do the check for turn number 9. – Andrew Lalis Aug 01 '15 at 00:57
  • Your while loops are a little confusing, but if you know how your program is structured, this should be quite the easy task. – Andrew Lalis Aug 01 '15 at 00:57
0

Here's the function that does what you want.

def is_tie():
    for position in board:
        if isinstance(position, int):
            return False
    print "The game is a tie."
    sys.exit()

Put a call to is_tie() directly after both while loops like this...

while True:
    is_tie()    
    player_a = int(raw_input(...

while True:
    is_tie()    
    player_b = int(raw_input(...

If this is a learning exercise for you I would recommend refactoring your code to find a way wrap all your logic blocks into functions and getting everything to flow without the use of sys.exit(). Doing so will increase the readability and make it easier to splice in new logic.

EDIT to your comment:

You can create an integer test function using just try / except statements like this...

def is_int(s):
    try: 
        int(s)
        return True
    except ValueError:
        return False

Credit here: Python: Check if a string represents an int, Without using Try/Except?

Your is_tie() function would then look like this:

def is_tie():
    for position in board:
        if is_int(position):
            return False
    print "The game is a tie."
    sys.exit()
Community
  • 1
  • 1
abaldwin99
  • 903
  • 1
  • 8
  • 26
  • Is there a "simpler" version of isinstance? I've not learned about that function yet so I don't want to include things I don't know. – tAU Aug 01 '15 at 01:41