ポンコツ夫婦のGame Trial Log Vol.1

Pythonでゲーム作成

カテゴリーの変更から

カテゴリー変更の説明がフォーマット化している点、ご容赦ください。今回は脱コロナをイメージしての変更ではなく、ゲームに関わる事柄を扱う新しい独立したカテゴリーとして「Game Trial Log」を立ち上げます。

Redkabagonはこれまで通り、G5Entertainmentの提供するアイテム探し&マッチ3を行い、その様子を録画・公開します。筆者Dr.takodemousは新たにゲームアプリを作成し、アプリのコード紹介と動作状況の録画公開に挑戦します

ゲームアプリ作成はGeminiのコーディングサポートを受けますが、時間がかかるため更新頻度は遅くなります。気長にお待ちください。また、機材に関わる内容は「The Gear」とクロスオーバーしますので、ゲームに興味はないけど機材には興味があるという方々のご来場もお待ちしております。

経歴の詳細は割愛しますが、2012年7月にサーティファイWEBクリエイター能力認定試験の上級(合格点65点に対し66点というブービー賞!)を45歳で取得。現在に至るまで、WEB業界で生計を立てられているとは言い難い状況です。他にIllustrator、Photoshop、Javascript、今では使われなくなったflashをかいつまんだ程度に理解している状況です。

Pythonのコード作成は未経験以前の無知。という状況でゲームを作成します。そこでR60世代に向けて是非ともメッセージしたい事があります。AI生成技術は産業革命に匹敵すると言われていますが、(筆者は産業革命を経験していないので匹敵するかどうかは不明!)AIは経験上、未知の世界へ飛び込むことに大いに役立ちます。R60世代の皆様も、一緒に飛び込みましょう!

【動画】AIと共同制作したオセロ、Dr.takodemousが勝利! Geminiと共同制作したオセロの完成版を、筆者がAI相手に打ち勝った動画です。ほぼ強制的に設置されたヒント表示を使用せず勝利したのは、ある程度のゲームのコツを知っていたからです。(コツは本ブログの趣旨と異なるため省略します。)

伝えたいのは、無知なレベルであってもAIを駆使すると、コーダーと言えるレベルのプログラムがつくれるという事です。ゲームやプログラムに興味がある方は是非参考にしてください。

プロンプトの参考になるように、最初に作成したオセロのコードから完成版までの道のりをフォルダに添付しておきます。プログラムに興味のある方は最初から順番に、ゲームに興味のある方は完全版を試してください。全てPythonのコードとなります。

redkabagonは今まで通り、G5Entertainmentの提供するアイテム探し&マッチ3をゲームしてもらい、その状況を録画そしてYou Tubeに投稿&本ブログにリンクする流れを行ってもらっています。

CapCutでの動画編集は現在のチャンネル登録分で最終となります。今後はCyberlinkの提供するPowerDirector 365を使用して作成していきます。PowerDirector 365についても、機材説明の機会に「The Gear」カテゴリーで紹介したいと思います。

映像作成に興味のある方は、是非ご来場ください。

pyramid of mahjong

前回まで五回にわたって記載してきたこの題目を、総括として終了したいと思います。コロナ禍が与えた影響は心身ともに、無意識下にダメージを与えていたと筆者は感じます。

漠然とした日々の不安や拠り所のない希望など、記載内容は意図的であれ無意識であれ、ネガティブな内容であった気がします。その当時はその状態が仕方ないとしても、現在の状況は自己選択が出来る状態です。

総じてカテゴリーの変更を行った後は、楽しみながら老いていくを実践しているようなものです。つまり最近のブログの内容は、R60のポンコツ夫婦が楽しみながら老いていく姿を紹介しているのです。やたら、参考にしてくださいというメッセージが多発するのは、自己選択の結果なような気がします。

やりがいや生きがいは、認知機能や肉体機能を維持するのに役立つと言われています。真意は不明といえばそれまでなのですが、信じてメッセージしていきたいと思います。

PR TIMESさんのサイトより”認知症予防の脳トレWebゲーム『Dr.脳トレ』をリリース。”のページを引用しています

今回からは、無知なAIコーダー(筆者)VSプロのコーダーの決戦の意味合いも含みます。脳科学には触れたことすらない筆者が「脳機能を鍛える」とプロンプトに指示して生まれたコードが、どこまでプロに肉薄できるか、自身でもウキウキしています。

第四回目も海馬を鍛えるシリーズになります。先ずはゲストモードで試してみて、効果を感じた場合アカウントを作成する感じで手軽に始めることが出来ます。このコナーのゲームは記憶の形成、空間学習、感情の制御を鍛えるというゲームとなっています。筆者も同類のアプリの作成にチャレンジするつもりです。

動画に登場しているバージョンは**プロンプト No.6です。DEPTH=4という設定で、レベルは中級者以上となっています。実行するには、Pythonを入手する必要があります。入手は自己責任ですが、世界中で使用されているプログラムを実行するためには必需品です。入手方法や設定方法などのリンクを貼っておきます。

どうぞGeminiのプロンプトの世界に、飛び込んでみてください。

プロンプトno1(外殻の設定と初期動作:相互手動)
# othello.py

# 1. ゲームボードの初期化
def create_board():
    board = []
    for i in range(8):
        row = [' '] * 8
        board.append(row)
    
    board[3][3] = 'W'
    board[3][4] = 'B'
    board[4][3] = 'B'
    board[4][4] = 'W'
    return board

# 2. ボードの表示
def print_board(board):
    print('  a b c d e f g h')
    print(' +-+-+-+-+-+-+-+-+')
    for i in range(8):
        print(f'{i+1}|', end='')
        for j in range(8):
            print(f'{board[i][j]}|', end='')
        print(f' {i+1}')
    print(' +-+-+-+-+-+-+-+-+')
    print('  a b c d e f g h')

# 3. 駒を置ける場所の判定と駒の反転
def is_valid_move(board, row, col, player, opponent):
    if not (0 <= row < 8 and 0 <= col < 8) or board[row][col] != ' ':
        return False

    directions = [
        (-1, -1), (-1, 0), (-1, 1),
        (0, -1),          (0, 1),
        (1, -1),  (1, 0),  (1, 1)
    ]
    
    found_flips = []

    for dr, dc in directions:
        r, c = row + dr, col + dc
        path = []
        while 0 <= r < 8 and 0 <= c < 8 and board[r][c] == opponent:
            path.append((r, c))
            r, c = r + dr, c + dc
        
        if 0 <= r < 8 and 0 <= c < 8 and board[r][c] == player and path:
            found_flips.extend(path)
            
    return found_flips

def flip_pieces(board, pieces_to_flip, player):
    for r, c in pieces_to_flip:
        board[r][c] = player

# 4. メインゲームループ
def main():
    board = create_board()
    player_turn = 'B'
    opponent_turn = 'W'

    while True:
        print_board(board)
        print(f'現在のターン: {player_turn}')

        try:
            move_str = input('駒を置く場所を入力してください (例: d3): ')
            col_char = move_str[0].lower()
            row_char = move_str[1:]
            
            # 入力を座標に変換
            col = 'abcdefgh'.index(col_char)
            row = int(row_char) - 1
            
            if not (0 <= row < 8 and 0 <= col < 8):
                print('無効な入力です。')
                continue
            
            # 有効な手か判定
            pieces_to_flip = is_valid_move(board, row, col, player_turn, opponent_turn)
            
            if pieces_to_flip:
                board[row][col] = player_turn
                flip_pieces(board, pieces_to_flip, player_turn)
                
                # ターンを交代
                player_turn, opponent_turn = opponent_turn, player_turn
            else:
                print('その場所には置けません。有効な手を打ってください。')
        
        except (ValueError, IndexError):
            print('無効な入力です。例: d3 のように入力してください。')

# プログラムの実行
if __name__ == '__main__':
    main()
プロンプトno2(GUIの設定1と初期動作:相互手動)
# 1. ゲームボードの初期化
# 盤面を表すための定数を定義します
# '・' : 空, '⚫' : 黒, '⚪' : 白
EMPTY = '・'
BLACK = '⚫'
WHITE = '⚪'

def create_board():
    """
    8x8の空の盤面を作成し、初期配置の石を配置します。
    """
    board = []
    for _ in range(8):
        row = [EMPTY] * 8
        board.append(row)
    
    board[3][3] = WHITE
    board[3][4] = BLACK
    board[4][3] = BLACK
    board[4][4] = WHITE
    return board

# 2. ボードの表示
def print_board(board):
    """
    現在の盤面をきれいに表示します。
    """
    # 列の表記を修正
    print('    a    b    c    d    e    f    g    h')
    # 罫線の表示
    print('  +---+---+---+---+---+---+---+---+---+---')
    for i in range(8):
        # 行の表示と升目の調整
        row_str = f'{i+1} |'
        for j in range(8):
            row_str += f' {board[i][j]} |'
        print(row_str)
        print('  +---+---+---+---+---+---+---+---+---+---')
    
# 3. 駒を置ける場所の判定と駒の反転
def is_valid_move(board, row, col, player, opponent):
    """
    指定された位置に石を置くことができるか判定し、
    ひっくり返せる石のリストを返します。
    """
    if not (0 <= row < 8 and 0 <= col < 8) or board[row][col] != EMPTY:
        return None

    # 8つの方向を定義 (行の変化, 列の変化)
    directions = [
        (-1, -1), (-1, 0), (-1, 1),
        (0, -1),            (0, 1),
        (1, -1),  (1, 0),  (1, 1)
    ]
    
    pieces_to_flip = []

    for dr, dc in directions:
        r, c = row + dr, col + dc
        path = []
        while 0 <= r < 8 and 0 <= c < 8 and board[r][c] == opponent:
            path.append((r, c))
            r, c = r + dr, c + dc
        
        # 挟み込んでいるかチェック
        if 0 <= r < 8 and 0 <= c < 8 and board[r][c] == player and path:
            pieces_to_flip.extend(path)
            
    return pieces_to_flip if pieces_to_flip else None

def flip_pieces(board, pieces_to_flip, player):
    """
    ひっくり返す石のリストを、指定されたプレイヤーの石に変換します。
    """
    for r, c in pieces_to_flip:
        board[r][c] = player

def get_valid_moves(board, player, opponent):
    """
    現在のプレイヤーが石を置けるすべての場所(有効な手)のリストを返します。
    """
    valid_moves = []
    for r in range(8):
        for c in range(8):
            if board[r][c] == EMPTY:
                if is_valid_move(board, r, c, player, opponent):
                    valid_moves.append((r, c))
    return valid_moves

def count_pieces(board):
    """
    盤面上の石の数を数え、勝敗を表示します。
    """
    black_count = 0
    white_count = 0
    for r in range(8):
        for c in range(8):
            if board[r][c] == BLACK:
                black_count += 1
            elif board[r][c] == WHITE:
                white_count += 1
    
    print(f"最終結果:黒 = {black_count}、白 = {white_count}")
    
    if black_count > white_count:
        print("黒の勝ちです!")
    elif white_count > black_count:
        print("白の勝ちです!")
    else:
        print("引き分けです。")

# 4. メインゲームループ
def main():
    """
    ゲームのメイン処理を実行します。
    """
    board = create_board()
    player_turn = BLACK
    opponent_turn = WHITE
    pass_count = 0  # 連続でパスした回数をカウント

    while True:
        print_board(board)
        
        valid_moves = get_valid_moves(board, player_turn, opponent_turn)
        
        if not valid_moves:
            pass_count += 1
            print(f'現在のターン: {"黒" if player_turn == BLACK else "白"}')
            print("置ける場所がありません。パスします。")
            
            if pass_count == 2:
                print("両プレイヤーがパスしました。ゲームを終了します。")
                break
            
            player_turn, opponent_turn = opponent_turn, player_turn
            continue
        else:
            pass_count = 0
            
        print(f'現在のターン: {"黒" if player_turn == BLACK else "白"}')
        
        try:
            move_str = input('駒を置く場所を入力してください (例: d3): ')
            
            if move_str.lower() == 'q':
                print("ゲームを終了します。")
                break

            col_char = move_str[0].lower()
            row_char = move_str[1:]
            
            col = 'abcdefgh'.index(col_char)
            row = int(row_char) - 1
            
            if (row, col) not in valid_moves:
                print('その場所には置けません。有効な手を打ってください。')
                continue
            
            pieces_to_flip = is_valid_move(board, row, col, player_turn, opponent_turn)
            board[row][col] = player_turn
            flip_pieces(board, pieces_to_flip, player_turn)
            
            player_turn, opponent_turn = opponent_turn, player_turn
        
        except (ValueError, IndexError):
            print('無効な入力です。例: d3 のように入力してください。')
    
    print("ゲーム終了!")
    count_pieces(board)
    
    input("結果を確認後、何かキーを押して終了してください...")

# プログラムの実行
if __name__ == '__main__':
    main()
プロンプトno3(GUIの設定2と初期動作:相互手動:盤面ほぼ完成)
import tkinter as tk
from tkinter import messagebox

# 盤面を表すための定数
EMPTY = '・'
BLACK = '⚫'
WHITE = '⚪'

# ウィンドウとキャンバスのサイズ
BOARD_SIZE = 400
CELL_SIZE = BOARD_SIZE // 8

# グローバル変数としてボードの状態を保持
game_board = None
canvas = None
current_player = BLACK
pass_count = 0

def create_board():
    """
    8x8の空の盤面を作成し、初期配置の石を配置します。
    """
    board = []
    for _ in range(8):
        row = [EMPTY] * 8
        board.append(row)
    
    board[3][3] = WHITE
    board[3][4] = BLACK
    board[4][3] = BLACK
    board[4][4] = WHITE
    return board

def is_valid_move(board, row, col, player, opponent):
    """
    指定された位置に石を置くことができるか判定し、
    ひっくり返せる石のリストを返します。
    """
    if not (0 <= row < 8 and 0 <= col < 8) or board[row][col] != EMPTY:
        return None

    directions = [
        (-1, -1), (-1, 0), (-1, 1),
        (0, -1),            (0, 1),
        (1, -1),  (1, 0),  (1, 1)
    ]
    
    pieces_to_flip = []

    for dr, dc in directions:
        r, c = row + dr, col + dc
        path = []
        while 0 <= r < 8 and 0 <= c < 8 and board[r][c] == opponent:
            path.append((r, c))
            r, c = r + dr, c + dc
        
        if 0 <= r < 8 and 0 <= c < 8 and board[r][c] == player and path:
            pieces_to_flip.extend(path)
            
    return pieces_to_flip if pieces_to_flip else None

def flip_pieces(board, pieces_to_flip, player):
    """
    ひっくり返す石のリストを、指定されたプレイヤーの石に変換します。
    """
    for r, c in pieces_to_flip:
        board[r][c] = player

def get_valid_moves(board, player, opponent):
    """
    現在のプレイヤーが石を置けるすべての場所(有効な手)のリストを返します。
    """
    valid_moves = []
    for r in range(8):
        for c in range(8):
            if board[r][c] == EMPTY:
                if is_valid_move(board, r, c, player, opponent):
                    valid_moves.append((r, c))
    return valid_moves

def count_pieces(board):
    """
    盤面上の石の数を数え、勝敗を決定します。
    """
    black_count = sum(row.count(BLACK) for row in board)
    white_count = sum(row.count(WHITE) for row in board)
    return black_count, white_count

def end_game_check():
    """
    ゲームが終了したかチェックし、終了していれば勝敗を表示します。
    """
    global pass_count
    
    black_count, white_count = count_pieces(game_board)
    
    if pass_count == 2 or (black_count + white_count) == 64:
        # ゲーム終了
        if black_count > white_count:
            message = f"ゲーム終了!\n黒の勝ちです!\n(黒: {black_count}, 白: {white_count})"
        elif white_count > black_count:
            message = f"ゲーム終了!\n白の勝ちです!\n(黒: {black_count}, 白: {white_count})"
        else:
            message = f"ゲーム終了!\n引き分けです!\n(黒: {black_count}, 白: {white_count})"
            
        messagebox.showinfo("ゲーム終了", message)
        return True
    return False

def draw_pieces():
    """
    Pythonのボード情報に基づいて、canvas上に石を描画します。
    """
    canvas.delete("all")
    
    # 盤面の升目を再描画
    for i in range(8):
        for j in range(8):
            x1 = j * CELL_SIZE
            y1 = i * CELL_SIZE
            x2 = x1 + CELL_SIZE
            y2 = y1 + CELL_SIZE
            canvas.create_rectangle(x1, y1, x2, y2, outline="black", fill="green")
            
    # 石を描画
    for row_idx in range(8):
        for col_idx in range(8):
            piece = game_board[row_idx][col_idx]
            if piece == BLACK:
                color = "black"
            elif piece == WHITE:
                color = "white"
            else:
                continue
            
            x1 = col_idx * CELL_SIZE + 5
            y1 = row_idx * CELL_SIZE + 5
            x2 = x1 + CELL_SIZE - 10
            y2 = y1 + CELL_SIZE - 10
            
            canvas.create_oval(x1, y1, x2, y2, fill=color, outline="black")

def on_click(event):
    """
    マウスがクリックされたときに呼び出される関数です。
    """
    global current_player, pass_count
    
    col = event.x // CELL_SIZE
    row = event.y // CELL_SIZE
    
    opponent_player = WHITE if current_player == BLACK else BLACK
    
    pieces_to_flip = is_valid_move(game_board, row, col, current_player, opponent_player)

    if pieces_to_flip:
        # 有効な手であれば、石を置く
        game_board[row][col] = current_player
        flip_pieces(game_board, pieces_to_flip, current_player)
        
        # プレイヤーを交代
        current_player = opponent_player
        pass_count = 0  # パスカウントをリセット

    else:
        # 無効な手の場合、何もしない
        return
        
    draw_pieces()
    
    # 相手プレイヤーに有効な手があるかチェック
    if not get_valid_moves(game_board, current_player, opponent_player):
        print(f'{current_player}は置ける場所がありません。パスします。')
        pass_count += 1
        current_player = opponent_player  # プレイヤーを再度交代
        
        # 連続パスの場合、ゲーム終了チェック
        if pass_count == 2:
            end_game_check()
        else:
            # パスしたので、盤面を再描画して次のプレイヤーの番
            draw_pieces()
            
    # ゲーム終了条件を常にチェック
    if not end_game_check():
        pass
    else:
        print("ゲームが終了しました。")

def create_gui_board():
    """
    tkinterのウィンドウとオセロ盤のGUIを作成します。
    """
    global game_board, canvas
    
    root = tk.Tk()
    root.title("オセロゲーム")

    canvas = tk.Canvas(root, width=BOARD_SIZE, height=BOARD_SIZE, bg="green")
    canvas.pack()
    
    canvas.bind("<Button-1>", on_click)
            
    game_board = create_board()
    draw_pieces()

    root.mainloop()

# プログラムの実行
if __name__ == "__main__":
    create_gui_board()
プロンプトno4(AI対戦相手のプログラムと初期動作)
import tkinter as tk
from tkinter import messagebox
import random # <--- ここを追加

# 盤面を表すための定数
EMPTY = '・'
BLACK = '⚫'
WHITE = '⚪'

# ウィンドウとキャンバスのサイズ
BOARD_SIZE = 400
CELL_SIZE = BOARD_SIZE // 8

# グローバル変数としてボードの状態を保持
game_board = None
canvas = None
current_player = BLACK
pass_count = 0

# AIの設定
AI_PLAYER = WHITE # AIを白のプレイヤーに設定
IS_AI_TURN = False # AIのターンかどうかを示すフラグ

def create_board():
    """
    8x8の空の盤面を作成し、初期配置の石を配置します。
    """
    board = []
    for _ in range(8):
        row = [EMPTY] * 8
        board.append(row)
    
    board[3][3] = WHITE
    board[3][4] = BLACK
    board[4][3] = BLACK
    board[4][4] = WHITE
    return board

# ----------------- AIロジックの追加 -----------------
def get_ai_move(valid_moves):
    """
    有効な手の中からランダムに手を選択します。
    """
    return random.choice(valid_moves)

def handle_ai_turn():
    """
    AIのターンを処理します。
    """
    global current_player, pass_count, IS_AI_TURN
    
    opponent_player = BLACK # AIは白なので、相手は黒
    
    valid_moves = get_valid_moves(game_board, AI_PLAYER, opponent_player)

    if not valid_moves:
        pass_count += 1
        print("AIは置ける場所がありません。パスします。")
        current_player = BLACK # プレイヤーを交代
        IS_AI_TURN = False
        end_game_check()
        draw_pieces()
    else:
        pass_count = 0
        
        # AIがランダムに手を選択
        row, col = get_ai_move(valid_moves)
        
        # 石を置く処理
        pieces_to_flip = is_valid_move(game_board, row, col, AI_PLAYER, opponent_player)
        game_board[row][col] = AI_PLAYER
        flip_pieces(game_board, pieces_to_flip, AI_PLAYER)
        
        current_player = BLACK # プレイヤーを交代
        IS_AI_TURN = False
        
        draw_pieces()
        
        if not end_game_check():
            pass
        else:
            print("ゲームが終了しました。")
            
def on_click(event):
    """
    マウスがクリックされたときに呼び出される関数です。
    """
    global current_player, pass_count, IS_AI_TURN
    
    if IS_AI_TURN:
        return # AIのターン中はプレイヤーの入力を無視
    
    col = event.x // CELL_SIZE
    row = event.y // CELL_SIZE
    
    opponent_player = WHITE # プレイヤーは黒なので、相手は白
    
    pieces_to_flip = is_valid_move(game_board, row, col, current_player, opponent_player)

    if pieces_to_flip:
        game_board[row][col] = current_player
        flip_pieces(game_board, pieces_to_flip, current_player)
        
        pass_count = 0
        current_player = opponent_player
        IS_AI_TURN = True # 次のターンはAI
        
        draw_pieces()
        
        if not end_game_check():
            canvas.after(500, handle_ai_turn) # 0.5秒後にAIを動かす
        else:
            print("ゲームが終了しました。")
    else:
        print("その場所には置けません。有効な手を打ってください。")


# ----------------- ここから下の関数は変更なし -----------------
def is_valid_move(board, row, col, player, opponent):
    if not (0 <= row < 8 and 0 <= col < 8) or board[row][col] != EMPTY:
        return None
    directions = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
    pieces_to_flip = []
    for dr, dc in directions:
        r, c = row + dr, col + dc
        path = []
        while 0 <= r < 8 and 0 <= c < 8 and board[r][c] == opponent:
            path.append((r, c))
            r, c = r + dr, c + dc
        if 0 <= r < 8 and 0 <= c < 8 and board[r][c] == player and path:
            pieces_to_flip.extend(path)
    return pieces_to_flip if pieces_to_flip else None

def flip_pieces(board, pieces_to_flip, player):
    for r, c in pieces_to_flip:
        board[r][c] = player

def get_valid_moves(board, player, opponent):
    valid_moves = []
    for r in range(8):
        for c in range(8):
            if board[r][c] == EMPTY:
                if is_valid_move(board, r, c, player, opponent):
                    valid_moves.append((r, c))
    return valid_moves

def count_pieces(board):
    black_count = sum(row.count(BLACK) for row in board)
    white_count = sum(row.count(WHITE) for row in board)
    return black_count, white_count

def end_game_check():
    global pass_count
    black_count, white_count = count_pieces(game_board)
    if pass_count == 2 or (black_count + white_count) == 64:
        if black_count > white_count:
            message = f"ゲーム終了!\n黒の勝ちです!\n(黒: {black_count}, 白: {white_count})"
        elif white_count > black_count:
            message = f"ゲーム終了!\n白の勝ちです!\n(黒: {black_count}, 白: {white_count})"
        else:
            message = f"ゲーム終了!\n引き分けです!\n(黒: {black_count}, 白: {white_count})"
        messagebox.showinfo("ゲーム終了", message)
        return True
    return False

def draw_pieces():
    canvas.delete("all")
    for i in range(8):
        for j in range(8):
            x1 = j * CELL_SIZE
            y1 = i * CELL_SIZE
            x2 = x1 + CELL_SIZE
            y2 = y1 + CELL_SIZE
            canvas.create_rectangle(x1, y1, x2, y2, outline="black", fill="green")
    for row_idx in range(8):
        for col_idx in range(8):
            piece = game_board[row_idx][col_idx]
            if piece == BLACK:
                color = "black"
            elif piece == WHITE:
                color = "white"
            else:
                continue
            x1 = col_idx * CELL_SIZE + 5
            y1 = row_idx * CELL_SIZE + 5
            x2 = x1 + CELL_SIZE - 10
            y2 = y1 + CELL_SIZE - 10
            canvas.create_oval(x1, y1, x2, y2, fill=color, outline="black")

def create_gui_board():
    global game_board, canvas
    root = tk.Tk()
    root.title("オセロゲーム")
    canvas = tk.Canvas(root, width=BOARD_SIZE, height=BOARD_SIZE, bg="green")
    canvas.pack()
    canvas.bind("<Button-1>", on_click)
    game_board = create_board()
    draw_pieces()
    root.mainloop()

if __name__ == "__main__":
    create_gui_board()
プロンプトno5(AI対戦相手のGUI改善:ヒント表示と初期動作)
import tkinter as tk
from tkinter import messagebox
import copy
import time 
import sys

# --- ゲーム定数 ---
BOARD_SIZE = 8
CELL_SIZE = 60
WINDOW_SIZE = BOARD_SIZE * CELL_SIZE
SIDE_PANEL_WIDTH = 150
AI_PLAYER = 2 # 2: 黒 (後攻) / 1: 白 (先攻)
SEARCH_DEPTH = 4 # AIの探索深さ

# --- グローバル変数 ---
root = None
canvas = None
board = None
current_player = 1 # 1:白, 2:黒
game_running = True
score_label = None
turn_label = None
history = [] 

# --- 初期化 ---

def create_initial_board():
    """初期盤面を作成 (0:空, 1:白, 2:黒)"""
    new_board = [[0] * BOARD_SIZE for _ in range(BOARD_SIZE)]
    new_board[3][3] = 1 # 白
    new_board[3][4] = 2 # 黒
    new_board[4][3] = 2 # 黒
    new_board[4][4] = 1 # 白
    return new_board

# --- ルールとAIロジック ---

def is_valid_move(r, c, player, current_board):
    """指定されたマスに駒を置けるかチェックし、裏返せる駒のリストを返す"""
    if current_board[r][c] != 0:
        return []

    opponent = 3 - player
    flips = []

    # 8方向をチェック
    directions = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (-1, 1), (1, -1), (1, 1)]

    for dr, dc in directions:
        line_flips = []
        rr, cc = r + dr, c + dc

        # 相手の駒が続く限り進む
        while 0 <= rr < BOARD_SIZE and 0 <= cc < BOARD_SIZE and current_board[rr][cc] == opponent:
            line_flips.append((rr, cc))
            rr, cc = rr + dr, cc + dc
        
        # 終点が自分の駒で、間に裏返せる駒がある場合
        if line_flips and 0 <= rr < BOARD_SIZE and 0 <= cc < BOARD_SIZE and current_board[rr][cc] == player:
            flips.extend(line_flips)

    return flips

def get_valid_moves(player, current_board):
    """合法手の一覧を (r, c) のリストで返す"""
    valid_moves = []
    for r in range(BOARD_SIZE):
        for c in range(BOARD_SIZE):
            if is_valid_move(r, c, player, current_board):
                valid_moves.append((r, c))
    return valid_moves

def apply_move(r, c, player, current_board):
    """実際に駒を置き、盤面を更新する (新しい盤面を返す)"""
    new_board = [row[:] for row in current_board]
    flips = is_valid_move(r, c, player, current_board)
    
    if not flips:
        return new_board # 無効な手の場合は元の盤面を返す

    new_board[r][c] = player
    for fr, fc in flips:
        new_board[fr][fc] = player
        
    return new_board

def evaluate_board(current_board, player):
    """評価関数: 駒の数の差を計算"""
    p1_count = sum(row.count(1) for row in current_board)
    p2_count = sum(row.count(2) for row in current_board)
    
    if player == 1:
        return p1_count - p2_count
    else:
        return p2_count - p1_count

def minimax(current_board, depth, is_maximizing_player, alpha, beta):
    """Minimax with Alpha-Beta Pruning"""
    current_player_minimax = 2 if is_maximizing_player else 1
    
    # 終端条件
    valid_moves = get_valid_moves(current_player_minimax, current_board)
    if depth == 0 or (not valid_moves and not get_valid_moves(3 - current_player_minimax, current_board)):
        return evaluate_board(current_board, 2), None # AI(黒=2)視点の評価を返す

    best_move = None
    
    if is_maximizing_player: # AI (黒=2) の手番
        max_eval = -float('inf')
        for r, c in valid_moves:
            new_board = apply_move(r, c, 2, current_board)
            current_eval, _ = minimax(new_board, depth - 1, False, alpha, beta)
            
            if current_eval > max_eval:
                max_eval = current_eval
                best_move = (r, c)
            
            alpha = max(alpha, max_eval)
            if beta <= alpha:
                break
        return max_eval, best_move
        
    else: # プレイヤー (白=1) の手番
        min_eval = float('inf')
        for r, c in valid_moves:
            new_board = apply_move(r, c, 1, current_board)
            current_eval, _ = minimax(new_board, depth - 1, True, alpha, beta)
            
            if current_eval < min_eval:
                min_eval = current_eval
                best_move = (r, c)
                
            beta = min(beta, min_eval)
            if beta <= alpha:
                break
        return min_eval, best_move

def find_best_move(current_board, depth):
    start_time = time.time()
    _, best_move = minimax(current_board, depth, True, -float('inf'), float('inf'))
    end_time = time.time()
    print(f"Minimax探索時間: {end_time - start_time:.2f}秒 (深さ: {depth})")
    return best_move

# --- UIと描画 ---

def draw_board():
    """盤面を描画し、駒を配置する"""
    canvas.delete("all")
    
    # 盤面のグリッド線を描画
    for i in range(BOARD_SIZE + 1):
        # 垂直線
        canvas.create_line(i * CELL_SIZE, 0, i * CELL_SIZE, WINDOW_SIZE, fill="black")
        # 水平線
        canvas.create_line(0, i * CELL_SIZE, WINDOW_SIZE, i * CELL_SIZE, fill="black")

    # 駒の配置
    for r in range(BOARD_SIZE):
        for c in range(BOARD_SIZE):
            player = board[r][c]
            if player != 0:
                x1 = c * CELL_SIZE + 5
                y1 = r * CELL_SIZE + 5
                x2 = (c + 1) * CELL_SIZE - 5
                y2 = (r + 1) * CELL_SIZE - 5
                color = "white" if player == 1 else "black"
                canvas.create_oval(x1, y1, x2, y2, fill=color, outline="black")

    update_score_display()

def update_score_display():
    """スコアとターン表示を更新する"""
    p1_count = sum(row.count(1) for row in board)
    p2_count = sum(row.count(2) for row in board)
    
    score_text = f"白: {p1_count}\n黒: {p2_count}"
    turn_text = f"現在のターン: {'白' if current_player == 1 else '黒'}"
    
    if score_label and turn_label:
        score_label.config(text=score_text)
        turn_label.config(text=turn_text)

def show_hint():
    """合法手があるマスをハイライト表示する"""
    canvas.delete("hint")
    valid_moves = get_valid_moves(current_player, board)
    
    for r, c in valid_moves:
        x1 = c * CELL_SIZE + 2
        y1 = r * CELL_SIZE + 2
        x2 = (c + 1) * CELL_SIZE - 2
        y2 = (r + 1) * CELL_SIZE - 2
        canvas.create_rectangle(x1, y1, x2, y2, outline="yellow", width=3, tags="hint")

# --- イベントハンドラ ---

def handle_click(event):
    """マウスがクリックされたときの処理"""
    global board, current_player, game_running
    
    if not game_running or current_player == AI_PLAYER:
        return

    c = event.x // CELL_SIZE
    r = event.y // CELL_SIZE
    
    if not (0 <= r < BOARD_SIZE and 0 <= c < BOARD_SIZE):
        return

    flips = is_valid_move(r, c, current_player, board)
    
    if flips:
        save_state() # 履歴保存
        
        board = apply_move(r, c, current_player, board)
        
        next_player = 3 - current_player
        end_turn(next_player)
    else:
        messagebox.showinfo("無効な手", "そこには置けません。")

def end_turn(next_player):
    """ターン終了時の処理"""
    global current_player, game_running
    current_player = next_player
    
    draw_board()
    
    p1_moves = get_valid_moves(1, board)
    p2_moves = get_valid_moves(2, board)
    
    if not p1_moves and not p2_moves:
        # 両者とも置けない = ゲーム終了
        game_running = False
        p1_count = sum(row.count(1) for row in board)
        p2_count = sum(row.count(2) for row in board)
        
        winner = "引き分け"
        if p1_count > p2_count: winner = "白の勝利"
        elif p2_count > p1_count: winner = "黒の勝利"
            
        messagebox.showinfo("ゲーム終了", f"最終スコア 白:{p1_count}, 黒:{p2_count}\n{winner}")
        return
        
    elif not get_valid_moves(current_player, board):
        # パス (合法手が無い場合は相手のターンに戻る)
        messagebox.showinfo("パス", f"{'白' if current_player == 1 else '黒'}は置く場所がないためパスします。")
        current_player = 3 - current_player
        draw_board() # プレイヤーが変わったことを表示

    show_hint()
    
    if current_player == AI_PLAYER and game_running:
        root.after(500, make_ai_move) # 0.5秒後にAIを起動

def make_ai_move():
    """AIが指し手を決定し、実行する"""
    global board, current_player, game_running
    
    if not game_running or current_player != AI_PLAYER:
        return

    save_state() # 履歴保存
    
    best_move = find_best_move(board, SEARCH_DEPTH)
    
    if best_move:
        r, c = best_move
        board = apply_move(r, c, AI_PLAYER, board)
        
        next_player = 3 - AI_PLAYER
        end_turn(next_player)
    else:
        # AIが置けない場合もパス処理で end_turn が実行される
        end_turn(3 - AI_PLAYER)

def save_state():
    """現在のゲーム状態を履歴に保存する (Undo用)"""
    global history
    state = (
        [row[:] for row in board],
        current_player
    )
    history.append(state)

def undo_move():
    """一手前の状態に戻す"""
    global board, current_player, game_running, history
    
    if current_player == AI_PLAYER:
        messagebox.showinfo("警告", "AIの手番中はUndoできません。")
        return
        
    if len(history) <= 1:
        messagebox.showinfo("警告", "初期状態のため、これ以上戻せません。")
        return
    
    # プレイヤーとAIの2手分を戻す
    if len(history) >= 2:
        history.pop() # AIの手
        history.pop() # プレイヤーの手
    else:
        # 初期盤面直後の履歴の場合
        history.pop() 

    prev_board, prev_player = history[-1]
    
    board = [row[:] for row in prev_board]
    current_player = prev_player
    game_running = True
    
    draw_board()
    show_hint()
    
    if current_player == AI_PLAYER and game_running:
        root.after(500, make_ai_move)
        
# --- GUIメイン関数 ---

def create_board_ui():
    global root, canvas, board, score_label, turn_label
    
    root = tk.Tk()
    root.title(f"オセロゲーム (AI深さ: {SEARCH_DEPTH})")
    
    # --- UI中央配置のための改善 ---
    
    # 1. すべての要素を保持するメインフレームを作成
    main_frame = tk.Frame(root)
    
    # 2. main_frameを親ウィンドウの中央に配置
    #    expand=True で利用可能なスペースを広げ、anchor='center' で中央に寄せます。
    main_frame.pack(expand=True, anchor='center') 
    
    # --------------------------------

    # 3. ボード(キャンバス)を main_frame の中に配置 (親を root から main_frame に変更)
    canvas = tk.Canvas(main_frame, width=WINDOW_SIZE, height=WINDOW_SIZE, bg="green")
    canvas.pack(side=tk.LEFT)
    
    # 4. スコアパネル(サイドパネル)を main_frame の中に配置 (親を root から main_frame に変更)
    score_frame = tk.Frame(main_frame, width=SIDE_PANEL_WIDTH)
    score_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=10, pady=10)
    
    # --- スコアとターン表示 ---
    
    score_label = tk.Label(score_frame, text="スコア", font=("Arial", 16))
    score_label.pack(pady=20)
    
    turn_label = tk.Label(score_frame, text="ターン", font=("Arial", 14))
    turn_label.pack(pady=10)

    # --- ボタン ---
    
    undo_button = tk.Button(score_frame, text="一手戻る (Undo)", command=undo_move, 
                            height=2, bg="#B0C4DE", fg="black")
    undo_button.pack(pady=20)
    
    hint_button = tk.Button(score_frame, text="ヒント表示", command=show_hint,
                            height=2, bg="#FFFACD", fg="black")
    hint_button.pack(pady=10)
    
    # --- ゲームの起動 ---
    
    board = create_initial_board()
    canvas.bind("<Button-1>", handle_click)
    
    # 初期状態を履歴に保存
    save_state()
    
    draw_board()
    show_hint()
    
    def on_closing():
        root.destroy()
        sys.exit()
        
    root.protocol("WM_DELETE_WINDOW", on_closing)
    root.mainloop()

if __name__ == "__main__":
    create_board_ui()
プロンプトno6(AI対戦相手の完全版ヒント表示の選択機能の追加と初期動作)
import tkinter as tk
from tkinter import messagebox
import copy
import time 
import sys

# --- ゲーム定数 ---
BOARD_SIZE = 8
CELL_SIZE = 60
WINDOW_SIZE = BOARD_SIZE * CELL_SIZE
SIDE_PANEL_WIDTH = 150
AI_PLAYER = 2 # 2: 黒 (後攻) / 1: 白 (先攻)
SEARCH_DEPTH = 4 # AIの探索深さ

# --- グローバル変数 ---
root = None
canvas = None
board = None
current_player = 1 # 1:白, 2:黒
game_running = True
score_label = None
turn_label = None
history = [] 

# --- 初期化 ---

def create_initial_board():
    """初期盤面を作成 (0:空, 1:白, 2:黒)"""
    new_board = [[0] * BOARD_SIZE for _ in range(BOARD_SIZE)]
    new_board[3][3] = 1 # 白
    new_board[3][4] = 2 # 黒
    new_board[4][3] = 2 # 黒
    new_board[4][4] = 1 # 白
    return new_board

# --- ルールとAIロジック ---

def is_valid_move(r, c, player, current_board):
    """指定されたマスに駒を置けるかチェックし、裏返せる駒のリストを返す"""
    if current_board[r][c] != 0:
        return []

    opponent = 3 - player
    flips = []

    # 8方向をチェック
    directions = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (-1, 1), (1, -1), (1, 1)]

    for dr, dc in directions:
        line_flips = []
        rr, cc = r + dr, c + dc

        # 相手の駒が続く限り進む
        while 0 <= rr < BOARD_SIZE and 0 <= cc < BOARD_SIZE and current_board[rr][cc] == opponent:
            line_flips.append((rr, cc))
            rr, cc = rr + dr, cc + dc
        
        # 終点が自分の駒で、間に裏返せる駒がある場合
        if line_flips and 0 <= rr < BOARD_SIZE and 0 <= cc < BOARD_SIZE and current_board[rr][cc] == player:
            flips.extend(line_flips)

    return flips

def get_valid_moves(player, current_board):
    """合法手の一覧を (r, c) のリストで返す"""
    valid_moves = []
    for r in range(BOARD_SIZE):
        for c in range(BOARD_SIZE):
            if is_valid_move(r, c, player, current_board):
                valid_moves.append((r, c))
    return valid_moves

def apply_move(r, c, player, current_board):
    """実際に駒を置き、盤面を更新する (新しい盤面を返す)"""
    new_board = [row[:] for row in current_board]
    flips = is_valid_move(r, c, player, current_board)
    
    if not flips:
        return new_board # 無効な手の場合は元の盤面を返す

    new_board[r][c] = player
    for fr, fc in flips:
        new_board[fr][fc] = player
        
    return new_board

def evaluate_board(current_board, player):
    """評価関数: 駒の数の差を計算"""
    p1_count = sum(row.count(1) for row in current_board)
    p2_count = sum(row.count(2) for row in current_board)
    
    if player == 1:
        return p1_count - p2_count
    else:
        return p2_count - p1_count

def minimax(current_board, depth, is_maximizing_player, alpha, beta):
    """Minimax with Alpha-Beta Pruning"""
    current_player_minimax = 2 if is_maximizing_player else 1
    
    # 終端条件
    valid_moves = get_valid_moves(current_player_minimax, current_board)
    if depth == 0 or (not valid_moves and not get_valid_moves(3 - current_player_minimax, current_board)):
        return evaluate_board(current_board, 2), None # AI(黒=2)視点の評価を返す

    best_move = None
    
    if is_maximizing_player: # AI (黒=2) の手番
        max_eval = -float('inf')
        for r, c in valid_moves:
            new_board = apply_move(r, c, 2, current_board)
            current_eval, _ = minimax(new_board, depth - 1, False, alpha, beta)
            
            if current_eval > max_eval:
                max_eval = current_eval
                best_move = (r, c)
            
            alpha = max(alpha, max_eval)
            if beta <= alpha:
                break
        return max_eval, best_move
        
    else: # プレイヤー (白=1) の手番
        min_eval = float('inf')
        for r, c in valid_moves:
            new_board = apply_move(r, c, 1, current_board)
            current_eval, _ = minimax(new_board, depth - 1, True, alpha, beta)
            
            if current_eval < min_eval:
                min_eval = current_eval
                best_move = (r, c)
                
            beta = min(beta, min_eval)
            if beta <= alpha:
                break
        return min_eval, best_move

def find_best_move(current_board, depth):
    start_time = time.time()
    _, best_move = minimax(current_board, depth, True, -float('inf'), float('inf'))
    end_time = time.time()
    print(f"Minimax探索時間: {end_time - start_time:.2f}秒 (深さ: {depth})")
    return best_move

# --- UIと描画 ---

def draw_board():
    """盤面を描画し、駒を配置する"""
    canvas.delete("all")
    
    # 盤面のグリッド線を描画
    for i in range(BOARD_SIZE + 1):
        # 垂直線
        canvas.create_line(i * CELL_SIZE, 0, i * CELL_SIZE, WINDOW_SIZE, fill="black")
        # 水平線
        canvas.create_line(0, i * CELL_SIZE, WINDOW_SIZE, i * CELL_SIZE, fill="black")

    # 駒の配置
    for r in range(BOARD_SIZE):
        for c in range(BOARD_SIZE):
            player = board[r][c]
            if player != 0:
                x1 = c * CELL_SIZE + 5
                y1 = r * CELL_SIZE + 5
                x2 = (c + 1) * CELL_SIZE - 5
                y2 = (r + 1) * CELL_SIZE - 5
                color = "white" if player == 1 else "black"
                canvas.create_oval(x1, y1, x2, y2, fill=color, outline="black")

    update_score_display()

def update_score_display():
    """スコアとターン表示を更新する"""
    p1_count = sum(row.count(1) for row in board)
    p2_count = sum(row.count(2) for row in board)
    
    score_text = f"白: {p1_count}\n黒: {p2_count}"
    turn_text = f"現在のターン: {'白' if current_player == 1 else '黒'}"
    
    if score_label and turn_label:
        score_label.config(text=score_text)
        turn_label.config(text=turn_text)

def show_hint():
    """合法手があるマスをハイライト表示する"""
    canvas.delete("hint")
    valid_moves = get_valid_moves(current_player, board)
    
    for r, c in valid_moves:
        x1 = c * CELL_SIZE + 2
        y1 = r * CELL_SIZE + 2
        x2 = (c + 1) * CELL_SIZE - 2
        y2 = (r + 1) * CELL_SIZE - 2
        canvas.create_rectangle(x1, y1, x2, y2, outline="yellow", width=3, tags="hint")

# --- イベントハンドラ ---

def handle_click(event):
    """マウスがクリックされたときの処理"""
    global board, current_player, game_running
    
    if not game_running or current_player == AI_PLAYER:
        return

    c = event.x // CELL_SIZE
    r = event.y // CELL_SIZE
    
    if not (0 <= r < BOARD_SIZE and 0 <= c < BOARD_SIZE):
        return

    flips = is_valid_move(r, c, current_player, board)
    
    if flips:
        save_state() # 履歴保存
        
        board = apply_move(r, c, current_player, board)
        
        next_player = 3 - current_player
        end_turn(next_player)
    else:
        messagebox.showinfo("無効な手", "そこには置けません。")

def end_turn(next_player):
    """ターン終了時の処理"""
    global current_player, game_running
    current_player = next_player
    
    draw_board()
    
    p1_moves = get_valid_moves(1, board)
    p2_moves = get_valid_moves(2, board)
    
    if not p1_moves and not p2_moves:
        # 両者とも置けない = ゲーム終了
        game_running = False
        p1_count = sum(row.count(1) for row in board)
        p2_count = sum(row.count(2) for row in board)
        
        winner = "引き分け"
        if p1_count > p2_count: winner = "白の勝利"
        elif p2_count > p1_count: winner = "黒の勝利"
            
        messagebox.showinfo("ゲーム終了", f"最終スコア 白:{p1_count}, 黒:{p2_count}\n{winner}")
        return
        
    elif not get_valid_moves(current_player, board):
        # パス (合法手が無い場合は相手のターンに戻る)
        messagebox.showinfo("パス", f"{'白' if current_player == 1 else '黒'}は置く場所がないためパスします。")
        current_player = 3 - current_player
        draw_board() # プレイヤーが変わったことを表示

    show_hint()
    
    if current_player == AI_PLAYER and game_running:
        root.after(500, make_ai_move) # 0.5秒後にAIを起動

def make_ai_move():
    """AIが指し手を決定し、実行する"""
    global board, current_player, game_running
    
    if not game_running or current_player != AI_PLAYER:
        return

    save_state() # 履歴保存
    
    best_move = find_best_move(board, SEARCH_DEPTH)
    
    if best_move:
        r, c = best_move
        board = apply_move(r, c, AI_PLAYER, board)
        
        next_player = 3 - AI_PLAYER
        end_turn(next_player)
    else:
        # AIが置けない場合もパス処理で end_turn が実行される
        end_turn(3 - AI_PLAYER)

def save_state():
    """現在のゲーム状態を履歴に保存する (Undo用)"""
    global history
    state = (
        [row[:] for row in board],
        current_player
    )
    history.append(state)

def undo_move():
    """一手前の状態に戻す"""
    global board, current_player, game_running, history
    
    if current_player == AI_PLAYER:
        messagebox.showinfo("警告", "AIの手番中はUndoできません。")
        return
        
    if len(history) <= 1:
        messagebox.showinfo("警告", "初期状態のため、これ以上戻せません。")
        return
    
    # プレイヤーとAIの2手分を戻す
    if len(history) >= 2:
        history.pop() # AIの手
        history.pop() # プレイヤーの手
    else:
        # 初期盤面直後の履歴の場合
        history.pop() 

    prev_board, prev_player = history[-1]
    
    board = [row[:] for row in prev_board]
    current_player = prev_player
    game_running = True
    
    draw_board()
    show_hint()
    
    if current_player == AI_PLAYER and game_running:
        root.after(500, make_ai_move)
        
# --- GUIメイン関数 ---

def create_board_ui():
    global root, canvas, board, score_label, turn_label
    
    root = tk.Tk()
    root.title(f"オセロゲーム (AI深さ: {SEARCH_DEPTH})")
    
    # --- UI中央配置のための改善 ---
    
    # 1. すべての要素を保持するメインフレームを作成
    main_frame = tk.Frame(root)
    
    # 2. main_frameを親ウィンドウの中央に配置
    #    expand=True で利用可能なスペースを広げ、anchor='center' で中央に寄せます。
    main_frame.pack(expand=True, anchor='center') 
    
    # --------------------------------

    # 3. ボード(キャンバス)を main_frame の中に配置 (親を root から main_frame に変更)
    canvas = tk.Canvas(main_frame, width=WINDOW_SIZE, height=WINDOW_SIZE, bg="green")
    canvas.pack(side=tk.LEFT)
    
    # 4. スコアパネル(サイドパネル)を main_frame の中に配置 (親を root から main_frame に変更)
    score_frame = tk.Frame(main_frame, width=SIDE_PANEL_WIDTH)
    score_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=10, pady=10)
    
    # --- スコアとターン表示 ---
    
    score_label = tk.Label(score_frame, text="スコア", font=("Arial", 16))
    score_label.pack(pady=20)
    
    turn_label = tk.Label(score_frame, text="ターン", font=("Arial", 14))
    turn_label.pack(pady=10)

    # --- ボタン ---
    
    undo_button = tk.Button(score_frame, text="一手戻る (Undo)", command=undo_move, 
                            height=2, bg="#B0C4DE", fg="black")
    undo_button.pack(pady=20)
    
    hint_button = tk.Button(score_frame, text="ヒント表示", command=show_hint,
                            height=2, bg="#FFFACD", fg="black")
    hint_button.pack(pady=10)
    
    # --- ゲームの起動 ---
    
    board = create_initial_board()
    canvas.bind("<Button-1>", handle_click)
    
    # 初期状態を履歴に保存
    save_state()
    
    draw_board()
    show_hint()
    
    def on_closing():
        root.destroy()
        sys.exit()
        
    root.protocol("WM_DELETE_WINDOW", on_closing)
    root.mainloop()

if __name__ == "__main__":
    create_board_ui()

次回はナンプレ(数独)のアプリを作成と動作確認を予定しています。楽しみにお待ちください。

ホーム » 脳内活性

いまさらながらのホームステイ(脳内活性)VOL6

脳内活性編に関しては、VOL4迄でご報告した通り”Sherlock:アイテム探し&マッチ3で事件捜査”をredkabagonが使用して実況を行うことができました。今回はSherlockと同じG5Entertainmentの提供する、pyramid of mahjongをplayして、その模様をyou tubuに動画をアップロードし、埋め込みリンクのご紹介いたします。

VOL2より登場の低スペックで動作可能なアプリと、書籍を1アイテムづつご紹介いたします。効果について現状我が家では嫁のredkabagonがアルバイト先で商品コードの間違え探しに役立っていると聞きました。。私は効果のほどを未だ実感できていません。しかしながら、続けることが結果予防になるのだと考えています。今回ご紹介する書籍については、私の父がトライしました。認知予防を意識している訳ではなく、日頃から遊び感覚で行っていた様です。最初は、新聞の少ない文字の記入のゲームから始まって、数式へと移り今では漢字へと変わっています。父親曰く、「面白いから」とのことですが、やはり楽しみながら認知予防した方が、長い間継続できるのではとおもいます。父がトライした中から、お勧めの書籍をリンクしておきます。

G5 Entertainmentを検索すると、ロシアで起業されウクライナにも分社されていると記載されています。昨今の事情を踏まえると、色々な意味合いで大勝負なのかと想像してしまいます。現在は本社がスウェーデンと表記されており、スパイ映画やドラマ好きな私としては、北欧の諜報活動の匂いがプンプンするなと思ってしまいます。

そんな危険性を感じる方は、アカウントを作成せずにplayすることをお勧めします。ゲームのアプリ毎に、ユーザーナンバーが当てはめられており、継続してロールプレイングできます。勿論課金はご法度かと。

スパイはさておき、本pyramid of mahjongは私でもクリアできるほどの簡単さを、初期の段階では示してくれます。内容は、同じカードを消して全面をクリアするか、王冠などの必須カードを消すことで次のゲームに進行できることになります。

ある程度の段階をクリアすると、画面上に映らない残されたカードの配置を読まないとクリアできなくなります。所謂メタ推理というやつです。先に消すべきカードを推理するゲームといえます。さて今回は、ルーティーンのアイテム獲得イベント(開催には諸条件がある。例えば毎日参加するなど。)を冒頭でお店します。カッコ書きにも記載していますが、今回の獲得イベントの参加条件とういうか状態は、期間限定のイベントとになります。プレイスポットに、イベント用の期間限定のタームが発生して、そのタームをクリアするとアイテムが貰える仕組みになっています。他にもいろいろなイベントがありますので参加してみてください。

その後、通常のタームを1ターム録画しています。合計の時間が約9分となっていますのでg了承くだい。尚我が家ではyou tubuのタイトルにもあるように、課金をせずにどこまでやれるのかがテーマになっています。皆様におかれましては、課金をする場合にはほどほどをお勧めいたします。

pyramid of mahjong

前回までは認知症についての個人の見解ををお話ししてきました。今回は、R60を間近に控えた私の個人のお話をしたいとおもいます。真っ先の挙げられるのが、体の衰えについてです。実は40歳を過ぎたあたりから、衰えを自覚していたような気がします。その当時は、水泳にいったり(年間温水)ウォーキングをしたりなどをしていました。私個人でいえば、衰えは見た目にすぐ出るものです。そして、精神的な部分も相当関係しているとおもいます。

その頃は個人事業を一度失敗して、他人の手を借りて持ち直しはじめた頃と重なっています。精神的に何が関係しているのかというと、(これはあくまで私個人の感想です)楽になると直ぐに気を抜くこととなり、生きるか死ぬかという精神状態と比較すると、差支えが殆どない日常になってしまう状態になます。結果的に、甘え切った日常が見た目の衰えを作ったのではないかと考えています。

流石にそのまずさに気づき引き締めを行うのですが、なかなか継続することができません。そこで当時考えたのが、ファッションから入るという手段です。丁度そのころゴールドウィンさんがnorthfaceのライセンスを日本で取得して、アパレル展開の認知度を上げていたころなので、スポーツショップには結構なプロモートをされていました。

ようやく立て直しが始まったばかりなのに贅沢するなよと、当時の自分を窘めたくなりますが、結局ファッションから入る作戦は私には効果があったようです。見た目はそれほどかわらなかったのですが、継続は凡そ3年は続いたとおもいます。他にもウォーキングする時のブランドはMELLET(ミレー)を使用するなど、お恥ずかしい話なのですが当時は結構それが楽しくて行っていました。見た目は殆ど引き締まっていないのですが。

そんな3年間を楽しく過ごした後、我が家の特徴である谷また谷に突入してしますのですが、この先は次回のお楽しみとさせていただきます。

PR TIMESさんのサイトより”認知症予防の脳トレWebゲーム『Dr.脳トレ』をリリース。”のページを引用しています

第三回目も海馬を鍛えるシリーズになります。先ずはゲストモードで試してみて、効果を感じた場合アカウントを作成する感じで手軽に始めることが出来ます。今回ご紹介した、”出現した順番に記号を選ぼう”は、更に難しくなったバージョンが前記の”Sherlock:アイテム探し&マッチ3で事件捜査”に登場します。

PCやスマホの操作が苦手という方に対しての書籍を紹介いたします。今回は、”ナンプレ”シリーズのご紹介です。実際父親が購入したことがあったり、プレゼントしたことがある書籍のなかから選んでします。期日までに正解を回答して、応募抽選により景品が貰える書籍も存在します。父親も数回応募したことがあり、商品券や図書券など頂いたことがあります。最近は、何故だか超難問に挑んでおり、殆どが期日を超えているのが現状ですが、本人曰く楽しいとのことなので、良しといております。

尚景品目当ての場合は、発売ご直かつ初心者用の書籍を選ぶことを父親がお勧めしておりました。後は、投稿終了期日に注意することだそうです。

実力番付ナンプレ250問
実力番付ナンプレ250問
ホーム » 脳内活性

いまさらながらのホームステイ(脳内活性)VOL5

脳内活性編に関しては、VOL4迄でご報告した通り”Sherlock:アイテム探し&マッチ3で事件捜査”をredkabagonが使用して実況を行うことができました。今回はSherlockと同じG5Entertainmentの提供する、pyramid of mahjongをplayして、その模様をyou tubuに動画をアップロードし、埋め込みリンクのご紹介いたします。

VOL2より登場の低スペックで動作可能なアプリと、書籍を1アイテムづつご紹介いたします。効果について現状我が家夫婦共々感じることができていません。しかしながら、続けることが結果予防になるのだと考えています。今回ご紹介する書籍については、私の父がトライしました。認知予防を意識している訳ではなく、日頃から遊び感覚で行っていた様です。最初は、新聞の少ない文字の記入のゲームから始まって、数式へと移り今では漢字へと変わっています。父親曰く、「面白いから」とのことですが、やはり楽しみながら認知予防した方が、長い間継続できるのではとおもいます。

G5 Entertainmentを検索すると、ロシアで起業されウクライナにも分社されていると記載されています。昨今の事情を踏まえると、色々な意味合いで大勝負なのかと想像してしまいます。現在は本社がスウェーデンと表記されており、スパイ映画やドラマ好きな私としては、北欧の諜報活動の匂いがプンプンするなと思ってしまいます。

そんな危険性を感じる方は、アカウントを作成せずにplayすることをお勧めします。ゲームのアプリ毎に、ユーザーナンバーが当てはめられており、継続してロールプレイングできます。勿論課金はご法度かと。

スパイはさておき、本pyramid of mahjongは私でもクリアできるほどの簡単さを、初期の段階では示してくれます。内容は、同じカードを消して全面をクリアするか、王冠などの必須カードを消すことで次のゲームに進行できることになります。

ある程度の段階をクリアすると、画面上に映らない残されたカードの配置を読まないとクリアできなくなります。所謂メタ推理というやつです。先に消すべきカードを推理するゲームといえます。今回は、全体を通して理解をしてもらえるように、21分という長めの時間をかけて録画しておりますので、ご容赦ください。

pyramid of mahjong

認知症を患った方を複数名知っています。進行度合いは人によってかなり変動しています。速く進行する方の特徴として、ご自身と家族が悲観してしまうことだけに時間を費やす傾向が見受けられます。ありうる現象の一つであるこは、ほぼ間違えありません。一方に於いて、認知症を患った方にスポットを当てると、喜怒哀楽は存在しています。認知前とツボが少し変わることもあるようですが、何がスイッチなのかを注視すると、ある程度の推測が可能となります。状態が把握できれば、喜びと楽しみのスイッチを押して挙げることができます。人によってツボが違うものの、笑うポイントを見つけ出せれば、それを提供できると日々が穏やかに進行するのではないかとおもいます。

PR TIMESさんのサイトより”認知症予防の脳トレWebゲーム『Dr.脳トレ』をリリース。”のページを引用しています

第三回目も海馬を鍛えるシリーズになります。先ずはゲストモードで試してみて、効果を感じた場合アカウントを作成する感じで手軽に始めることが出来ます。今回ご紹介した、”出現した順番に記号を選ぼう”は、更に難しくなったバージョンが前記の”Sherlock:アイテム探し&マッチ3で事件捜査”に登場します。

PCやスマホの操作が苦手という方に対しての書籍を紹介いたします。今回は、”ナンプレ”シリーズのご紹介です。実際父親が購入したことがあったり、プレゼントしたことがある書籍のなかから選んでします。期日までに正解を回答して、応募抽選により景品が貰える書籍も存在します。父親も数回応募したことがあり、商品券や図書券など頂いたことがあります。最近は、何故だか超難問に挑んでおり、殆どが期日を超えているのが現状ですが、本人曰く楽しいとのことなので、良しとしております。

尚景品目当ての場合は、発売ご直かつ初心者用の書籍を選ぶことを父親がお勧めしておりました。後は、投稿終了期日に注意することだそうです。

ナンプレメイトMini EXPERT
ナンプレメイトMini EXPERT
ホーム » 脳内活性

いまさらながらのホームステイ(脳内活性)VOL4

脳内活性編に関しては、VOL3でご報告した通り”Sherlock:アイテム探し&マッチ3で事件捜査”をredkabagonが使用して実況を行うことができました。今回は、VOL3より更に短いバージョンでその模様をyou tubuに動画をアップロードし、埋め込みリンクのご紹介いたします。

認知予防効果についてその三

VOL2より登場の低スペックで動作可能なアプリと、書籍を1アイテムづつご紹介いたします。効果について現状我が家夫婦共々感じることができていません。しかしながら、続けることが結果予防になるのだと考えています。今回ご紹介する書籍については、私がトライしました。認知予防というより脳を鍛える系の難しさを感じました。結果的には予防効果があるのではとおもっています。やり終えると、かなり疲れるというのが実感です。

Sherlock:アイテム探し&マッチ3で事件捜査その三

VOL3では、今回はショートバージョン(ワンターム分)をアップロードしてご紹介いたしました。更に今回は、ワンタームの中の1ゲーム分(時間制限が1ゲーム2分30で区切られています)をアップロードしてご紹介いたします。全体の操作方法を約30分、ワンタームの操作方法を約10分、1ゲームで約3分となります。

Sherlock:アイテム探し&マッチ3で事件捜査

楽しみながら老いていくその三

認知症を患った方を複数名知っています。進行度合いは人によってかなり変動しています。速く進行する方の特徴として、ご自身と家族が悲観してしまうことだけに時間を費やす傾向が見受けられます。ありうる現象の一つであるこは、ほぼ間違えありません。対照的に、進行がかなり遅い方もいらっしゃいます。専門職ではないことを前提に、進行が遅い方によく見受けられるのは、よく食べよく動きよく笑う傾向がありそうです。更に他者とよく話すと聞きます。加えて、ご家族が受け入れ拙いとおもわれがちな内容であっても、認知症を患う以前と同様な対応をしているといってらっしゃいました。どんなものでも構わないので、家族と分かち合える時間を大切にすることが、予防を含めて重要なんだろうとおもいます。

海馬を鍛える脳トレゲームその三

PR TIMESさんのサイトより”認知症予防の脳トレWebゲーム『Dr.脳トレ』をリリース。”のページを引用しています

数字を覚えて小さい順番に選ぶ脳トレ

第三回目も海馬を鍛えるシリーズになります。先ずはゲストモードで試してみて、効果を感じた場合アカウントを作成する感じで手軽に始めることが出来ます。タイトルこそ違え、この内容のゲームウォッチ友達が持っていた気がします。

アプリの操作が難しい方には

PCやスマホの操作が苦手という方に対しての書籍を紹介いたします。今回は、”脳を鍛える大人のドリル”シリーズの約2年後に購入した、岩波メソッド ゴースト暗算シリーズのご紹介です。”おさかなプレート””で有名なドリルです。私の体験談としては終了すると、頭の中がうねりまっくってかなり疲れます。認知予防というより、トレーニングと呼んだ方が相応しいかもしれません。

岩波メソッド ゴースト暗算
岩波メソッド ゴースト暗算
ホーム » 脳内活性

いまさらながらのホームステイ(脳内活性)VOL3

脳内活性編に関しては、VOL2でご報告した通り”Sherlock:アイテム探し&マッチ3で事件捜査”をredkabagonが使用して実況を行うことができました。今回は、短いバージョンでその模様をyou tubuに動画をアップロードし、埋め込みリンクのご紹介いたします。

認知予防効果についてその二

前回より登場の低スペックで動作可能なアプリと、書籍を1アイテムづつご紹介いたします。効果について現状我が家夫婦共々感じることができていません。しかしながら、続けることが結果予防になるのだと考えています。書籍については、私の父親がナンプレを愛用しています。もうそろそろ15経過します。主観的には、認知予防の効果があるんではなかろうかとおもいます。そのうち、リアルな体験として私の父親の経過を紹介できればとおもっています。

Sherlock:アイテム探し&マッチ3で事件捜査その二

前回の再生時間が30分超であったことを踏まえ、今回はショートバージョン(ワンターム分)をアップロードしています。色々なタームを一気に紹介するのがいいのか、ワンターム別に紹介するのがいいのか迷っています。試行錯誤するとおもわれますが、どうぞお付き合いください。

Sherlock:アイテム探し&マッチ3で事件捜査

楽しみながら老いていくその二

前回のご紹介は海馬を鍛える脳トレゲームでした。そして、ゲームウォッチ以上ファミコン未満だろうと表現しています。実際プレイしてみると、我らが世代のゲームウォッチの様といっても過言ではないとおもいます。当然主観な意見であることは間違えありませんが。懐かしい感覚を思い出しながら、ゲームをするとより認知予防になるのではないかと超個人的にはおもいます。

海馬を鍛える脳トレゲームその二

PR TIMESさんのサイトより”認知症予防の脳トレWebゲーム『Dr.脳トレ』をリリース。”のページを引用しています

パネルが出現した順番を記憶し選ぶ脳トレ

第二回目も海馬を鍛えるシリーズになります。先ずはゲストモードで試してみて、効果を感じた場合アカウントを作成する感じで手軽に始めることが出来ます。これぞゲームウォッチな感覚で楽しみながらゲームできそうです。

アプリの操作が難しい方には

PCやスマホの操作が苦手という方に対しての書籍を紹介いたします。前回の続きより当時川島隆太教授が監修した”脳を鍛える大人のドリル”シリーズのご紹介となります。買った当時から現在に至るまで、まだ効果を実感できていません。ならば、父親に試してもらおうと依頼したのですが、クイズ形式ではないので興味が湧かないとのことでした。どなたか、効果を体感した方がいらっしゃいましたら、情報共有させていただきたいものです。

川島隆太教授の脳を鍛える大人の音読ドリル
川島隆太教授の脳を鍛える大人の音読ドリル
ホーム » 脳内活性