オセロ作ってみた　#100日チャレンジに感化されて

#### 今日はオセロ作ってみた
GW後半戦突入〜！制作頑張ろう

![othell.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668168/f107f506-9438-497d-849a-0df59878f3c8.gif)

```python
import pygame
import sys
import random

pygame.init()

#初期画面設定
size = 8
cell_size = 60
board_size = size * cell_size
window = pygame.display.set_mode((board_size, board_size))
#ゲームウィンドウを作成するための関数
#pygame.display.set_mode((幅，　高さ))

pygame.display.set_caption("オセロ")

#色の設定
green = (0,255,0)
black = (0,0,0)
white = (255,255,255)

#ゲーム盤の状態
#初期は「0」　黒の碁を置いたら，「1」 白の碁を置いたら「2」
board = [[0 for _ in range(size)] for _ in range(size)]

#boardの中央に，碁石を置く
board[3][4] = board[4][3] = 1
board[3][3] = board[4][4] = 2

player = 1

# 8方向
directions = [(-1,-1), (-1,0), (-1,1), (0,-1), (0,1), (1,-1), (1,0), (1,1)]

def is_valid_move(x, y, player):
    if board[y][x] != 0:
        return False
    opponent = 3 - player
    for dx, dy in directions:
        nx, ny = x + dx, y + dy
        has_opponent_between = False
        while 0 <= nx < size and 0 <= ny < size:
            if board[ny][nx] == opponent:
                has_opponent_between = True
            elif board[ny][nx] == player:
                if has_opponent_between:
                    return True
                else:
                    break
            else:
                break
            nx += dx
            ny += dy
    return False

def get_valid_moves(player):
    return [(x, y) for y in range(size) for x in range(size) if is_valid_move(x, y, player)]

def place_disc(x, y, player):
    board[y][x] = player
    opponent = 3 - player
    for dx, dy in directions:
        nx, ny = x + dx, y + dy
        discs_to_flip = []
        while 0 <= nx < size and 0 <= ny < size:
            if board[ny][nx] == opponent:
                discs_to_flip.append((nx, ny))
            elif board[ny][nx] == player:
                for fx, fy in discs_to_flip:
                    board[fy][fx] = player
                break
            else:
                break
            nx += dx
            ny += dy

def draw_board():
    window.fill(green)
    for x in range(size):
        for y in range(size):
            rect = pygame.Rect(x * cell_size, y * cell_size, cell_size, cell_size)
            pygame.draw.rect(window, black, rect, 1)
            if board[y][x] == 1:
                pygame.draw.circle(window, black, rect.center, cell_size // 2 - 5)
            elif board[y][x] == 2:
                pygame.draw.circle(window, white, rect.center, cell_size // 2 - 5)
    pygame.display.update()

def cpu_move():
    moves = get_valid_moves(2) #CPUはplayer=2と仮定
    if moves:
        x, y = random.choice(moves)
        place_disc(x, y, 2)

def count_discs():
    black_count = sum(row.count(1) for row in board)
    white_count = sum(row.count(2) for row in board)
    return black_count, white_count

def show_result_and_restart():
    black_count, white_count = count_discs()
    if black_count > white_count:
        result_text = f"winner! {black_count} vs {white_count}"
    elif white_count > black_count:
        result_text = f"loss... {white_count} vs {black_count}"
    else:
        result_text = f"draw... {black_count} vs {white_count}"

    font = pygame.font.SysFont("arial", 36)
    button_font = pygame.font.SysFont("arial", 28)
    window.fill(green)

    text_surface = font.render(result_text, True, black, white)
    text_rect = text_surface.get_rect(center=(board_size // 2, board_size // 2 - 60))
    window.blit(text_surface, text_rect)

    button_rect = pygame.Rect(board_size // 2 - 80, board_size // 2 + 20, 160, 50)
    pygame.draw.rect(window, white, button_rect)
    pygame.draw.rect(window, black, button_rect, 2)
    button_text = button_font.render("restart", True, black)
    button_text_rect = button_text.get_rect(center=button_rect.center)
    window.blit(button_text, button_text_rect)

    pygame.display.update()
    waiting = True
    while waiting:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()
            elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                if button_rect.collidepoint(event.pos):
                    restart_game()
                    waiting = False
                    
def restart_game():
    global board, player, cpu_pending, cpu_timer
    board = [[0 for _ in range(size)] for _ in range(size)]
    board[3][4] = board[4][3] = 1
    board[3][3] = board[4][4] = 2
    player = 1

cpu_pending = False
cpu_timer = 0

# --- メインループ ---
running = True
while running:
    draw_board()

    now = pygame.time.get_ticks()
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            if not cpu_pending:
                
                mx, my = pygame.mouse.get_pos()
                x, y = mx // cell_size, my // cell_size
                if is_valid_move(x, y, 1):
                    place_disc(x, y, 1)
                    
                    if get_valid_moves(2): #CPUに手があるなら
                        cpu_pending = True
                        cpu_timer = now + 500 #1秒後
                    elif not get_valid_moves(1) and not get_valid_moves(2):
                        running = False

        if cpu_pending and now>= cpu_timer:
            cpu_move()
            cpu_pending = False
            
            while not get_valid_moves(1) and get_valid_moves(2):
                pygame.time.delay(500)
                cpu_move()
                
        if not get_valid_moves(1) and not get_valid_moves(2):
            draw_board()
            show_result_and_restart()
```

気に入ったらいいね👍してね！