オセロをつくった

pythonでオセロのプログラムを書いた。
functions_othello.pyに使う関数をまとめた。

from functions_othello import *
turn = 'black' #黒
B = board() #盤面生成
BP, able = check(B,turn)
show_double(B,BP,turn)
while able != 0:
    B, turn = place(B,BP,turn)
    BP, able = check(B,turn)
    show_double(B,BP,turn)        
    if able == 0:
        if turn == 'black':
            BP, able = check(B,'white')
            if able == 0:
                break
            else:
                turn = 'white'
                print('黒を置ける場所はありません')
                show_double(B,BP,turn)
        else:#white
            BP, able = check(B,'black')
            if able == 0:
                break
            else:
                turn = 'black'
                print('白を置ける場所はありません')
                show_double(B,BP,turn)
cnt_black_stone = 0
cnt_white_stone = 0
for i in range(8):
    for j in range(8):
        if B[i][j] == 'black':
            cnt_black_stone += 1
        elif B[i][j] == 'white':
            cnt_white_stone += 1
show(B)
if cnt_black_stone > cnt_white_stone:
    print('黒○ の勝ち')
elif cnt_black_stone < cnt_white_stone:
    print('白● の勝ち')
else:
    print('引き分け')

Bは現在の盤面を表し、'black'、'white'、'null'が入った8×8のリストです。
BPは石を置くことのできる位置を表し、'able'、'null'が入った8×8のリストです。
turnは黒と白のどちらの番であるかを表し、'black'または'white'です。

board()はオセロの初めの盤面を構成する関数です。

def board():
    B = [['null' for i in range(8) ] for i in range(8)]
    B[3][3] = 'white'
    B[3][4] = 'black'
    B[4][3] = 'black'
    B[4][4] = 'white'
    return B

show(B)は現在の盤面をオセロ風に表示する関数です。

def show(B):
    BQ = ['null']*10
    for i in range(1,9):
        s = chr(97 + i - 1) + '|'
        for j in range(8):
            if B[i-1][j] == 'white':
                s += '● '
            elif B[i-1][j] == 'black':
                s += '○ '
            else:
                s += '  '
            s += '|'
        s += chr(97 + i - 1)        
        BQ[i] = s
    K = ' |'
    for i in range(1,9):
        K += ' ' + str(i)
        K += '|'
    BQ[0] = K
    BQ[9] = K
    for i in range(10):
        print(BQ[i])

check(B,turn)は現在の盤面と番を入力することで、置ける位置と置ける枚数を返す関数です。

def check(B,turn):#BPとして置ける部分をマークしたものを出力したい
    #turn = 'black'の場合で解説を書く
    able = 0
    BP = [['null' for i in range(8) ] for i in range(8)]
    #縦横斜めで順番にcheckしていく
    for i in range(8):#横
        a = -1
        k = 0
        t = 2
        for j in range(8):
            stone = B[i][j]
            if stone == 'null':
                if t == 1:
                    if a >= 1:
                        BP[i][j] = 'able'
                        able += 1
                        k = j
                        a = 0
                        t = 0
                    else:
                        t = 0
                        k = j
                else:
                    a = 0
                    k = j
                    t = 0
            elif stone != turn:#white
                if t == 1 or t == -1:
                    a += 1
                elif t == 0:
                    a = 1
                    t = -1
            else:#black
                if t == -1 and a >= 1:
                    BP[i][k] = 'able'
                    able += 1
                    k = j
                    a = 0
                    t = 1
                else:
                    a = 0
                    t = 1

    for j in range(8):#縦
        a = -1
        k = 0
        t = 2
        for i in range(8):
            stone = B[i][j]
            if stone == 'null':
                if t == 1:
                    if a >= 1:
                        BP[i][j] = 'able'
                        able += 1
                        k = i
                        a = 0
                        t = 0
                    else:
                        t = 0
                        k = i
                else:
                    a = 0
                    k = i
                    t = 0
            elif stone != turn:#white
                if t == 1 or t == -1:
                    a += 1
                elif t == 0:
                    a = 1
                    t = -1
            else:#black
                if t == -1 and a >= 1:
                    BP[k][j] = 'able'
                    able += 1
                    k = i
                    a = 0
                    t = 1
                else:
                    a = 0
                    t = 1

    for i in range(8):#斜め右上
        a = -1
        k = 0
        t = 2
        for j in range(8-i):
            stone = B[i+j][j]
            if stone == 'null':
                if t == 1:
                    if a >= 1:
                        BP[i+j][j] = 'able'
                        able += 1
                        k = j
                        a = 0
                        t = 0
                    else:
                        t = 0
                        k = j
                else:
                    k = j
                    a = 0
                    t = 0
            elif stone != turn:#white
                if t == 1 or t == -1:
                    a += 1
                elif t == 0:
                    a = 1
                    t = -1
            else:#black
                if t == -1 and a >= 1:
                    BP[i+k][k] = 'able'
                    able += 1
                    k = j
                    a = 0
                    t = 1
                else:
                    a = 0
                    t = 1

    for j in range(1,8):#斜め左下
        a = -1
        k = 0
        t = 2
        for i in range(8-j):
            stone = B[i][i+j]
            if stone == 'null':
                if t == 1:
                    if a >= 1:
                        BP[i][i+j] = 'able'
                        able += 1
                        k = i
                        a = 0
                        t = 0
                    else:
                        t = 0
                        k = i
                else:
                    a = 0
                    k = i
                    t = 0
            elif stone != turn:#white
                if t == 1 or t == -1:
                    a += 1
                elif t == 0:
                    a = 1
                    t = -1
            else:#black
                if t == -1 and a >= 1:
                    BP[k][k+j] = 'able'
                    able += 1
                    k = i
                    a = 0
                    t = 1
                else:
                    a = 0
                    t = 1
                    
    for i in range(8):#斜め左上
        a = -1
        k = 0
        t = 2
        for j in range(8-i):
            stone = B[7-i-j][j]
            if stone == 'null':
                if t == 1:
                     if a >= 1:
                         BP[7-i-j][j] = 'able'
                         able += 1
                         k = j
                         a = 0
                         t = 0
                     else:
                         t = 0
                         k = j
                else:
                    k = j
                    a = 0
                    t = 0
            elif stone != turn:#white
                if t == 1 or t == -1:
                    a += 1
                elif t == 0:
                    a = 1
                    t = -1
            else:#black
                if t == -1 and a >= 1:
                    BP[7-i-k][k] = 'able'
                    able += 1
                    k = j
                    a = 0
                    t = 1
                else:
                    a = 0
                    t = 1

    for j in range(1,8):#斜め右下
        a = -1
        k = 0
        t = 2
        for i in range(8-j):
            stone = B[7-i][i+j]
            if stone == 'null':
                if t == 1:
                    if a >= 1:
                        BP[7-i][i+j] = 'able'
                        able += 1
                        k = i
                        a = 0
                        t = 0
                    else:
                        t = 0
                        k = i
                else:
                    a = 0
                    k = i
                    t = 0
            elif stone != turn:#white
                if t == 1 or t == -1:
                    a += 1
                elif t == 0:
                    a = 1
                    t = -1
            else:#black
                if t == -1 and a >= 1:
                    BP[7-k][k+j] = 'able'
                    able += 1
                    k = i
                    a = 0
                    t = 1
                else:
                    a = 0
                    t = 1

    return BP, able

show_able(BP)は置ける場所を三角で表示する関数です。必要はない。

def show_able(BP):
    BPQ = ['null']*10
    for i in range(1,9):
        s = chr(97 + i - 1) + '|'
        for j in range(8):
            if BP[i-1][j] == 'able':
                s += '△ '
            else:
                s += '  '
            s += '|'
        s += chr(97 + i - 1)        
        BPQ[i] = s
    K = ' |'
    for i in range(1,9):
        K += ' ' + str(i)
        K += '|'
    BPQ[0] = K
    BPQ[9] = K
    for i in range(10):
        print(BPQ[i])

place(B,BP,turn)は石をどこに置くかの入力を求めて、それが置けるかどうか判断して、実際に現状の盤面Bを更新する関数です。
更新はupdate(B,turn,x,y)に任せた。

def place(B,BP,turn):#turnの人が入力してそれを盤面に反映する
    while True:
        if turn == 'black':
            S = list(input('黒○ の番です。置きたい位置を入力してください。(例:5d)'))
        else:
            S = list(input('白● の番です。置きたい位置を入力してください。(例:5d)'))
        x, y = ord(S[1])-97, int(S[0]) -1
        if BP[x][y] == 'able':
            if turn == 'black':
                B = update(B,turn,x,y)
                turn = 'white'
            else:#white
                B = update(B,turn,x,y)
                turn = 'black'
            return B, turn
        else:
            print('そこは置けません')
            show_double(B,BP,turn)
            pass

update(B,turn,x,y)はx,y成分に石が置かれた場合の盤面の更新をする関数です。

def update(B,turn,x,y):
    S = []
    for i in range(x-1,-1,-1):#北
        if B[i][y] == 'null':
            break
        elif B[i][y] == turn:#black
            for j in S:
                B[j][y] = turn
            break
        else:#white
            S.append(i)

    S = []
    for i in range(x+1,8):#南
        if B[i][y] == 'null':
            break
        elif B[i][y] == turn:#black
            for l in S:
                B[l][y] = turn
            break
        else:#white
            S.append(i)

    S = []
    for j in range(y-1,-1,-1):#西
        if B[x][j] == 'null':
            break
        elif B[x][j] == turn:#black
            for l in S:
                B[x][l] = turn
            break
        else:#white
            S.append(j)
            
    S = []    
    for j in range(y+1,8):#東
        if B[x][j] == 'null':
            break
        elif B[x][j] == turn:#black
            for l in S:
                B[x][l] = turn
            break
        else:#white
            S.append(j)
        
    if x <= y:#右上
        S = []
        for i in range(x-1,-1,-1):
            if B[i][y-x+i] == 'null':
                break
            elif B[i][y-x+i] == turn:
                for l in S:
                    B[l][y-x+l] = turn
                break
            else:
                S.append(i)

        S = []
        for j in range(y+1,8):
            if B[x+j-y][j] == 'null':
                break
            elif B[x+j-y][j] == turn:
                for l in S:
                    B[x+l-y][l] = turn
                break
            else:
                S.append(j)

    else:#左下
        S = []
        for j in range(y-1,-1,-1):
            if B[x-y+j][j] == 'null':
                break
            elif B[x-y+j][j] == turn:
                for l in S:
                    B[x-y+l][l] = turn
                break
            else:
                S.append(j)

        S = []
        for i in range(x+1,8):
            if B[i][y+i-x] == 'null':
                break
            elif B[i][y+i-x] == turn:
                for l in S:
                    B[l][y+l-x] = turn
                break
            else:
                S.append(i)

    if x + y <= 7:#左上
        S = []
        for i in range(x-1,-1,-1):
            if B[i][y+x-i] == 'null':
                break
            elif B[i][y+x-i] == turn:
                for l in S:
                    B[l][y+x-l] = turn
                break
            else:
                S.append(i)

        S = []
        for j in range(y-1,-1,-1):
            if B[x+y-j][j] == 'null':
                break
            elif B[x+y-j][j] == turn:
                for l in S:
                    B[x+y-l][l] = turn
                break
            else:
                S.append(j)
    else:#右下
        S = []
        for i in range(x+1,8):
            if B[i][y+x-i] == 'null':
                break
            elif B[i][y+x-i] == turn:
                for l in S:
                    B[l][y+x-l] = turn
                break
            else:
                S.append(i)

        S = []
        for j in range(y+1,8):
            if B[x+y-j][j] == 'null':
                break
            elif B[x+y-j][j] == turn:
                for l in S:
                    B[x+y-l][l] = turn
                break
            else:
                S.append(j)
    B[x][y] = turn
    return B

show_double(B,BP,turn)は前述のshow(B)とshow_able(B,BP)を合わせたものです。

def show_double(B,BP,turn):
    if turn == 'black':
        T = '△ '
    else:
        T = '▲ '
    BandBP= ['null']*10
    for i in range(1,9):
        s = chr(97 + i - 1) + '|'
        for j in range(8):
            if B[i-1][j] == 'white':
                s += '● '
            elif B[i-1][j] == 'black':
                s += '○ '
            elif BP[i-1][j] == 'able':
                s += T
            else:
                s += '  '
            s += '|'
        s += chr(97 + i - 1)        
        BandBP[i] = s
    K = ' |'
    for i in range(1,9):
        K += ' ' + str(i)
        K += '|'
    BandBP[0] = K
    BandBP[9] = K
    for i in range(10):
        print(BandBP[i])