# -*- coding: utf-8 -*-
"""
邪魔付き重力付き三目並べ（プログラム）
"""
# これは，難易度１を達成するプログラムのソースコードです．
# これを流用する場合は，内容を理解し，コメントを追加しなさい．
# 難易度２以上の達成を目指すには，このコードからでは遠回りになる場合があります．
# きちんと自分で考えて試行錯誤することが大切です．


import random


BOARD_SIZE_H = 8  # 盤面横サイズ
BOARD_SIZE_V = 8  # 盤面縦サイズ
WINCON_LEN   = 3  # 勝利条件：三目
STONE_STR = ["[ ]", " X ", " O ", " # "]  # 石の文字
# 盤面を初期化した状態でグローバル変数として生成
board   = [[0 for j in range(BOARD_SIZE_H)] for i in range(BOARD_SIZE_V)]
TICKS_H = "\x1b[4;104m" + "".join([f"{i+1:2d} " for i in range(BOARD_SIZE_H)])  + "\x1b[0m"  # 横軸目盛

# 盤面の表示
def print_board():
    # print("\x1b[2J", end="")  # 画面のクリア
    print(TICKS_H)  # 横軸目盛
    j = 1
    for board_raw in board:
        # １行分の盤面の要素をそれぞれ文字列化
        str_raw = [STONE_STR[i] for i in board_raw]
        # 縦軸目盛とともに１行分の盤面を表示
        print("".join(str_raw))
        j += 1
    print(TICKS_H)  # 横軸目盛


# 位置が盤面の外かどうかを判定
def is_out_of_board(num_v, num_h):
    return not ((0 <= num_v < BOARD_SIZE_V) and (0 <= num_h < BOARD_SIZE_H))


# 盤面に空きがないか確認
def is_board_full():
    for j in range(BOARD_SIZE_H):
        # 重力付きなので上辺だけ確認すればよい
        if board[0][j] == 0:
            return False
    return True


# 一番下まで落ちたところに石を置く
def put_stone(num_side, num_h):
    num_v = BOARD_SIZE_V - 1
    if is_out_of_board(0, num_h) or (board[0][num_h] != 0):
        return
    while board[num_v][num_h] != 0:
        num_v -= 1
    board[num_v][num_h] = num_side
    return num_v


# 前に置かれた石の近くに邪魔な石を置く
def obstacle(num_h):
    dh = random.randrange(3) - 1
    put_stone(3, num_h + dh)


# 縦横斜めのいずれかの方向に指定の石が並んでいるか確認
# 下記は難易度２では間違っているので要修正
def check_line():
    return 1


def main():
    num_side = 1      # どちらの手番か
    num_move = 1      # 何手目か
    flag_win = False  # 勝敗フラグ

    num_h = random.randrange(BOARD_SIZE_H)
    put_stone(3, num_h)
    print_board()
    # 盤面に空きがあれば継続
    while not is_board_full():
        # 手番の出力
        print(STONE_STR[num_side] + "の番です")
        try:
            # 位置の入力　listのインデックスと対応させるため -1
            num_h = int(input(f"どこに置きますか？（{num_move}手目）：")) - 1
        except ValueError:
            print("整数で入力してください")
            continue
        print()  # 改行のみ

        # 位置が 0 以下の場合は終了
        if num_h < 0:
            break

        # 位置が盤面の外の場合や上限に達していた場合はやり直し
        if is_out_of_board(0, num_h) or (board[0][num_h] != 0):
            print("そこには置けません")
            continue

        num_v = put_stone(num_side, num_h)
        obstacle(num_h)

        # 各方向について同じ種類の石がどれだけ並んでいるかチェック
        flag_win = False
        for dv in range(-1, 2):
            for dh in range(2):
                # 置いたところと対向は省略（左上，上，右，右下を確認）
                if (dv <= 0) and (dh <= 0):
                    continue

                # 置いた石＋指示した方向＋その対向　で数え上げて合計
                # 下記は難易度２では間違っている（引数がない）ので要修正
                num_stone = check_line()
                
                # 指定の数以上なら勝ち
                if  num_stone >= WINCON_LEN:
                    flag_win = True

        # 盤面を表示
        print_board()
        # 勝敗がついた場合（石を置いた側が勝ち）は終了
        if flag_win:
            print(STONE_STR[num_side] + "の勝ちです")
            break
        # 攻守交替
        num_side = (num_side % 2) + 1
        num_move += 1

    else:
        print("引き分けです")
    
    input("\nEnterを押してプログラムを完全終了")


if __name__ == "__main__":
    main()
