メインコンテンツまでスキップ

探索アルゴリズム

探索アルゴリズム

探索アルゴリズムは、与えられた問題またはデータセットから目標、解、または特定の条件を見つけるための計算手法である。 ゲームなどの分野で使用されている。

オセロ

探索アルゴリズムを実装してどのように勝率が変化するのかを確認するためにオセロを題材にして見ていこうと思う。

そのため、各言語のオセロを行うコードを以下に示す。今後は Player クラスにで新しい戦略を追加し、他のアルゴリズムと対決させていくことを考える。 取れる手の中からランダムで手を選択する戦略を基準戦略として実装している。

注記

もっといい実装方法やおかしな点があれば、教えていただければ幸いです。

それぞれの言語のディレクトリ構造

actionsディレクトリに探索アルゴリズムを追加していく。また、アルゴリズムによっては評価関数が存在する。評価関数は同様のもを使用できるようにevaluationファイルにまとめる。 evaluationコードは必要になった際に記述する。

.
├── __init__.py
├── lib
│ ├── actions
│ │ ├── __init__.py
│ │ ├── action.py
│ │ └── random_action.py
│ ├── evaluation.py
│ ├── othello.py
│ └── player.py
└── main.py

othell ファイル

othello.py
import time

from lib.othello import Othello, GameState
from lib.player import Player


def play_game(player1_strategy, player2_strategy):
# 対戦マップ作成
othello = Othello()

# playerを作成
player1 = Player(1, othello, player1_strategy)
player2 = Player(0, othello, player2_strategy)

# print(othello)
while (not othello.is_done()):
# player1のアクション
player1.put()
# player2のアクション
player2.put()
return othello.get_winner()


n = 100
white = 0
black = 0
draw = 0
start = time.time()
for i in range(n):
win: GameState = play_game("random", "random")
print(f"{i}回目: {win.value}")
if win == GameState.WHITE_WIN:
white += 1
elif win == GameState.BLACK_WIN:
black += 1
else:
draw += 1

print(f"白の勝率: {white/n}")
print(f"黒の勝率: {black/n}")
print(f"引き分け: {draw/n}")
print(f"実行時間: {time.time() - start}")

player ファイル

player.py
from lib.othello import Othello
from lib.actions import *


class Player():

def __init__(self, _id: int, board: Othello, strategy: str) -> None:
self.id = _id
self.othello = board
# 次の手を選択する手法を返る
match strategy:
case "random":
self.strategy = RandomAction(_id)
case _:
self.strategy = RandomAction(_id)

def put(self):
action = self.strategy.action(self.othello.copy_board())
# 置くところがなかった場合
if action is None:
return
self.othello.put(self.id, action)

action ファイル

注記

actionsディレクトリの__init__.pyには各 action を import するように記述しています。

action.py
import sys
from pathlib import Path
from abc import ABC, abstractmethod

sys.path.append(str(Path(__file__).parent.parent.parent))
from lib.othello import Othello


class Action(ABC):

def __init__(self, _id: int) -> None:
self.id = _id

@abstractmethod
def action(self, othello: Othello) -> tuple[int, int]:
raise NotImplementedError("")

main ファイル

main.py
from lib.othello import Othello, GameState
from lib.player import Player


def play_game(player1_strategy, player2_strategy):
# 対戦マップ作成
othello = Othello()

# playerを作成
player1 = Player(1, othello, player1_strategy, 2, "custom")
player2 = Player(0, othello, player2_strategy, 2, "custom")

# print(othello)
while (not othello.is_done()):
# player1のアクション
player1.put()
# player2のアクション
player2.put()
return othello.get_winner()


n = 100
white = 0
black = 0
draw = 0
for i in range(n):
win: GameState = play_game("alpha_beta", "minimax")
print(f"{i}回目: {win.value}")
if win == GameState.WHITE_WIN:
white += 1
elif win == GameState.BLACK_WIN:
black += 1
else:
draw += 1

print(f"白の勝率: {white/n}")
print(f"黒の勝率: {black/n}")
print(f"引き分け: {draw/n}")