Tic Tac Toe game in Python

Most of what I'm writing is pretty quick and dirty as I'm crashing through a lot of stuff to learn. My variable/function/class names are most likely not efficient and I still need to get a lot of the PEP8 formatting down.

That said, I put a quick Tic Tac Toe game together in Python. I'm going to add some decision logic for the computer to run blocks and common Tic Tac Toe strategy, but for now it's just a dumb chooser.

Can I consolidate a lot of the code here? I think a lot of it is repetitive and it seems to me it could be much more efficient.

#!/usr/bin/env python3

'''

Basic Tic Tac Toe game - Chris Gleason 2015

'''

from random import randint

whowon = 'no'
coords = [ [ '[1]' , '[2]' , '[3]'] , [ '[4]' ,'[5]' , '[6]' ] , [ '[7]' , '[8]' , '[9]' ] ]

def printmatrix():

'''
Function to print out the Tic Tac Toe Matrix
'''

print (' This is the matrix of the co-ordinates ')
print ('''
''')

print ('' , coords[0][0] , '\t' , coords[0][1] , '\t' , coords[0][2])
print ('' , coords[1][0] , '\t' , coords[1][1] , '\t' , coords[1][2])
print ('' , coords[2][0] , '\t' , coords[2][1] , '\t' , coords[2][2])
print ('')

def wincondition():

'''
This Fucntion defines wether a player has won and if so who has won before allowing
execution of the playturn function.
'''

if coords[0][0] == "[X]" and coords [0][1] == "[X]" and coords[0][2] == "[X]":
iswon = 'yes'
whowon = 'player'

elif coords[1][0] == "[X]" and coords [1][1] == "[X]" and coords[1][2] == "[X]":
iswon = 'yes'
whowon = 'player'

elif coords[2][0] == "[X]" and coords [2][1] == "[X]" and coords[2][2] == "[X]":
iswon = 'yes'
whowon = 'player'

elif coords[0][0] == "[X]" and coords [1][0] == "[X]" and coords[2][0] == "[X]":
iswon = 'yes'
whowon = 'player'

elif coords[0][1] == "[X]" and coords [1][1] == "[X]" and coords[2][1] == "[X]":
iswon = 'yes'
whowon = 'player'

elif coords[0][2] == "[X]" and coords [1][2] == "[X]" and coords[2][2] == "[X]":
iswon = 'yes'
whowon = 'player'

elif coords[0][0] == "[X]" and coords [1][1] == "[X]" and coords[2][2] == "[X]":
iswon = 'yes'
whowon = 'player'

elif coords[0][2] == "[X]" and coords [1][1] == "[X]" and coords[2][0] == "[X]":
iswon = 'yes'
whowon = 'player'

elif coords[0][0] == "[O]" and coords [0][1] == "[O]" and coords[0][2] == "[O]":
iswon = 'yes'
whowon = 'computer'

elif coords[1][0] == "[O]" and coords [1][1] == "[O]" and coords[1][2] == "[O]":
iswon = 'yes'
whowon = 'computer'

elif coords[2][0] == "[O]" and coords [2][1] == "[O]" and coords[2][2] == "[O]":
iswon = 'yes'
whowon = 'computer'

elif coords[0][0] == "[O]" and coords [1][0] == "[O]" and coords[2][0] == "[O]":
iswon = 'yes'
whowon = 'computer'

elif coords[0][1] == "[O]" and coords [1][1] == "[O]" and coords[2][1] == "[O]":
iswon = 'yes'
whowon = 'computer'

elif coords[0][2] == "[O]" and coords [1][2] == "[O]" and coords[2][2] == "[O]":
iswon = 'yes'
whowon = 'computer'

elif coords[0][0] == "[O]" and coords [1][1] == "[O]" and coords[2][2] == "[O]":
iswon = 'yes'
whowon = 'computer'

elif coords[0][2] == "[O]" and coords [1][1] == "[O]" and coords[2][0] == "[O]":
iswon = 'yes'
whowon = 'computer'

else:
iswon = 'no'

if iswon == 'yes':
print ('The game is over! ' ,  whowon , ' won!')
exit(0)

def playturn():

'''
This Function adds logic to the players turn to decide wether or not
the space is taken or or not and marks the grid accordingly
'''

wincondition()
goodroll = 'no'
while goodroll != 'yes':
playerchoice = input ('Which co-ordinate would you like to mark?')

if playerchoice == "1" and coords[0][0] == "[1]":
coords[0][0] = "[X]"
goodroll = 'yes'

elif playerchoice == "2" and coords[0][1] == "[2]":
coords[0][1] = "[X]"
goodroll = 'yes'

elif playerchoice == "3" and coords[0][2] == "[3]":
coords[0][2] = "[X]"
goodroll = 'yes'

elif playerchoice == "4" and coords[1][0] == "[4]":
coords[1][0] = "[X]"
goodroll = 'yes'

elif playerchoice == "5" and coords[1][1] == "[5]":
coords[1][1] = "[X]"
goodroll = 'yes'

elif playerchoice == "6" and coords[1][2] == "[6]":
coords[1][2] = "[X]"
goodroll = 'yes'

elif playerchoice == "7" and coords[2][0] == "[7]":
coords[2][0] = "[X]"
goodroll = 'yes'

elif playerchoice == "8" and coords[2][1] == "[8]":
coords[2][1] = "[X]"
goodroll = 'yes'

elif playerchoice == "9" and coords[2][2] == "[9]":
coords[2][2] = "[X]"
goodroll = 'yes'

else:
print('None of those coordiantes are available!')

def compturn():

'''
This function adds decision logic to the computers turn, picks a random number
and keeps looping until it picks a valid unchosen spot on the grid.
'''

wincondition()
goodroll = 'no'
while goodroll != 'yes':
compchoice  = randint(1,9)

if compchoice == 1 and coords[0][0] == "[1]":
coords[0][0] = "[O]"
goodroll = 'yes'

elif compchoice == 2 and coords[0][1] == "[2]":
coords[0][1] = "[O]"
goodroll = 'yes'

elif compchoice == 3 and coords[0][2] == "[3]":
coords[0][2] = "[O]"
goodroll = 'yes'

elif compchoice == 4 and coords[1][0] == "[4]":
coords[1][0] = "[O]"
goodroll = 'yes'

elif compchoice == 5 and coords[1][1] == "[5]":
coords[1][0] = "[O]"
goodroll = 'yes'

elif compchoice == 6 and coords[1][2] == "[6]":
coords[1][0] = "[O]"
goodroll = 'yes'

elif compchoice == 7 and coords[2][0] == "[7]":
coords[2][0] = "[O]"
goodroll = 'yes'

elif compchoice == 8 and coords[2][1] == "[8]":
coords[2][1] = "[O]"
goodroll = 'yes'

elif compchoice == 9 and coords[2][2] == "[9]":
coords[2][2] = "[O]"
goodroll = 'yes'

else:
goodroll = 'no'

print('Computer choice is: ' , compchoice)

print ('Welcome to tic tac toe!')
print ('You are X and the computer is O')

while whowon != 'yes':
print ('''
''')
printmatrix()
playturn()
compturn()

• Functions should take arguments, everything global is a no-no. Commented Jul 4, 2015 at 19:02
• @Caridorc can you elaborate? I'm not sure what you mean here? Do you mean defining arguments in def function(x) instead of def function()? Commented Jul 4, 2015 at 20:24
• Look the first example in @SirPython 's answer. Commented Jul 4, 2015 at 20:53

1. You are repeating yourself in playturn and in compturn.

A large chunk of these two functions is exactly the same thing: checking to see if a square is empty or not.

I recommend creating a function call is_available which will take one argument that is an element of coords, and will return True if the space is empty and False if not.

Here is what I came up with:

def is_available(coord):
"""
@param(string) -- a coord from the coords array
@return(boolean) -- True if the square is empty
-- False if the square is occupied
"""
return coord != "[X]" && coord != "[O]"


I did something a little different in this function than what you did that allowed me to reduce this function to one line. You were checking if the square was equal to it's default value ("[1]", "[3]", etc) and I checked that the square was not X and was not O.

Now, let's go back to compturn. Let's re-write it using is_available:

def compturn():

'''
This function adds decision logic to the computers turn, picks a random number
and keeps looping until it picks a valid unchosen spot on the grid.
'''

wincondition()
goodroll = false
while not goodroll:
choice1 = randint(0,2)
choice2 = randint(0,2)
if is_available(coords[choice1, choice2]):
coords[choice1, choice2] = "[0]"
goodroll = True

print('Computer choice is: ' , compchoice)


I also made a few more improvements to this function:

1. I changed goodroll to use True and False, rather than "yes" and "no" because boolean comparisons are much, much faster than string comparisons.

2. I moved the final print statement out of the while loop so, in the case of an invalid move, the move won't be printed.

3. I go rid of the else part because, if the conditional before it was not True, then goodroll would not have been set and will remain False.

You should use this same principle here for your wincondition function so you aren't being so repetitive there either.

Your game does not handle ties. It will just asking for a place to go (or randomly generating a place to go in the case of the computer's turn) and the program will never exit.

You should add a function that checks for a tie.

printmatrix is not a descriptive name. You should call it print_board.

Here:

if iswon == 'yes':
print ('The game is over! ' ,  whowon , ' won!')
exit(0)


You use the function exit, but you never imported it anywhere.

At the top of your code, you should put:

from sys import exit

• Thanks! I'll look this over tomorrow after I'm no longer at the pub! I appreciate the feedback and looks like just what I was looking for. Commented Jul 4, 2015 at 20:26
• Also, the exit works. Is it working some other way than being called the way I am calling it? Commented Jul 4, 2015 at 20:29
• @ChrisGleason My assumption is that, since sys is a pretty common and important library (might be standard, but I don't know), your interpreter automatically included it for you. Commented Jul 4, 2015 at 20:42
• Got it. So this likely included in my distro, but should be defined just in cast someones python install doesn't include the sys module? Commented Jul 5, 2015 at 0:03
• Thanks, I finally read through this. I see the improvements are pretty optimized. Thanks. The one thing I see is I think you intended on showing some code for def compturn() to show how you were going to utilize the new is_available(coords) function, but didn't include it. I think I could probably deduce it from what you suggested, but figured I'd see if you wanted to add it. Thanks! Commented Jul 5, 2015 at 13:28

I just wanted to post the updated, working script with the suggestions added. I also added a line to check if it was a tie.

#!/usr/bin/env python3

'''

Basic Tic Tac Toe game - Chris Gleason 2015

'''

from sys import exit
from random import randint

whowon = 'no'
coords = [ [ '[1]' , '[2]' , '[3]'] , [ '[4]' ,'[5]' , '[6]' ] , [ '[7]' , '[8]' , '[9]' ] ]

def is_available(coords):

"""

@param(string) -- a coord from the coords array
@return(boolean) -- True if the square is empty
-- False if the square is occupied
"""

return coords != "[X]" and coords != "[O]"

def print_board():

'''
Function to print out the Tic Tac Toe Matrix
'''

print (' This is the board represented as a grid of the co-ordinates ')
print ('''
''')

print ('' , coords[0][0] , '\t' , coords[0][1] , '\t' , coords[0][2])
print ('' , coords[1][0] , '\t' , coords[1][1] , '\t' , coords[1][2])
print ('' , coords[2][0] , '\t' , coords[2][1] , '\t' , coords[2][2])
print ('')

def wincondition():

'''
This Fucntion defines wether a player has won and if so who has won before allowing
execution of the playturn function. It also decides if there is a tie.
'''

if coords[0][0] == "[X]" and coords [0][1] == "[X]" and coords[0][2] == "[X]":
iswon = True
whowon = 'player'

elif coords[1][0] == "[X]" and coords [1][1] == "[X]" and coords[1][2] == "[X]":
iswon = True
whowon = 'player'

elif coords[2][0] == "[X]" and coords [2][1] == "[X]" and coords[2][2] == "[X]":
iswon = True
whowon = 'player'

elif coords[0][0] == "[X]" and coords [1][0] == "[X]" and coords[2][0] == "[X]":
iswon = True
whowon = 'player'

elif coords[0][1] == "[X]" and coords [1][1] == "[X]" and coords[2][1] == "[X]":
iswon = True
whowon = 'player'

elif coords[0][2] == "[X]" and coords [1][2] == "[X]" and coords[2][2] == "[X]":
iswon = True
whowon = 'player'

elif coords[0][0] == "[X]" and coords [1][1] == "[X]" and coords[2][2] == "[X]":
iswon = True
whowon = 'player'

elif coords[0][2] == "[X]" and coords [1][1] == "[X]" and coords[2][0] == "[X]":
iswon = True
whowon = 'player'

elif coords[0][0] == "[O]" and coords [0][1] == "[O]" and coords[0][2] == "[O]":
iswon = True
whowon = 'computer'

elif coords[1][0] == "[O]" and coords [1][1] == "[O]" and coords[1][2] == "[O]":
iswon = True
whowon = 'computer'

elif coords[2][0] == "[O]" and coords [2][1] == "[O]" and coords[2][2] == "[O]":
iswon = True
whowon = 'computer'

elif coords[0][0] == "[O]" and coords [1][0] == "[O]" and coords[2][0] == "[O]":
iswon = True
whowon = 'computer'

elif coords[0][1] == "[O]" and coords [1][1] == "[O]" and coords[2][1] == "[O]":
iswon = True
whowon = 'computer'

elif coords[0][2] == "[O]" and coords [1][2] == "[O]" and coords[2][2] == "[O]":
iswon = True
whowon = 'computer'

elif coords[0][0] == "[O]" and coords [1][1] == "[O]" and coords[2][2] == "[O]":
iswon = True
whowon = 'computer'

elif coords[0][2] == "[O]" and coords [1][1] == "[O]" and coords[2][0] == "[O]":
iswon = 'yes'
whowon = 'computer'

else:
iswon = False

if iswon == True:
print ('The game is over! ' ,  whowon , ' won!')
exit(0)

if coords[0][0] != "[1]" and coords[0][1] != "[2]" and coords [0][2] != "[3]" \
and coords[1][0] != "[4]" and coords[1][1] != "[5]" and coords [1][2] != "[6]" \
and coords[2][0] != "[7]" and coords[2][1] != "[8]" and coords [2][2] != "[9]":
print('The game is a tie!')
exit(0)

def playturn():

'''
This Function adds logic to the players turn to decide wether or not
the space is taken or or not and marks the grid accordingly
'''

wincondition()
goodroll = 'no'
while goodroll != 'yes':
playerchoice = input ('Which co-ordinate would you like to mark?')

if playerchoice == "1" and coords[0][0] == "[1]":
coords[0][0] = "[X]"
goodroll = 'yes'

elif playerchoice == "2" and coords[0][1] == "[2]":
coords[0][1] = "[X]"
goodroll = 'yes'

elif playerchoice == "3" and coords[0][2] == "[3]":
coords[0][2] = "[X]"
goodroll = 'yes'

elif playerchoice == "4" and coords[1][0] == "[4]":
coords[1][0] = "[X]"
goodroll = 'yes'

elif playerchoice == "5" and coords[1][1] == "[5]":
coords[1][1] = "[X]"
goodroll = 'yes'

elif playerchoice == "6" and coords[1][2] == "[6]":
coords[1][2] = "[X]"
goodroll = 'yes'

elif playerchoice == "7" and coords[2][0] == "[7]":
coords[2][0] = "[X]"
goodroll = 'yes'

elif playerchoice == "8" and coords[2][1] == "[8]":
coords[2][1] = "[X]"
goodroll = 'yes'

elif playerchoice == "9" and coords[2][2] == "[9]":
coords[2][2] = "[X]"
goodroll = 'yes'

else:
print('None of those coordiantes are available!')

def compturn():

'''
This function adds decision logic to the computers turn, picks a random number
and keeps looping until it picks a valid unchosen spot on the grid.
'''

wincondition()
goodroll = False
while not goodroll:
choice1 = randint(0,2)
choice2 = randint(0,2)
if is_available(coords[choice1][choice2]):
coords[choice1][choice2] = "[O]"
goodroll = True

print('Computer chose co-ordinates: ', choice1 , ',' , choice2 )

print ('Welcome to tic tac toe!')
print ('You are X and the computer is O')

while whowon != True:
print ('''
''')
print_board()
playturn()
compturn()