-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgui.py
210 lines (177 loc) · 6.48 KB
/
gui.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
import tkinter as tk
from tkinter import font
from tkinter import messagebox
from game import Game
from RL.model import RL_Model
from MCTS.model import MCTS_Model
from ANN.model import ANN_Model
from Minimax.model import Minimax_Model
class App(tk.Tk):
def __init__(self):
info = self.chose_type_of_game()
super().__init__()
self.title("Tic-Tac-Toe Game. By Javier Abollado.")
self.f1 = TicTacToeBoard(self, info)
self.f1.pack()
def chose_type_of_game(self):
print("\nChose your oponent:")
print(" 1) Minimax")
print(" 2) Artificial Neural Network")
print(" 3) Reinforcement Learning")
print(" 4) MCTS")
option = input(" > ")
mcts = False
if option == "1":
model = Minimax_Model()
elif option == "2":
model = ANN_Model("ANN/models/model.pkl")#"ANN/models/model_lr01_x20k_epochs100.pkl")
elif option == "3":
model = RL_Model()
else:
model = MCTS_Model()
mcts = True
print("\nStart player?")
print(" 1) AI Player")
print(" 2) Human")
option = input(" > ")
if option == "1":
start_player = "AI"
AI_chip = "x"
else:
start_player = "Human"
AI_chip = "o"
return model, start_player, AI_chip, mcts
class TicTacToeBoard(tk.Frame):
def __init__(self, master, info):
super().__init__(master=master)
self.model, self.start_player, self.AI_chip, self.is_mcts = info
# init variables and create frames
self._cells = {}
self._create_board_display()
self._create_board_grid()
# create a parallel board & load the AI model
self.game = Game()
if self.start_player == "AI":
self.playAI()
"""
Play our AI model (trained with Q learning)
- 'playAI' makes a move (by the AI)
- 'g' converts the turn : {"x","o"} -> {-1,1} in order to let the model read it
"""
def playAI(self):
a = self.model.move(self.game, only_action=True)
self.move(a//3, a%3)
"""
Move functions
- 'command' is a function that returns another function 'move' to the button (row, col)
- 'move' checks & print the move, also check if we have won or not
"""
def command(self, row, col):
frc = lambda : self.move(row, col)
return frc
def move(self, row, col):
button = self._cells[(row,col)]
if button["text"] == "": # and not self.win:
button.config(text=self.game.player)
action = 3*row+col
# update the mcts in case
if not self.game.player == self.AI_chip and self.is_mcts and self.game.empty_spaces > 1:
self.model.move_direct(action)
self.game.insert(action)
# check winner
finished = self.game.finished(type=True)
if finished != -1:
if finished == 0:
self.draw_row(row)
elif finished == 1:
self.draw_col(col)
elif finished == 2:
self.draw_diag1()
else:
self.draw_diag2()
self.winner()
elif self.game.full():
self.winner(draw=True)
else:
# change turn after move
self.display.config(text=f"Turn : {self.game.player}")
if self.game.player == self.AI_chip and self.game.empty_spaces > 0:
self.playAI()
"""
1) Create a header (self.display)
2) Create a 3x3 board
"""
def _create_board_display(self):
display_frame = tk.Frame(master=self)
display_frame.pack(fill=tk.X)
self.display = tk.Label(
master=display_frame,
text="Ready?",
font=font.Font(size=28, weight="bold"),
)
self.display.pack()
def _create_board_grid(self):
grid_frame = tk.Frame(master=self)
grid_frame.pack()
for row in range(3):
# self.rowconfigure(row, weight=1, minsize=50)
# self.columnconfigure(row, weight=1, minsize=50)
for col in range(3):
button = tk.Button(
master=grid_frame,
command=self.command(row,col),
text="",
font=font.Font(size=36, weight="bold"),
fg="black",
width=4,
height=2,
relief="ridge",
borderwidth=4,
highlightbackground="lightblue",
)
self._cells[(row, col)] = button
button.grid(
row=row,
column=col,
padx=5,
pady=5,
sticky="nsew"
)
def reset_game(self):
self.display.config(text="Ready?")
for i in range(3):
for j in range(3):
self._cells[(i,j)].config(text="", fg="black")
self.game.reset()
if self.is_mcts:
self.model.reset()
if self.start_player == "AI":
self.playAI()
"""
1) Check if someone wins : ROWS / COLUMNS / DIAGONALS
2) Draw with green the line which has won the game
"""
def winner(self, draw=False):
self.game.change_player()
if not draw:
message = f"Player '{self.game.player}' wins!\nReady for another round?"
else:
message = f"Draw!\nReady for another round?"
x = messagebox.askyesno(message=message, title="End Game!")
self.game.change_player()
if x:
self.reset_game()
else:
exit(0)
def draw_row(self, row):
for j in range(3):
self._cells[(row,j)].config(fg="green")
def draw_col(self, col):
for i in range(3):
self._cells[(i,col)].config(fg="green")
def draw_diag1(self):
for k in range(3):
self._cells[(k,k)].config(fg="green")
def draw_diag2(self):
for k in range(3):
self._cells[(k,2-k)].config(fg="green")