俺の備忘録

個人的な備忘録です。

Pythonの勉強がてらオセロAIを作ってみる②

はじめに

前回(Pythonの勉強がてらオセロAIを作ってみる① - 俺の備忘録)からの続き

  1. オセロの基本ロジックの実装
  2. 完全ランダムな手で打つAIの実装
  3. 今現在、最もたくさん石が取れる手を選ぶAIの実装  <= 本稿はココ
  4. ちょっとだけオセロの定石を知ってるAIの実装
  5. もうちょっとオセロの定石を知っているAIの実装
  6. MinMax法で打つAIの実装
  7. AlphaBeta法で打つAIの実装
  8. モンテカルロ法で打つAIの実装
  9. モンテカルロ木探索?で打つAIの実装
  10. (このあたりで機械学習を取り入れたい?)

現在最も石が取れる手を選ぶAIの実装

前回は完全にランダムな手を選択するAIを作った。

今回は最も石が取れる手の中からランダムで選ぶAIを作ってみた。 (とっても簡単)

前回(Pythonの勉強がてらオセロAIを作ってみる① - 俺の備忘録)のPlayer.pyを拡張

class NextStoneMaxAi(Player):
    """今回の1手で最も石が取れる場所に置くAI"""

    def next_move(self, board):
        # 石を置ける全候補地
        all_candidatess = ReverseCommon.get_puttable_points(board, self._color)

        # 今回の一手で最も石が取れる場所一覧
        filtered_candidates = []
        max_score = -1
        for candidates in all_candidatess:
            next_board = ReverseCommon.put_stone(board, self._color, candidates[0], candidates[1])
            score = ReverseCommon.get_score(next_board, self._color)
            if score >= max_score:
                filtered_candidates.append(candidates)
                max_score = score

        return filtered_candidates[random.randint(0, len(filtered_candidates) - 1)]

戦わせてみる

それぞれのパターンで3000回ずつ戦わせてみた。

パターン①:
黒(完全ランダムAI):1108勝
白(最も石を取れる手からランダムAI):1892勝

パターン②:
黒(最も石を取れる手からランダムAI):1955勝
白(最完全ランダムAI):1045勝

パターン③:
黒(最も石を取れる手からランダムAI):1470勝
白(最も石を取れる手からランダムAI):1530勝

おおっ。完全ランダムより確実に強いっす。

以下が戦わせたときのコード。 前回 (Pythonの勉強がてらオセロAIを作ってみる① - 俺の備忘録)のMain.pyを拡張 30行目から34行目でAIを切り替える

おまけ

作ったAIがどのくらい強いか確認するために、人間が戦えるようにするクラスを作った。

で現状のAIと戦ってみたけど、結果は弱すぎて話にならない(笑)

class Human(Player):
    """人間です。"""

    def next_move(self, board):
        all_candidates = ReverseCommon.get_puttable_points(board, self._color)
        while True:
            try:
                # x,yの形式で入力する
                next_move_str = raw_input("next_move > ")
                next_move_str_split = next_move_str.split(",")
                if len(next_move_str_split) == 2:
                    next_move = [int(next_move_str_split[0]), int(next_move_str_split[1])]
                    if next_move in all_candidates:
                        return next_move
                    else:
                        print "can't put there."
            except ValueError:
                print "format error."