ChatGPTの試し(オセロ)

■ChatGPTを試してみる。
以前から生成AIについて興味があったので、強化学習の勉強の箸休めとしてどんなものか試してみた。
無料版は使えるそうなので、それでオセロのコードを出力させてみた。他にPlus、Pro(現時点でUS$20/月, 200/月)の有料版がある。
Googleのアカウントでログインでき、すぐに使い始められた。


上の画面から質問を入れるだけ。
まず「Pythonで作るCUIのオセロのコードを教えて」と入力すると対戦型のオセロのコードが出てきた。その後に、「Pythonで作るCUIのオセロのコードで、コンピュータと対戦のものを教えて」とすると、出力されたコードが改良されて下のものになった。この間、10秒程度。

import numpy as np
import random

def initialize_board():
    board = np.zeros((8, 8), dtype=int)
    board[3, 3], board[3, 4] = 1, -1
    board[4, 3], board[4, 4] = -1, 1
    return board

def print_board(board):
    symbols = {1: '●', -1: '○', 0: '.'}
    print("  " + " ".join(map(str, range(8))))
    for i, row in enumerate(board):
        print(i, " ".join(symbols[cell] for cell in row))

def is_valid_move(board, row, col, player):
    if board[row, col] != 0:
        return False
    directions = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
    opponent = -player
    for dr, dc in directions:
        r, c = row + dr, col + dc
        if 0 <= r < 8 and 0 <= c < 8 and board[r, c] == opponent:
            while 0 <= r < 8 and 0 <= c < 8:
                if board[r, c] == 0:
                    break
                if board[r, c] == player:
                    return True
                r += dr
                c += dc
    return False

def get_valid_moves(board, player):
    return [(r, c) for r in range(8) for c in range(8) if is_valid_move(board, r, c, player)]

def apply_move(board, row, col, player):
    board[row, col] = player
    directions = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
    opponent = -player
    for dr, dc in directions:
        r, c = row + dr, col + dc
        flips = []
        while 0 <= r < 8 and 0 <= c < 8 and board[r, c] == opponent:
            flips.append((r, c))
            r += dr
            c += dc
        if 0 <= r < 8 and 0 <= c < 8 and board[r, c] == player:
            for fr, fc in flips:
                board[fr, fc] = player

def computer_move(board, player):
    moves = get_valid_moves(board, player)
    if moves:
        return random.choice(moves)
    return None

def play_game():
    board = initialize_board()
    player = 1
    while True:
        print_board(board)
        moves = get_valid_moves(board, player)
        if not moves:
            if not get_valid_moves(board, -player):
                break
            player = -player
            continue

        if player == 1:
            row, col = map(int, input(f"Player ●, enter row and column: ").split())
        else:
            row, col = computer_move(board, player)
            print(f"Computer ○ chooses: {row}, {col}")

        if (row, col) in moves:
            apply_move(board, row, col, player)
            player = -player
        else:
            print("Invalid move. Try again.")

    print("Game over!")
    print_board(board)
    count = np.sum(board)
    if count > 0:
        print("Winner: ●")
    elif count < 0:
        print("Winner: ○")
    else:
        print("It's a draw!")

if __name__ == "__main__":
    play_game()

コンピュータの配置はランダム。プレイヤー側の入力の仕方が初め分からなかったけど、1ゲーム最後まで問題なく実行できた。置いていない部分が半角の「.」で表現されているため多少ずれているけど(下が実行画面)、追加で質問なりすれば修正されるのではと思う。


以前自分で考えたコードよりすっきりしている。勝ち負けの判定も自分の石を+1、置いていない部分を0、相手の石を-1として、ボード上の全ての和から判定しており、なるほどと思った。

出てきたアウトプットを理解せずそのまま使うということも起こってそうだけど、健全な使い方を考えるなら、まずはアイデアを出すために使ったり、ChatGPTでドラフトを作ってそれをレビューして成果物を作るといったあたりかな。