Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #tictactoe game by Usmar A Padow and Inoishi Mitsuro, this title updated on Sep. 15 2009
- #Thanx to Dude-X and Twey
- #any comments to [email protected]
- #some work still needs to be done in the parts marked as:
- #*needs to be implemented
- #we need a way to do forks and block forks for the AI and a way to judge for a stalemate
- #also we need different difficulty levels
- import re
- import sys #for sys.exit()
- class AR():#object that containst the array and methods to handle it
- def __init__(self):#constructor
- self.gameover=False
- self.r=["0","1","2","3","4","5","6","7","8"]
- def print_board(self):
- #Twey> amigojapan: def print_board(self): print map("-----".join(map("|".join, map(self.row, range(1, 4)))))
- print self.r[0]+"|"+self.r[1]+"|"+self.r[2]
- print "-----"
- print self.r[3]+"|"+self.r[4]+"|"+self.r[5]
- print "-----"
- print self.r[6]+"|"+self.r[7]+"|"+self.r[8]
- def place_is_empty(self,place):
- #def place_is_empty(self, place): return self.r[place] in "012345678"
- if self.r[place] in "012345678":
- return True
- else:
- return False
- #return self.r[place] in "012345678"
- def get_input(self,letter):
- print "Board for player input"
- self.print_board()
- print "Enter a number for " + letter + " [p]ass [q]uit:"
- notvalid=True
- while notvalid:
- number=raw_input()
- if number.lower() in "012345678pq" and len(number)==1: #true if number is 0-5 and it must be one number
- notvalid=False
- else:
- print "Invalid input"
- #if self.r[int(number)] == "O" or self.r[int(number)] == "X":
- if number.lower() == "p":
- return
- if number.lower() == "q":
- invalidinput = True
- while invalidinput == True:
- print "press [Q] TO quit the game, [M] to quit this match or [R] to resume game"
- inp = raw_input()
- if inp.lower() in "qmr" and len(inp)==1:
- invalidinput = False
- if inp.lower() == "q":
- sys.exit()
- if inp.lower() == "m":
- self.gameover=True
- return
- if inp.lower() == "r":
- self.get_input(letter)
- return
- if not self.place_is_empty(int(number)):
- print "Invalid Move"
- self.get_input(letter)
- else:
- self.r[int(number)] = letter
- def make_free(self,string):
- #>>> p = re.compile( '(blue|white|red)')
- #>>> p.sub( 'colour', 'blue socks and red shoes')
- #'colour socks and colour shoes'
- #>>> p.sub( 'colour', 'blue socks and red shoes', count=1)
- #'colour socks and red shoes'
- #p = re.compile( '[0-8]')
- #p.sub( '-', 'abc1239xmn')
- p = re.compile( '[0-8]')
- return p.sub( '-', string)
- #<Twey> amigojapan: def row(self, n): return self.make_free(sum(self.r[(n - 1) * 3 : (n - 1) * 3 - 1])); def col(self, n): return self.make_free(sum(self.r[n - 1 :: 3]))
- def row1(self):
- return self.make_free(self.r[0]+self.r[1]+self.r[2])
- def row2(self):
- return self.make_free(self.r[3]+self.r[4]+self.r[5])
- def row3(self):
- return self.make_free(self.r[6]+self.r[7]+self.r[8])
- def col1(self):
- return self.make_free(self.r[0]+self.r[3]+self.r[6])
- def col2(self):
- return self.make_free(self.r[1]+self.r[4]+self.r[7])
- def col3(self):
- return self.make_free(self.r[2]+self.r[5]+self.r[8])
- def diag1(self):
- return self.make_free(self.r[0]+self.r[4]+self.r[8])
- def diag2(self):
- return self.make_free(self.r[2]+self.r[4]+self.r[6])
- def ai_move(self):
- #1. Win: If you have two in a row, play the third to get three in a row.
- if self.row1()=="XX-":
- self.r[2]="X"
- return
- if self.row1()=="X-X":
- self.r[1]="X"
- return
- if self.row1()=="-XX":
- self.r[0]="X"
- return
- if self.row2()=="XX-":
- self.r[5]="X"
- return
- if self.row2()=="X-X":
- self.r[4]="X"
- return
- if self.row2()=="-XX":
- self.r[3]="X"
- return
- if self.row3()=="XX-":
- self.r[8]="X"
- return
- if self.row3()=="X-X":
- self.r[7]="X"
- return
- if self.row3()=="-XX":
- self.r[6]="X"
- return
- if self.col1()=="XX-":
- self.r[6]="X"
- return
- if self.col1()=="X-X":
- self.r[3]="X"
- return
- if self.col1()=="-XX":
- self.r[0]="X"
- return
- if self.col2()=="XX-":
- self.r[7]="X"
- return
- if self.col2()=="X-X":
- self.r[4]="X"
- return
- if self.col2()=="-XX":
- self.r[1]="X"
- return
- if self.col3()=="XX-":
- self.r[8]="X"
- return
- if self.col3()=="X-X":
- self.r[5]="X"
- return
- if self.col3()=="-XX":
- self.r[2]="X"
- return
- if self.diag1()=="XX-":
- self.r[8]="X"
- return
- if self.diag1()=="X-X":
- self.r[4]="X"
- return
- if self.diag1()=="-XX":
- self.r[0]="X"
- return
- if self.diag2()=="XX-":
- self.r[6]="X"
- return
- if self.diag2()=="X-X":
- self.r[4]="X"
- return
- if self.diag2()=="-XX":
- self.r[2]="X"
- return
- #2. Block: If the opponent has two in a row, play the third to block them.
- if self.row1()=="OO-":
- self.r[2]="X"
- return
- if self.row1()=="O-O":
- self.r[1]="X"
- return
- if self.row1()=="-OO":
- self.r[0]="X"
- return
- if self.row2()=="OO-":
- self.r[5]="X"
- return
- if self.row2()=="O-O":
- self.r[4]="X"
- return
- if self.row2()=="-OO":
- self.r[3]="X"
- return
- if self.row3()=="OO-":
- self.r[8]="X"
- return
- if self.row3()=="O-O":
- self.r[7]="X"
- return
- if self.row3()=="-OO":
- self.r[6]="X"
- return
- if self.col1()=="OO-":
- self.r[6]="X"
- return
- if self.col1()=="O-O":#I think there is a bug in this option, it didnt play this move when it shouldhave
- self.r[3]="X"
- return
- if self.col1()=="-OO":
- self.r[0]="X"
- return
- if self.col2()=="OO-":
- self.r[7]="X"
- return
- if self.col2()=="O-O":
- self.r[4]="X"
- return
- if self.col2()=="-OO":
- self.r[1]="X"
- return
- if self.col3()=="OO-":
- self.r[8]="X"
- return
- if self.col3()=="O-O":
- self.r[5]="X"
- return
- if self.col3()=="-OO":
- self.r[2]="X"
- return
- if self.diag1()=="OO-":
- self.r[8]="X"
- return
- if self.diag1()=="O-O":
- self.r[4]="X"
- return
- if self.diag1()=="-OO":
- self.r[0]="X"
- return
- if self.diag2()=="OO-":
- self.r[6]="X"
- return
- if self.diag2()=="O-O":
- self.r[4]="X"
- return
- if self.diag2()=="-OO":
- self.r[2]="X"
- return
- #3. Fork: Create an opportunity where you can win in two ways.
- #*needs to be implemented
- #4. Block Opponent's Fork:
- # Option 1: Create two in a row to force the opponent into defending, as long as it doesn't result in them creating a fork or winning. For example, if "X" has a corner, "O" has the center, and "X" has the opposite corner as well, "O" must not play a corner in order to win. (Playing a corner in this scenario creates a fork for "X" to win.)
- # Option 2: If there is a configuration where the opponent can fork, block that fork.
- #*needs to be implemented
- #5. Center: Play the center.
- if self.place_is_empty(4):
- self.r[4]="X"
- return
- #6. Opposite Corner: If the opponent is in the corner, play the opposite corner.
- if self.row1()=="O--":
- self.r[2]="X"
- return
- if self.row1()=="--O":
- self.r[0]="X"
- return
- if self.row2()=="O--":
- self.r[5]="X"
- return
- if self.row2()=="--O":
- self.r[3]="X"
- return
- if self.row3()=="O--":
- self.r[8]="X"
- return
- if self.row3()=="--O":
- self.r[6]="X"
- return
- if self.col1()=="O--":
- self.r[6]="X"
- return
- if self.col1()=="--O":
- self.r[0]="X"
- return
- if self.col2()=="O--":
- self.r[7]="X"
- return
- if self.col2()=="--O":
- self.r[1]="X"
- return
- if self.col3()=="O--":
- self.r[8]="X"
- return
- if self.col3()=="--O":
- self.r[2]="X"
- return
- if self.diag1()=="O--":
- self.r[8]="X"
- return
- if self.diag1()=="--O":
- self.r[0]="X"
- return
- if self.diag2()=="O--":
- self.r[6]="X"
- return
- if self.diag2()=="--O":
- self.r[2]="X"
- return
- #7. Empty Corner: Play an empty corner.
- if self.place_is_empty(0):
- self.r[0]="X"
- return
- if self.place_is_empty(2):
- self.r[2]="X"
- return
- if self.place_is_empty(6):
- self.r[6]="X"
- return
- if self.place_is_empty(8):
- self.r[8]="X"
- return
- #8. Empty Side: Play an empty side.
- if self.place_is_empty(1):
- self.r[1]="X"
- return
- if self.place_is_empty(3):
- self.r[3]="X"
- return
- if self.place_is_empty(5):
- self.r[5]="X"
- return
- if self.place_is_empty(7):
- self.r[7]="X"
- return
- #9 error, shouldn't reach this part with a perfect AI, I think.
- print "Error AI didn't make any move"
- def prompt_gameover(self):
- print "Game Over"
- invalidinput = True
- while invalidinput == True:
- print "Play again? [Y] or [N]:"
- inp = raw_input()
- if inp.lower() in "yn" and len(inp)==1:
- invalidinput = False
- if inp.lower() == "y":
- self.gameover=True
- return
- if inp.lower() == "n":
- sys.exit()
- def judge(self):
- #check to see if board is full
- counter=0
- for a in range (0, 9):
- if self.place_is_empty(a):
- counter=counter+1
- #print "counter " +str(counter)
- if counter == 0:
- self.prompt_gameover()
- if self.gameover==True:
- return
- #check for 3 in a row
- if self.row1()=="OOO":
- print "Player O wins"
- self.prompt_gameover()
- if self.row1()=="XXX":
- print "Player X wins"
- self.prompt_gameover()
- if self.row2()=="OOO":
- print "Player O wins"
- self.prompt_gameover()
- if self.row2()=="XXX":
- print "Player X wins"
- self.prompt_gameover()
- if self.row3()=="OOO":
- print "Player O wins"
- self.prompt_gameover()
- if self.row3()=="XXX":
- print "Player X wins"
- self.prompt_gameover()
- if self.col1()=="OOO":
- print "Player O wins"
- self.prompt_gameover()
- if self.col1()=="XXX":
- print "Player X wins"
- self.prompt_gameover()
- if self.col2()=="OOO":
- print "Player O wins"
- self.prompt_gameover()
- if self.col2()=="XXX":
- print "Player X wins"
- self.prompt_gameover()
- if self.col3()=="OOO":
- print "Player O wins"
- self.prompt_gameover()
- if self.col3()=="XXX":
- print "Player X wins"
- self.prompt_gameover()
- if self.diag1()=="OOO":
- print "Player O wins"
- self.prompt_gameover()
- if self.diag1()=="XXX":
- print "Player X wins"
- self.prompt_gameover()
- if self.diag2()=="OOO":
- print "Player O wins"
- self.prompt_gameover()
- if self.diag2()=="XXX":
- print "Player X wins"
- self.prompt_gameover()
- #Judge stale mate
- #*needs to be implemented
- if __name__ == "__main__":
- ar=AR()#create instance that contains the arrayfrom array object,initialize game array in constructor
- endgame=False
- while endgame==False:
- ar.__init__()
- ar.gameover=False
- invalidinput = True
- while invalidinput == True:
- print "Play 2 players or against computer [2] or [c]:"
- inp = raw_input()
- if inp.lower() in "2c" and len(inp)==1:
- invalidinput = False
- if inp.lower() == "2":
- gametype = "2player"
- if inp.lower() == "c":
- gametype = "computer"
- while ar.gameover==False:
- ar.get_input("O")#prompt and get user input, validate and enter data
- if ar.gameover==True:
- continue
- print "Judging game"#judge to see if it is game over, who wins and tie(stale mate)
- ar.judge()
- if ar.gameover==True:
- continue
- print "Board after player move"
- ar.print_board()#Show output for the users move
- #ar.get_input("X")#temporary function for testing AI or use for 2 player game
- #ar.ai_move()
- if gametype == "2player":
- ar.get_input("X")
- if ar.gameover==True:
- continue
- print "Board after player X's move"
- if gametype == "computer":
- print "computer calculating move..."#calculate computer's move
- ar.ai_move()
- print "Board after computer move"
- ar.print_board()#show computers move
- print "Judging game"#judge to see if it is game over, who wins and tie(stale mate)
- ar.judge()
Advertisement
Add Comment
Please, Sign In to add comment