jmooremcc

Python OOP TicTacToe

Jul 9th, 2019
397
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.27 KB | None | 0 0
  1. # Tic Tac Toe
  2. # Author: John Moore
  3. from enum import IntEnum
  4.  
  5. # global constants
  6. X = 'X'
  7. O = 'O'
  8. EMPTY = ' '
  9. TIE = 'T'
  10. NO_ONE = 'N'
  11. NUM_SQUARES = 9
  12. DIMENSION = 3
  13. YES = 'y'
  14. NO = 'n'
  15.  
  16.  
  17. class Status(IntEnum):
  18. WINNER = 1
  19. NOWINNER = 2
  20. TIE_GAME = 3
  21.  
  22.  
  23.  
  24.  
  25. class GameBoard():
  26. def __init__(self):
  27. self.reset()
  28.  
  29. def reset(self):
  30. self.board = [[EMPTY for x in range(DIMENSION)] for y in range(DIMENSION)]
  31.  
  32. def countEmptyCells(self):
  33. count = 0
  34. for row in range(DIMENSION):
  35. for col in range(DIMENSION):
  36. if self.board[row][col] == EMPTY:
  37. count += 1
  38.  
  39. return count
  40.  
  41. def Display(self):
  42. for row in range(DIMENSION):
  43. print("{:^3}|{:^3}|{:^3}".format(self.board[row][0], self.board[row][1], self.board[row][2]))
  44. if row < DIMENSION - 1:
  45. print("-" * 10)
  46.  
  47. def getMark(self, location):
  48. mark = self.board[location // DIMENSION][location % DIMENSION]
  49. return mark
  50.  
  51. def putMark(self, location, mark):
  52. self.board[location // DIMENSION][location % DIMENSION] = mark
  53.  
  54. def isLegal(self, location):
  55. return self.board[location // DIMENSION][location % DIMENSION] == EMPTY
  56.  
  57. def winner(self):
  58. TOTAL_ROWS = 8
  59. WINNING_ROWS = [
  60. [0, 1, 2],
  61. [3, 4, 5],
  62. [6, 7, 8],
  63. [0, 3, 6],
  64. [1, 4, 7],
  65. [2, 5, 8],
  66. [0, 4, 8],
  67. [2, 4, 6]
  68. ]
  69.  
  70. for row in range(TOTAL_ROWS):
  71. status = self.getMark(WINNING_ROWS[row][0]) != EMPTY \
  72. and self.getMark(WINNING_ROWS[row][0]) == self.getMark(WINNING_ROWS[row][1]) \
  73. and self.getMark(WINNING_ROWS[row][1]) == self.getMark(WINNING_ROWS[row][2])
  74.  
  75. if status:
  76. return self.getMark(WINNING_ROWS[row][0])
  77.  
  78. # See if we have a tie
  79. if self.countEmptyCells() == 0:
  80. return TIE
  81.  
  82. # No Winner
  83. return NO_ONE
  84.  
  85. def getStatus(self):
  86. status = self.winner()
  87. if status == NO_ONE:
  88. print("NO WINNER")
  89. return Status.NOWINNER
  90. elif status == TIE:
  91. print("TIE GAME")
  92. return Status.TIE_GAME
  93. else:
  94. print("WINNER")
  95. return Status.WINNER
  96.  
  97.  
  98. class Player():
  99. def __init__(self, gameboard, mark=None):
  100. self.board = gameboard # type: GameBoard
  101. self.marker = mark
  102.  
  103. @property
  104. def Marker(self):
  105. return self.marker
  106.  
  107. @Marker.setter
  108. def Marker(self, value):
  109. self.marker = value
  110.  
  111. def askNumber(self, question, high, low):
  112. number = None
  113. while True:
  114. number = int(input(question + "({} - {}):".format(low, high)))
  115. if number >= low and number <= high:
  116. return number
  117.  
  118. def takeYourTurn(self):
  119. while True:
  120. move = self.askNumber("\nPlease Enter Your Move", 9, 1) - 1
  121. moveIsLegit = self.board.isLegal(move)
  122. if moveIsLegit:
  123. self.board.putMark(move, self.marker)
  124. break
  125. else:
  126. print("\nThat Move Has Already Been Taken\nPlease Try Again!\n")
  127.  
  128.  
  129. class ComputerPlayer(Player):
  130. def __init__(self, gameboard, mark=None):
  131. super().__init__(gameboard, mark)
  132.  
  133. def opponent(self):
  134. if self.marker == X:
  135. return O
  136. else:
  137. return X
  138.  
  139. def Strategy1(self):
  140. for move in range(NUM_SQUARES):
  141. if self.board.isLegal(move):
  142. self.board.putMark(move, self.marker)
  143. if self.board.winner() == self.marker:
  144. print(move + 1)
  145. return True
  146. else:
  147. self.board.putMark(move, EMPTY)
  148.  
  149. return False
  150.  
  151. def Strategy2(self):
  152. opponent = self.opponent()
  153. for move in range(NUM_SQUARES):
  154. if self.board.isLegal(move):
  155. self.board.putMark(move, opponent)
  156. if self.board.winner() == opponent:
  157. print(move + 1)
  158. self.board.putMark(move, self.marker)
  159. return True
  160. else:
  161. self.board.putMark(move, EMPTY)
  162.  
  163. return False
  164.  
  165. def Strategy3(self):
  166. Best_Moves = [4, 0, 7, 6, 8, 1, 3, 5, 2]
  167. for i in range(NUM_SQUARES):
  168. move = Best_Moves[i]
  169. if self.board.isLegal(move):
  170. self.board.putMark(move, self.marker)
  171. print(move + 1)
  172. return
  173.  
  174. def takeYourTurn(self):
  175. print("\nI'm going to take move ", end='')
  176. if self.Strategy1():
  177. return
  178. elif self.Strategy2():
  179. return
  180. else:
  181. self.Strategy3()
  182.  
  183.  
  184. class TicTacToe():
  185. def __init__(self):
  186. self.board = GameBoard()
  187. self.computer = ComputerPlayer(self.board)
  188. self.human = Player(self.board)
  189. self.turn = None
  190.  
  191. def askYesNo(self, question):
  192. response = None
  193. while True:
  194. response = input(question + "(y/n):").lower()
  195. if response[0] == YES or response[0] == NO:
  196. return response
  197.  
  198. def switchTurn(self):
  199. self.turn = O if self.turn == X else X
  200.  
  201. def displayInstructions(self):
  202. print("Welcome to the ultimate man-machine showdown: Tic-Tac-Toe.\n")
  203. print("--where human brain is pit against silicon processor\n\n")
  204.  
  205. print("Make your move known by entering a number, 1 - 9. The number\n")
  206. print("corresponds to the desired board position, as illustrated:\n\n")
  207.  
  208. print(" 1 | 2 | 3")
  209. print(" ---------")
  210. print(" 4 | 5 | 6")
  211. print(" ---------")
  212. print(" 7 | 8 | 9\n")
  213.  
  214. print("Prepare yourself, human. The battle is about to begin.\n\n")
  215.  
  216. def declareATie(self):
  217. print("It's a tie.")
  218. print("You were most lucky, human, and somehow managed to tie me.")
  219. print("Celebrate... for this is the best you will ever achieve.")
  220.  
  221. def congratulateWinner(self):
  222. theWinner = self.board.winner()
  223.  
  224. if theWinner == self.human.Marker:
  225. print(theWinner + "'s won!")
  226. print("No, no! It cannot be! Somehow you tricked me, human.")
  227. print("But never again! I, the computer, so swear it!")
  228. else: # theWinner == computer.getMarker()
  229. print(theWinner + "'s won!")
  230. print("As I predicted, human, I am triumphant once more -- proof")
  231. print("that computers are superior to humans in all regards.")
  232.  
  233. def determineFirstPlayer(self):
  234. if self.turn is not None:
  235. return
  236.  
  237. self.turn = X
  238.  
  239. if self.askYesNo("Do You Want To Go First") == YES:
  240. self.human = Player(self.board, X)
  241. self.computer = ComputerPlayer(self.board, O)
  242. else: # answer is no
  243. self.human = Player(self.board, O)
  244. self.computer = ComputerPlayer(self.board, X)
  245.  
  246. def PlayOneRound(self):
  247. self.board.reset()
  248. self.displayInstructions()
  249. self.determineFirstPlayer()
  250. status = None
  251.  
  252. if self.turn == self.human.Marker:
  253. self.board.Display()
  254.  
  255. # Game Loop
  256. while True:
  257. if self.turn == self.human.Marker:
  258. self.human.takeYourTurn()
  259. else: # turn == computer.getMarker()
  260. self.computer.takeYourTurn()
  261.  
  262. self.board.Display()
  263. self.switchTurn()
  264.  
  265. status = self.board.getStatus()
  266. if status == Status.WINNER or status == Status.TIE_GAME:
  267. break
  268.  
  269. if status == Status.WINNER:
  270. self.congratulateWinner()
  271. else: # Tie Game
  272. self.declareATie()
  273.  
  274.  
  275.  
  276. def Play(self):
  277. while True:
  278. self.PlayOneRound()
  279. if self.askYesNo("Do you want to play again") != YES:
  280. break
  281.  
  282. print("\nThanks For Playing Tic Tac Toe!\n")
  283.  
  284.  
  285. if __name__ == "__main__":
  286. game = TicTacToe()
  287. game.Play()
Advertisement
Add Comment
Please, Sign In to add comment