読者です 読者をやめる 読者になる 読者になる

Python3.5.2でオセロを作る

プログラミング

勉強がてら、pythonでオセロを作りました。とりあえず基本的な部分は出来たと思います。

リスト内包表記とか、実際に使ってみるととても便利!楽しいです。

肝心のオセロは1000回くらい回してみましたが、どうも後攻の白が優勢になってしまいます。多分何かが間違っている……w

3000回回した結果

BLACK_WIN:1149 WHITE_WIN:1711 DRAW:139

ソースコードgithubで公開しています。ここにも乗せておきます...

main.py

from ai import Ai

black = 1
white = 2
map = [[0 for x in range(10)] for y in range(10)]
black_ai = Ai()
white_ai = Ai()
black_win = 0
white_win = 0
draw = 0


def init():
    # 初期化処理 #
    for x in range(10):
        for y in range(10):
            if x != 0 and y != 0 and y != len(map) - 1 and x != len(map) - 1:
                map[x][y] = 0
            else:
                map[x][y] = -1  # 番兵
    map[4][4] = white
    map[4][5] = black
    map[5][4] = black
    map[5][5] = white


def map_print():
    for x in map:
        for y in x:
            if y == -1:
                print('#', end='')
            elif y == 0:
                print('・', end='')
            elif y == 2:
                print("○", end='')
            else:
                print("●", end='')
        print("")

for z in range(1, 3000):
    print(str(z) + "回目...")
    init()
    while 1:
        break_count = 0
        black_ai.turn(map, black)
        white_ai.turn(map, white)
        if black_ai.game_end(map, black) and white_ai.game_end(map, white):
            map_print()
            break
    if black_ai.get_score(map, black) == white_ai.get_score(map, white):
        draw += 1
    elif black_ai.get_score(map, black) > white_ai.get_score(map, white):
        black_win += 1
    else:
        white_win += 1

print("BLACK_WIN:" + str(black_win))
print("WHITE_WIN:" + str(white_win))
print("DRAW:" + str(draw))

Ai.py

import random


class Ai(object):
    def get_score(self, map, color):
        # 指定した色の個数を返す
        count = 0
        for x in range(10):
            for y in range(10):
                if map[y][x] == color:
                    count += 1
        return count

    def grid(self, map, color):
        # 置ける場所の候補地を絞って、座標をリストで返す関数
        count = []
        for x in range(10):
            for y in range(10):
                if map[y][x] == 0:
                    count.append(self.up_scan_conform(map, color, y, x))
                    count.append(self.right_scan_conform(map, color, y, x))
                    count.append(self.down_scan_conform(map, color, y, x))
                    count.append(self.left_scan_comform(map, color, y, x))
                    count.append(self.upper_left_scan_conform(map, color, y, x))
                    count.append(self.upper_right_scan_conform(map, color, y, x))
                    count.append(self.lower_left_scan_conform(map, color, y, x))
                    count.append(self.lower_right_scan_conform(map, color, y, x))
        count = [x for x in count if x != 0]
        return count

    def up_scan_conform(self, map, color, y, x):
        # 上側に返せる石があったら、その場所の座標を返す
        stack = 0
        for count in range(1, 10):
            if map[y - count][x] == -1 or map[y - count][x] == 0:
                return 0
            elif map[y - count][x] != color:
                stack += 1
            if map[y - (count + 1)][x] == color and stack >= 1:
                return [y, x]

    def right_scan_conform(self, map, color, y, x):
        # 右側に返せる石があったら、その場所の座標を返す
        stack = 0
        for count in range(1, 10):
            if map[y][x + count] == -1 or map[y][x + count] == 0:
                return 0
            elif map[y][x + count] != color:
                stack += 1
            if map[y][x + (count + 1)] == color and stack >= 1:
                return [y, x]

    def down_scan_conform(self, map, color, y, x):
        # 下側に返せる石があったら、その場所の座標を返す
        stack = 0
        for count in range(1, 10):
            if map[y + count][x] == -1 or map[y + count][x] == 0:
                return 0
            elif map[y + count][x] != color:
                stack += 1
            if map[y + (count + 1)][x] == color and stack >= 1:
                return [y, x]

    def left_scan_comform(self, map, color, y, x):
        # 左側に返せる石があったら、その場所の座標を返す
        stack = 0
        for count in range(1, 10):
            if map[y][x - count] == -1 or map[y][x - count] == 0:
                return 0
            elif map[y][x - count] != color:
                stack += 1
            if map[y][x - (count + 1)] == color and stack >= 1:
                return [y, x]

    def upper_left_scan_conform(self, map, color, y, x):
        # 左上側に返せる石があったら、その場所の座標を返す
        stack = 0
        for count in range(1, 10):
            if map[y - count][x - count] == -1 or map[y - count][x - count] == 0:
                return 0
            elif map[y - count][x - count] != color:
                stack += 1
            if map[y - (count + 1)][x - (count + 1)] == color and stack >= 1:
                return [y, x]

    def lower_left_scan_conform(self, map, color, y, x):
        # 左下側に返せる石があったら、その場所の座標を返す
        stack = 0
        for count in range(1, 10):
            if map[y + count][x - count] == -1 or map[y + count][x - count] == 0:
                return 0
            elif map[y + count][x - count] != color:
                stack += 1
            if map[y + (count + 1)][x - (count + 1)] == color and stack >= 1:
                return [y, x]

    def upper_right_scan_conform(self, map, color, y, x):
        # 右上側に返せる石があったら、その場所の座標を返す
        stack = 0
        for count in range(1, 10):
            if map[y - count][x + count] == -1 or map[y - count][x + count] == 0:
                return 0
            elif map[y - count][x + count] != color:
                stack += 1
            if map[y - (count + 1)][x + (count + 1)] == color and stack >= 1:
                return [y, x]

    def lower_right_scan_conform(self, map, color, y, x):
        # 右下側に返せる石があったら、その場所の座標を返す
        stack = 0
        for count in range(1, 10):
            if map[y + count][x + count] == -1 or map[y + count][x + count] == 0:
                return 0
            elif map[y + count][x + count] != color:
                stack += 1
            if map[y + (count + 1)][x + (count + 1)] == color and stack >= 1:
                return [y, x]

    def remove_duplicate_data(self, grid):
        # gridから重複データを削除する
        molding_grid = []
        for x in grid:
            if x not in molding_grid:
                molding_grid.append(x)
        return molding_grid

    def turn(self, map, color):
        # ターンを管理する関数
        grid = self.grid(map, color)
        molding_grid = self.remove_duplicate_data(grid)
        if len(molding_grid) < 1:
            return 0
        else:
            rand_grid = random.choice(molding_grid)
            y = int(rand_grid[0])
            x = int(rand_grid[1])
            map[y][x] = color
            self.up_scan(map, color, y, x)
            self.right_scan(map, color, y, x)
            self.down_scan(map, color, y, x)
            self.left_scan(map, color, y, x)
            self.upper_left_scan(map, color, y, x)
            self.lower_left_scan(map, color, y, x)
            self.upper_right_scan(map, color, y, x)
            self.lower_right_scan(map, color, y, x)

    def game_end(self, map, color):
        if self.grid(map, color):
            return 0
        else:
            return 1

    def grid_empty_check(self, map, color):
        # 座標に空きが有るかどうかをチェックする
        count = 0
        for x in range(10):
            for y in range(10):
                if map[y][x] == 0:
                    count += 1
        return count

    def up_scan(self, map, color, y, x):
        # 上側に返せる石があったら返す
        stack = 0
        for count in range(1, 10):
            if map[y - count][x] == -1 or map[y - count][x] == 0:
                break
            elif map[y - count][x] != color:
                stack += 1
            if map[y - (count + 1)][x] == color and stack >= 1:
                for z in range(1, stack + 1):
                    map[y - z][x] = color

    def right_scan(self, map, color, y, x):
        # 右側に返せる石があったら返す
        stack = 0
        for count in range(1, 10):
            if map[y][x + count] == -1 or map[y][x + count] == 0:
                break
            elif map[y][x + count] != color:
                stack += 1
            if map[y][x + (count + 1)] == color and stack >= 1:
                for z in range(1, stack + 1):
                    map[y][x + z] = color

    def down_scan(self, map, color, y, x):
        # 下側に返せる石があったら返す
        stack = 0
        for count in range(1, 10):
            if map[y + count][x] == -1 or map[y + count][x] == 0:
                break
            elif map[y + count][x] != color:
                stack += 1
            if map[y + (count + 1)][x] == color and stack >= 1:
                for z in range(1, stack + 1):
                    map[y + z][x] = color

    def left_scan(self, map, color, y, x):
        # 左側に返せる石があったら返す
        stack = 0
        for count in range(1, 10):
            if map[y][x - count] == -1 or map[y][x - count] == 0:
                break
            elif map[y][x - count] != color:
                stack += 1
            if map[y][x - (count + 1)] == color and stack >= 1:
                for z in range(1, stack + 1):
                    map[y][x - z] = color

    def upper_left_scan(self, map, color, y, x):
        # 左上側に返せる石があったら返す
        stack = 0
        for count in range(1, 10):
            if map[y - count][x - count] == -1 or map[y - count][x - count] == 0:
                break
            elif map[y - count][x - count] != color:
                stack += 1
            if map[y - (count + 1)][x - (count + 1)] == color and stack >= 1:
                for z in range(1, stack + 1):
                    map[y - z][x - z] = color

    def lower_left_scan(self, map, color, y, x):
        # 左下側に返せる石があったら返す
        stack = 0
        for count in range(1, 10):
            if map[y + count][x - count] == -1 or map[y + count][x - count] == 0:
                break
            elif map[y + count][x - count] != color:
                stack += 1
            if map[y + (count + 1)][x - (count + 1)] == color and stack >= 1:
                for z in range(1, stack + 1):
                    map[y + z][x - z] = color

    def upper_right_scan(self, map, color, y, x):
        # 右上側に返せる石があったら返す
        stack = 0
        for count in range(1, 10):
            if map[y - count][x + count] == -1 or map[y - count][x + count] == 0:
                break
            elif map[y - count][x + count] != color:
                stack += 1
            if map[y - (count + 1)][x + (count + 1)] == color and stack >= 1:
                for z in range(1, stack + 1):
                    map[y - z][x + z] = color

    def lower_right_scan(self, map, color, y, x):
        # 右下側に返せる石があったら返す
        stack = 0
        for count in range(1, 10):
            if map[y + count][x + count] == -1 or map[y + count][x + count] == 0:
                break
            elif map[y + count][x + count] != color:
                stack += 1
            if map[y + (count + 1)][x + (count + 1)] == color and stack >= 1:
                for z in range(1, stack + 1):
                    map[y + z][x + z] = color