Advertisement
al33kappa

Крестики нолики ИИ

Jun 7th, 2018
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.12 KB | None | 0 0
  1. # coding=UTF8
  2. from tkinter import Tk, Button
  3. from tkinter.font import Font
  4. from copy import deepcopy
  5.  
  6.  
  7. class Board:
  8.  
  9. def __init__(self, other=None):
  10. self.player = 'X'
  11. self.opponent = 'O'
  12. self.empty = '.'
  13. self.size = 3
  14. self.fields = {}
  15. for y in range(self.size):
  16. for x in range(self.size):
  17. self.fields[x, y] = self.empty
  18. # copy constructor
  19. if other:
  20. self.__dict__ = deepcopy(other.__dict__)
  21.  
  22. def move(self, x, y):
  23. board = Board(self)
  24. board.fields[x, y] = board.player
  25. (board.player, board.opponent) = (board.opponent, board.player)
  26. return board
  27.  
  28. def __minimax(self, player):
  29. if self.won():
  30. if player:
  31. return (-1, None)
  32. else:
  33. return (+1, None)
  34. elif self.tied():
  35. return (0, None)
  36. elif player:
  37. best = (-2, None)
  38. for x, y in self.fields:
  39. if self.fields[x, y] == self.empty:
  40. value = self.move(x, y).__minimax(not player)[0]
  41. if value > best[0]:
  42. best = (value, (x, y))
  43. return best
  44. else:
  45. best = (+2, None)
  46. for x, y in self.fields:
  47. if self.fields[x, y] == self.empty:
  48. value = self.move(x, y).__minimax(not player)[0]
  49. if value < best[0]:
  50. best = (value, (x, y))
  51. return best
  52.  
  53. def best(self):
  54. return self.__minimax(True)[1]
  55.  
  56. def tied(self):
  57. for (x, y) in self.fields:
  58. if self.fields[x, y] == self.empty:
  59. return False
  60. return True
  61.  
  62. def won(self):
  63. # horizontal
  64. for y in range(self.size):
  65. winning = []
  66. for x in range(self.size):
  67. if self.fields[x, y] == self.opponent:
  68. winning.append((x, y))
  69. if len(winning) == self.size:
  70. return winning
  71. # vertical
  72. for x in range(self.size):
  73. winning = []
  74. for y in range(self.size):
  75. if self.fields[x, y] == self.opponent:
  76. winning.append((x, y))
  77. if len(winning) == self.size:
  78. return winning
  79. # diagonal
  80. winning = []
  81. for y in range(self.size):
  82. x = y
  83. if self.fields[x, y] == self.opponent:
  84. winning.append((x, y))
  85. if len(winning) == self.size:
  86. return winning
  87. # other diagonal
  88. winning = []
  89. for y in range(self.size):
  90. x = self.size - 1 - y
  91. if self.fields[x, y] == self.opponent:
  92. winning.append((x, y))
  93. if len(winning) == self.size:
  94. return winning
  95. # default
  96. return None
  97.  
  98. def __str__(self):
  99. string = ''
  100. for y in range(self.size):
  101. for x in range(self.size):
  102. string += self.fields[x, y]
  103. string += "\n"
  104. return string
  105.  
  106.  
  107. class GUI:
  108.  
  109. def __init__(self):
  110. self.app = Tk()
  111. self.app.title('TicTacToe')
  112. self.app.resizable(width=False, height=False)
  113. self.board = Board()
  114. self.font = Font(family="Helvetica", size=32)
  115. self.buttons = {}
  116. for x, y in self.board.fields:
  117. handler = lambda x=x, y=y: self.move(x, y)
  118. button = Button(self.app, command=handler, font=self.font, width=2, height=1)
  119. button.grid(row=y, column=x)
  120. self.buttons[x, y] = button
  121. handler = lambda: self.reset()
  122. button = Button(self.app, text='reset', command=handler)
  123. button.grid(row=self.board.size + 1, column=0, columnspan=self.board.size, sticky="WE")
  124. self.update()
  125.  
  126. def reset(self):
  127. self.board = Board()
  128. self.update()
  129.  
  130. def move(self, x, y):
  131. self.app.config(cursor="watch")
  132. self.app.update()
  133. self.board = self.board.move(x, y)
  134. self.update()
  135. move = self.board.best()
  136. if move:
  137. self.board = self.board.move(*move)
  138. self.update()
  139. self.app.config(cursor="")
  140.  
  141. def update(self):
  142. for (x, y) in self.board.fields:
  143. text = self.board.fields[x, y]
  144. self.buttons[x, y]['text'] = text
  145. self.buttons[x, y]['disabledforeground'] = 'black'
  146. if text == self.board.empty:
  147. self.buttons[x, y]['state'] = 'normal'
  148. else:
  149. self.buttons[x, y]['state'] = 'disabled'
  150. winning = self.board.won()
  151. if winning:
  152. for x, y in winning:
  153. self.buttons[x, y]['disabledforeground'] = 'red'
  154. for x, y in self.buttons:
  155. self.buttons[x, y]['state'] = 'disabled'
  156. for (x, y) in self.board.fields:
  157. self.buttons[x, y].update()
  158.  
  159. def mainloop(self):
  160. self.app.mainloop()
  161.  
  162.  
  163. if __name__ == '__main__':
  164. GUI().mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement