最強の三目並べAI
X
O
X
O
X
O
X
O
X
O
X
O
X
O
X
O
X
O
def cell_click(position):
game.play_turn(position)
if game.game_running:
ai_turn()
def ai_turn():
game.stop()
score, pos = min_max(game, 1)
game.resume()
game.play_turn(pos)
def reset():
game.start()
def update_cells(values):
for i, value in enumerate(values, start=1):
Element(f"pos-{i}-x").add_class("hidden")
Element(f"pos-{i}-o").add_class("hidden")
Element(f"pos-{i}-none").add_class("hidden")
if value == 0:
Element(f"pos-{i}-x").remove_class("hidden")
elif value == 1:
Element(f"pos-{i}-o").remove_class("hidden")
else:
Element(f"pos-{i}-none").remove_class("hidden")
def display_message(value):
Element("message").write(value)
def min_max(game, player):
opp = 1 if player == 0 else 0
if game.is_winner(1): # COMP win
return 10, None
elif game.is_winner(0):
return -10, None
elif game.is_draw():
return 0, None
opp = (1 + player) % 2
if player == 1:
max_t = -9999
max_c = None
for c in game.candidates():
game.move(c, player)
t, cc = min_max(game, opp)
if max_t < t:
max_t = t
max_c = c
game.back(c)
return max_t, max_c
else:
min_t = 9999
min_c = None
for c in game.candidates():
game.move(c, player)
t, cc = min_max(game, opp)
if min_t > t:
min_t = t
min_c = c
game.back(c)
return min_t, min_c
class TicTacToe:
def start(self):
self.player = 0
self.cells = [None] * 9
self.game_running = True
display_message('あなたの番')
update_cells(self.cells)
Element("reset-button").add_class("hidden")
def stop(self):
self.game_running = False
def resume(self):
self.game_running = True
def play_turn(self, position):
if not self.game_running:
return
if self.cells[position] != None:
display_message("Invalid Position")
return
self.cells[position] = self.player
update_cells(self.cells)
if not self.is_game_over():
self.next_palyer()
else:
self.game_running = False
Element("reset-button").remove_class("hidden")
def next_palyer(self):
player_messages = ["あなたの番", "AIの番(考え中...)"]
self.player = (self.player + 1) % 2
display_message(player_messages[self.player])
def is_game_over(self):
if self.is_winner(self.player):
win_messages = ["あなたの勝ち🎉", "あなたの負け😞"]
display_message(win_messages[self.player])
self.game_running = False
return True
if self.is_draw():
display_message("引き分け")
self.game_running = False
return True
return False
def is_winner(self, player):
win_patterns = [(0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6)]
for a1, a2, a3 in win_patterns:
if self.cells[a1] == self.cells[a2] == self.cells[a3] == player:
return True
return False
def is_draw(self):
return all(val != None for val in self.cells)
def candidates(self):
return [i for i,x in enumerate(self.cells) if x == None]
def move(self, pos, player):
self.cells[pos] = player
def back(self, pos):
self.cells[pos] = None
game = TicTacToe()
game.start()
import sys
sys.setrecursionlimit(3000) # 1000(default)