-
-
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() | |
fixed error in checking for row win
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.
first pass