jarrodhroberson
7/25/2019 - 5:10 PM

Python 3 TicTacToe Game for Console

Python 3 TicTacToe Game for Console

# Import needed modules
import os
import time
import re

# Regular Expression to validate that the input is in the expected format!
inputPattern = re.compile('^\d{1},\d{1}$')

#Initialize a 2D array to represent the board using a SPACE to represent unclaimed cells.
board = [[' ' for x in range(3)] for y in range(3)]

# keep up with the current player.
current_player = 0

# Draw a single row of the board.
def drawRow(row,board):
      print(u"{0} {1}|{2}|{3}".format(row,board[row][0], board[row][1], board[row][2]))  

# Draw the entire board.
def drawBoard(board):
    # Draw the Column Indexes
    print("  0 1 2")
    for r in range(3):
        drawRow(r,board)
        if r < 2:
            print("  \u2014 \u2014 \u2014")

# Validate the input to make sure the input is in range and not already taken.
# Pause 3 seconds on failures so the player can read the error message!
def validateCoordinates(row,col,board):
    if row not in range(0,3):
        print('Row must be between 0 and 2')
        time.sleep(3)
        return False
    elif col not in range(0,3):
        print('Column must be between 0 and 2')
        time.sleep(3)
        return False
    elif board[row][col] != ' ':
        print("{},{} is already taken by {}".format(row, col, board[row][col]))
        time.sleep(3)
        return False
    else:
        return True

# Register the players move on the board.
def registerMove(board,row,column,player):
    if validateCoordinates(row,column,board):
        board[row][column] = "O" if player == 0 else "X" 
        return True
    else:
        return False

#Clear the Screen ( works on Linux and Windows (nt) differently! )
def clearScreen():
    os.system('cls' if os.name == 'nt' else 'clear')

# Evaluate the state of the board and determine if the game is over.
def is_game_over(board,current_player):
    # An Entire Row is captured by the same player.
    for r in range(0,3):
        if board[r][0] != ' ' and (board[r][0] == board[r][1] and board[r][0] == board[r][2]):
            print("Player {} WINS!".format(current_player))
            return True
    # An entire column is captured by the same player.
    for c in range(0,3):
        if board[0][c] != ' ' and (board[0][c] == board[1][c] and board[0][c] == board[2][c]):
            print("Player {} WINS!".format(current_player))
            return True
    # Diagonal is captured by the same player.
    if board[0][0] != ' ' and (board[0][0] == board[1][1] and board[1][1] == board[2][2]):
            print("Player {} WINS!".format(current_player))
            return True
    elif board[0][2] != ' ' and (board[0][2] == board[1][1] and board[1][1] == board[2][0]):
            print("Player {} WINS!".format(current_player))
            return True
    else:
        # All the cells are captured but no one wins!
        for r in range(0,3):
            for c in range(0,3):
                if board[r][c] == ' ':
                    return False
        print("DRAW! Nobody Wins!")
        return True

# Start the script running!
clearScreen()
drawBoard(board)
# Game Loop runs until the game is over. Win or Draw will return True
while not is_game_over(board,current_player):
    move = input("Player {} Enter Row,Column: ".format(current_player + 1))
    # make sure the input is formatted as expected
    if inputPattern.match(move):
        # parse the input into something we can use
        parsed = move.split(",")
        row = int(parsed[0])
        col = int(parsed[1])
        if registerMove(board,row,col,current_player):
            current_player ^= 1
            clearScreen()
            drawBoard(board)
        else:
            clearScreen()
            drawBoard(board)
            continue
    else:
        print("Input must match the format #,#! '{}' does not match this format!".format(move))
        time.sleep(3)
        clearScreen()
        drawBoard(board)
        continue