Skip to content

Instantly share code, notes, and snippets.

@anjchang
Last active July 14, 2022 17:05
Show Gist options
  • Save anjchang/085b2c61824338bd2b3f5a9e5895e46d to your computer and use it in GitHub Desktop.
Save anjchang/085b2c61824338bd2b3f5a9e5895e46d to your computer and use it in GitHub Desktop.
import re
import random
board = ""
player=None #current player
playAgain = True
humanplayer=''
aiplayer=''
moves=[]
def initBoard(): #board is a string
global board
board = "."*9
def displayBoard(): #show places
global board
for i in range(len(board)):
print(board[i]+' ',end='')
if (i+1)%3==0: #help screen on the side
print(' | '+str(i-1)+" "+str(i)+" "+str(i+1))
print('\n')
def choosePlayer():
global humanplayer,aiplayer,player
#get player order and set X as first turn
while True:
humanplayer= input("Type x or o to choose your player\n").lower()
if humanplayer=='0' or humanplayer=='o':
humanplayer='o'
break
elif humanplayer=='x':
break
if humanplayer=='x':
aiplayer = 'o'
player=humanplayer
else:
aiplayer = 'x'
player = aiplayer
return(humanplayer)
def getMove():
#input move
while True:
move =input("Where do you want to go?\n")
if move.isnumeric():
move = int(move)
if move<=9 and move>0:
if(board[move-1]=='.'):
return(move-1)
print("Choose an open space.")
def checkWin(p,board,verbose):
winnerFound=False
test = p*3
if re.search(test,board) and re.search(test,board).start()%3==0:
if verbose:
print("Row of "+p+"'s found!")
winnerFound=True
if re.search('x..x..x',board) or re.search('o..o..o',board):
if verbose:
print("Column of "+p+"'s found!")
winnerFound=True
if re.search('x...x...x',board) or re.search('o...o...o',board):
if verbose:
print("Diagonal '\ of " +p+"'s found!")
winnerFound=True
if re.search('..x.x.x..',board) or re.search('..o.o.o..',board):
if verbose:
print("Diagonal / of " +p+"'s found!")
winnerFound=True
return(winnerFound)
def makeMove():
global board,player,humanplayer,aiplayer
myboard= list(board)
aiboard = board
freemoves=[]
for i in range(len(myboard)):
if myboard[i] == '.':
freemoves.append(i+1)
#print("freemoves",freemoves)
for move in freemoves:
#internal board representation uses 0-based index
lookahead=board[:(move-1)]+humanplayer+board[move:] #lookahead humanplayer
humanplayerwinsnext=checkWin(humanplayer,lookahead,False) #will human win
#print("lookahead",lookahead,end=""),print(humanplayerwinsnext,end="")
aiboard=board[:(move-1)]+aiplayer+board[move:] #lookahead aiplayer
aiplayerwinsnext=checkWin(aiplayer,aiboard,False) #will AI win
#print(" aiboard",aiboard,end="");print(aiplayerwinsnext)
if (humanplayerwinsnext or aiplayerwinsnext):
return(move-1) #choose winning or blocking move
break
move = random.choice(freemoves) #no obvious win found, random move
return(move-1)
def playGame():
global board,player,playAgain,gameWon,humanplayer,moves,aiplayer
initBoard()
humanplayer = choosePlayer()
displayBoard()
gameWon = False
while gameWon==False:
print("Player "+player+"'s turn")
if humanplayer==player:
loc = getMove()
else:
loc= makeMove()
#print("before move",board,end="")
board=board[:int(loc)]+player+board[int(loc)+1:]
#print(" after move",board)
displayBoard()
gameWon = checkWin(player,board,True)
if gameWon: #if someone won, see if they want to play again
print("Player "+player+" won! ",end="")
if player==humanplayer:
print("Congratulations!")
else:
print("Better luck next time!")
playAgain = askToContinue()
break
if '.' not in board: #all possible moves taken, restart?
print("It's a draw. ")
playAgain = askToContinue()
break
if player=='x': #swap active player and continue gameplay
player='o'
else:
player='x'
def askToContinue():
while True:
response= input("Type yes to play again, no to quit.\n")[:1].lower()
if response=='y':
return(True)
elif response=='n' or response=='q':
print("Goodbye.")
return(False)
print ('TIC TAC TOE')
while playAgain:
playGame()
@anjchang
Copy link
Author

anjchang commented Jul 9, 2022

first pass

@anjchang
Copy link
Author

anjchang commented Jul 9, 2022

fixed error in checking for row win

@anjchang
Copy link
Author

Added an AI player. So now we need to distinguish between the AI and human player. The current player in the game loop is always called "player."
The AI player looks ahead to see if any of the next moves by (the player or the AI) would result in a win. If so, it chooses the move that will block or win. Otherwise, it'll choose a random move.
To do so, I needed to store two copies of the board (projecting the next move by the player and AI). I also had to store all the open moves and iterate through them.
Then repurposed the checkWin function to check those copies for a win.
One tricky issue was the board representation, a 9-digit string, starts at 0 index, but the View is starts at 1. So we have to decrement any moves by 1 when we pass it to the model representation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment