【Python】オセロ(Othero)[リバーシ(riversi)]を作ってみた

リクエストがあったのでオセロを作ってみました
作成所要時間は座標系の嫌なバグが出たので15時間ほどかかりました
参考になれば幸いです


#プレイヤー値 順番により入れ替わる
player=1
notplayer=2

#ボードサイズ
bsize=8

#盤面
board=[[0 for i in range(bsize)] for j in range(bsize)]
#初期配置
board[3][4]=1#黒
board[4][3]=1
board[3][3]=2#白
board[4][4]=2

#入力チェック
def check(x,y):
    try:
        val=board[y][x]
    except:#範囲外
        return False
    if val==0:#無接続
        return False
    return True

#全て駒で埋まったかチェック
def full():
    cnt=0
    for i in range(bsize):
        for j in range(bsize):
            if board[i][j]>0:
                cnt+=1
    if cnt==bsize*bsize:
        return True
    else:
        return False

#盤面表示
def pboard():
    print(" 01234567")
    for i in range(bsize):
        print(su[i],end='')
        for j in range(bsize):
            print(dic[board[i][j]],end='')
        print('\n',end='')

#裏返す
def reversi(x,y):#PieceReturn
    #既に置かれた所はダメ
    if board[y][x]==player:
        return False
    if board[y][x]==notplayer:
        return False
    #CanInputEraser(入力可能表示を消す)
    board[y][x]=player
    for i in range(bsize):
        for j in range(bsize):
            if board[i][j]<0:
                board[i][j]=0

    result=[]
    for dy,dx in [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]:
        depth,flg = 1,0
        tmp = []
        for _ in range(bsize):
            # 検索対象の座標を設定する
            ry,rx = y + (dy * depth) , x + (dx * depth) 
            # ボードの範囲を超えていたら抜ける
            if any([rx<0,ry<0,rx>=bsize,ry>=bsize]):
                break
            # 返せる駒がなくて0だったら抜ける
            if board[ry][rx]==0:
                break
            # 返せる駒がなくてplayerと同じ駒だったら抜ける
            elif flg==0 and board[ry][rx]==player:
                break
            # 返せる駒が初めて見つかったらflg=1にする
            elif flg==0 and board[ry][rx]==notplayer:
                flg = 1
                # 返せる座標を追加する
                tmp.append((ry,rx))
            # 返せる駒が初めて見つかったら返せる座標を追加する
            elif flg==1 and board[ry][rx]==notplayer:
                tmp.append((ry,rx))
            # flg=1の状態でplayerと同じ駒が見つかったらresultに追加する
            elif flg==1 and board[ry][rx]==player:
                result += tmp
                break
            depth += 1
        
    # 石をひっくり返す
    for y2,x2 in result:
        board[y2][x2]=player
    return True

#入力可能位置の検索
def CanInput():
    for x in range(bsize):
        for y in range(bsize):
            if board[y][x]<0:
                board[y][x]=0
    bingo=False
    for x in range(bsize):
        for y in range(bsize):
            if board[y][x]==player:
                for dy,dx in [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]:
                    depth,flg = 1,0
                    for _ in range(bsize):
                        # 検索対象の座標を設定する
                        ry,rx = y + (dy * depth) , x + (dx * depth) 
                        # ボードの範囲を超えていたら抜ける
                        if any([rx<0,ry<0,rx>=bsize,ry>=bsize]):
                            break
                        # 返せる駒がなくてplayerと同じ駒だったら抜ける
                        if flg==0 and board[ry][rx]==player:
                            break
                        # 返せる駒が初めて見つかったらflg=1にする
                        elif flg==0 and board[ry][rx]==notplayer:
                            flg = 1
                        # flg=1の状態でplayerと同じ駒が見つかったら処理を抜ける
                        elif flg==1 and board[ry][rx]==player:
                            break
                        # flg=1の状態で駒を置ける場合はマークする
                        elif flg==1 and board[ry][rx]<=0:
                            board[ry][rx]=-player
                            bingo=True
                            break
                        if board[ry][ry]<=0:
                            break
                        depth += 1
    return bingo

#結果表示 勝敗と駒の数
def DispResult():
    black=0
    white=0
    for i in range(bsize):
        for j in range(bsize):
            if board[i][j]==1:
                black+=1
            elif board[i][j]==2:
                white+=1
    if black>white:
        print(f"Black Win! Black={black} White={white}")
    elif white>black:
        print(f"White Win! White={white} Black={black}")
    elif white==black:
        print("Drow!")

#ここからメイン===================================================

#表示用
dispplayer={1:"○",2:"●"}
dic={0:' ',1:'○',2:'●',-1:'□',-2:'■'}
su={0:'0',1:'1',2:'2',3:'3',4:'4',5:'5',6:'6',7:'7',}
passcount=0

while(True):
    CanInput()  #入力可能位置の検索
    pboard()    #盤面表示
    #座標入力
    try:
        print(f"player={dispplayer[player]}")
        x=int(input("col="))
        y=int(input("row="))
    except:
        #入力不正時はゲーム終了
        break
    #駒をひっくり返す
    if check(x,y)==True:
        if full()==False:
            #ここで駒を返す処理
            if reversi(x,y)==False:
                print("NG") #まず無いハズ(既に駒があるところを指定)
                print("")
            else:
                passcount=0
                #プレイヤー交代
                player,notplayer=notplayer,player
        else:
            #全て駒で埋まった
            #結果表示
            pboard()
            DispResult()
            break   #ゲーム終了
    else:
        print("NG")
        print("")

    #駒が置ける位置の検索表示
    if CanInput()==False:
        passcount+=1
        #駒を置けない
        pboard()
        #すべて駒で埋まったか
        if full()==False or passcount<2:
            #駒が置けないのでパス
            print(f"player={dispplayer[player]} Pass!")
            print("")
            #プレイヤー交代
            player,notplayer=notplayer,player
            #黒白共に駒が置けない場合は終了
            if CanInput()==False:
                pboard()
                DispResult()
                break
        else:
            #全て駒で埋まった又は両プレイヤー共に駒が置けない
            #結果表示
            pboard()
            DispResult()
            break   #ゲーム終了