Pygame を使ったナ oughts and crosses の作成

PythonPythonBeginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

このプロジェクトでは、Pygameを使ってナメコゲームを作成する手順を案内します。ナメコゲームは2人用のゲームで、横、縦、斜めのいずれかであなたの記号を3つ並べることが目的です。このプロジェクトでは、ゲームウィンドウを設定し、ゲーム盤を描画し、プレイヤーとAIの手番を処理し、勝者を決定する方法を学びます。このプロジェクトが終了すると、AI相手と対戦できる完全に機能するナメコゲームが完成します。

👀 プレビュー

Pygameを使ったナメコゲーム

🎯 タスク

このプロジェクトでは、以下を学びます。

  • プロジェクトファイルを作成し、必要なライブラリをインポートする方法
  • PyGameを初期化し、ゲームウィンドウを設定する方法
  • 記号、色、ゲーム状態を定義する方法
  • ボタンのプロパティを定義し、ヘルパー関数を作成する方法
  • メインゲームループを作成し、ヘルパー関数を実装する方法
  • メインゲームループ内の残りのコードを記入する方法

🏆 成果

このプロジェクトを完了すると、以下のことができるようになります。

  • Pygameを使ってグラフィカルゲームを作成する
  • Pygameを使ってウィンドウにグラフィックを描画する
  • ユーザー入力を処理し、ゲーム状態を更新する
  • 勝利条件のチェックなどのゲームロジックを実装する
  • ゲームを実行し続けるためのゲームループを作成する

プロジェクトファイルを作成する

まず、tic_tac_toe.py という名前の新しいファイルを作成します。好きなテキストエディタでそのファイルを開きます。

cd ~/project
touch tic_tac_toe.py
✨ 解答を確認して練習

必要なライブラリをインポートする

tic_tac_toe.py で、必要なライブラリをインポートします。pygamerandom です。これらのライブラリは、それぞれゲームグラフィックを処理したり、ランダムなAIの手を生成したりするために使用されます。

import pygame
import random

次のコマンドを使って pygame ライブラリをインストールします。

sudo pip install pygame
✨ 解答を確認して練習

PyGameを初期化してゲームウィンドウを設定する

tic_tac_toe.py で、pygame.init() を使ってPyGameを初期化します。その後、ウィンドウの幅と高さ、背景色、線の色、セルサイズを定義することでゲームウィンドウを設定します。また、指定された幅と高さのPyGameウィンドウを作成し、ウィンドウのキャプションを設定します。

pygame.init()

WIDTH = 600
HEIGHT = 600
BACKGROUND_COLOR = (40, 40, 40)
LINE_COLOR = (70, 70, 70)
CELL_SIZE = WIDTH // 3

win = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Tic-Tac-Toe")
✨ 解答を確認して練習

記号と色を定義する

tic_tac_toe.py で、プレイヤーとAI用の記号と色を定義します。これらの記号と色は、ゲーム盤上にプレイヤーとAIの手を描画する際に使用されます。

PLAYER_SYMBOL = "X"
AI_SYMBOL = "O"
PLAYER_COLOR = (0, 255, 0)
AI_COLOR = (255, 0, 0)
EMPTY_COLOR = (0, 0, 0)
✨ 解答を確認して練習

ゲーム状態を定義する

tic_tac_toe.py で、初期のゲーム状態を定義します。これには、ゲーム盤、現在の手番(「player」または「ai」)、ゲームが終了したかどうかを示すフラグ、およびゲームの勝者が含まれます。

board = [["" for _ in range(3)] for _ in range(3)]
turn = "player"
game_over = False
winner = None
✨ 解答を確認して練習

ボタンのプロパティを定義する

tic_tac_toe.py で、リセットボタンのプロパティを定義します。これには、ボタンの幅、高さ、色、文字色、およびフォントサイズが含まれます。また、pygame.Rect クラスを使って reset_button_rect オブジェクトを作成し、ボタンの位置とサイズを表します。

BUTTON_WIDTH = 200
BUTTON_HEIGHT = 50
BUTTON_COLOR = (50, 50, 50)
BUTTON_TEXT_COLOR = (255, 255, 255)
BUTTON_FONT = pygame.font.Font(None, 30)

reset_button_rect = pygame.Rect(
    (WIDTH - BUTTON_WIDTH) // 2,
    (HEIGHT - BUTTON_HEIGHT) // 2,
    BUTTON_WIDTH,
    BUTTON_HEIGHT,
)
✨ 解答を確認して練習

ヘルパー関数を作成する

tic_tac_toe.py で、ゲーム全体で使用されるいくつかのヘルパー関数を定義します。

  • draw_board():この関数は、ゲーム盤をウィンドウに描画します。

  • draw_symbols():この関数は、ゲーム盤上にプレイヤーとAIの記号を描画します。

  • is_board_full():この関数は、ゲーム盤が埋まっているかどうかを確認します。

  • is_winner():この関数は、あるプレイヤーがゲームに勝利したかどうかを確認します。

  • make_move():この関数は、ゲーム盤上に手を打ちます。

  • player_move():この関数は、プレイヤーの手番を処理します。

  • ai_move():この関数は、AIの手番を処理します。

  • check_game_over():この関数は、ゲームが終了したかどうかを確認します。

  • draw_winner():この関数は、勝者のメッセージをウィンドウに描画します。

  • draw_reset_button():この関数は、リセットボタンをウィンドウに描画します。

  • reset_game():この関数は、ゲーム状態をリセットします。

## ヘルパー関数
def draw_board():
    ## ゲーム盤を描画する
    pass

def draw_symbols():
    ## ゲーム盤上にプレイヤーとAIの記号を描画する
    pass

def is_board_full():
    ## ゲーム盤が埋まっているかどうかを確認する
    pass

def is_winner(symbol):
    ## あるプレイヤーがゲームに勝利したかどうかを確認する
    pass

def make_move(x, y, symbol):
    ## ゲーム盤上に手を打つ
    pass

def player_move():
    ## プレイヤーの手番を処理する
    pass

def ai_move():
    ## AIの手番を処理する
    pass

def check_game_over():
    ## ゲームが終了したかどうかを確認する
    pass

def draw_winner():
    ## 勝者のメッセージをウィンドウに描画する
    pass

def draw_reset_button():
    ## リセットボタンをウィンドウに描画する
    pass

def reset_game():
    ## ゲーム状態をリセットする
    pass
✨ 解答を確認して練習

メインゲームループを作成する

tic_tac_toe.py で、while ループを使ってメインゲームループを作成します。このループは、ユーザーがゲームウィンドウを閉じるまで実行されます。ゲームループの中で、ユーザーの入力イベントを処理し、それに応じてゲーム状態を更新します。

## メインゲームループ
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if reset_button_rect.collidepoint(event.pos):
                reset_game()
            elif not game_over and turn == "player":
                player_move()

    if not game_over and turn == "ai":
        ai_move()
        check_game_over()

    draw_board()
    draw_symbols()

    if game_over:
        draw_winner()
        draw_reset_button()

    pygame.display.flip()

## ゲーム終了
pygame.quit()
✨ 解答を確認して練習

ヘルパー関数を実装する

さて、先ほど定義したヘルパー関数を実装しましょう。まずは draw_board() 関数を完成させます。この関数は、pygame.draw.line() 関数を使って垂直線と水平線を描画することで、ゲーム盤をウィンドウに描画します。

## ヘルパー関数
def draw_board():
    win.fill(BACKGROUND_COLOR)

    ## 垂直線を描画する
    for x in range(1, 3):
        pygame.draw.line(
            win, LINE_COLOR, (CELL_SIZE * x, 0), (CELL_SIZE * x, HEIGHT), 2
        )

    ## 水平線を描画する
    for y in range(1, 3):
        pygame.draw.line(win, LINE_COLOR, (0, CELL_SIZE * y), (WIDTH, CELL_SIZE * y), 2)
✨ 解答を確認して練習

残りのヘルパー関数を実装する

次に、残りのヘルパー関数:draw_symbols()is_board_full()is_winner()make_move()player_move()ai_move()check_game_over()draw_winner()draw_reset_button()、およびreset_game()を実装します。

## ヘルパー関数
def draw_symbols():
    for x in range(3):
        for y in range(3):
            symbol = board[x][y]
            if symbol == PLAYER_SYMBOL:
                color = PLAYER_COLOR
            elif symbol == AI_SYMBOL:
                color = AI_COLOR
            else:
                color = EMPTY_COLOR
            if symbol!= "":
                pygame.draw.circle(
                    win,
                    color,
                    (x * CELL_SIZE + CELL_SIZE // 2, y * CELL_SIZE + CELL_SIZE // 2),
                    CELL_SIZE // 2 - 10,
                    2,
                )

def is_board_full():
    for row in board:
        if "" in row:
            return False
    return True

def is_winner(symbol):
    for row in board:
        if all(cell == symbol for cell in row):
            return True
    for col in range(3):
        if all(board[row][col] == symbol for row in range(3)):
            return True
    if all(board[i][i] == symbol for i in range(3)):
        return True
    if all(board[i][2 - i] == symbol for i in range(3)):
        return True
    return False

def make_move(x, y, symbol):
    if board[x][y] == "":
        board[x][y] = symbol
        return True
    return False

def player_move():
    global turn
    mouse_pos = pygame.mouse.get_pos()
    cell_x = mouse_pos[0] // CELL_SIZE
    cell_y = mouse_pos[1] // CELL_SIZE

    if make_move(cell_x, cell_y, PLAYER_SYMBOL):
        turn = "ai"

def ai_move():
    global turn
    empty_cells = []
    for x in range(3):
        for y in range(3):
            if board[x][y] == "":
                empty_cells.append((x, y))

    if empty_cells:
        x, y = random.choice(empty_cells)
        make_move(x, y, AI_SYMBOL)

    turn = "player"

def check_game_over():
    global game_over, winner
    if is_winner(PLAYER_SYMBOL):
        game_over = True
        return "player"
    elif is_winner(AI_SYMBOL):
        game_over = True
        return "ai"
    elif is_board_full():
        game_over = True
        return "tie"
    return None

def draw_winner():
    font = pygame.font.Font(None, 50)
    if winner == "player":
        text = font.render("Player Wins!", True, PLAYER_COLOR)
    elif winner == "ai":
        text = font.render("AI Wins!", True, AI_COLOR)
    else:
        text = font.render("It's a Tie!", True, (255, 255, 255))
    text_rect = text.get_rect(center=(WIDTH // 2, HEIGHT // 3))
    win.blit(text, text_rect)

def draw_reset_button():
    pygame.draw.rect(win, BUTTON_COLOR, reset_button_rect)
    button_text = BUTTON_FONT.render("Reset", True, BUTTON_TEXT_COLOR)
    button_text_rect = button_text.get_rect(center=reset_button_rect.center)
    win.blit(button_text, button_text_rect)

def reset_game():
    global board, turn, game_over, winner
    board = [["" for _ in range(3)] for _ in range(3)]
    turn = "player"
    game_over = False
    winner = None

上記のコードでは、draw_symbols()関数が盤面に記号を描画します。is_board_full()関数が盤面が埋まっているかどうかを確認します。is_winner()関数が与えられた記号がゲームに勝利したかどうかを確認します。make_move()関数が盤面に手を打ちます。player_move()関数がプレイヤーの手番を処理します。ai_move()関数がAIの手番を処理します。check_game_over()関数がゲームが終了したかどうかを確認します。draw_winner()関数が勝者のメッセージを描画します。draw_reset_button()関数がリセットボタンを描画します。reset_game()関数がゲームをリセットします。

✨ 解答を確認して練習

残りのコードを埋める

最後に、メインゲームループ内の残りのコードを埋めて、適切な場所でヘルパー関数を呼び出します。これには、ゲーム盤と記号を描画するためのdraw_board()draw_symbols()関数を呼び出すこと、ゲームが終了したかどうかを確認するためのcheck_game_over()関数を呼び出すこと、そして勝者メッセージとリセットボタンをそれぞれ描画するためのdraw_winner()draw_reset_button()関数を呼び出すことが含まれます。

## メインゲームループ
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if reset_button_rect.collidepoint(event.pos):
                reset_game()
            elif not game_over and turn == "player":
                player_move()

    if not game_over and turn == "ai":
        ai_move()
        winner = check_game_over()

    draw_board()
    draw_symbols()

    if game_over:
        draw_winner()
        draw_reset_button()

    pygame.display.flip()

## ゲーム終了
pygame.quit()

以下のコマンドを使用してゲームを実行します。

python tic_tac_toe.py
tic tac toe game screenshot
✨ 解答を確認して練習

まとめ

おめでとうございます!あなたはPygameを使ってナoughts and crossesゲームを成功裏に作成しました。このプロジェクトでは、ゲームウィンドウを設定し、ゲーム盤を描画し、プレイヤーとAIの手番を処理し、勝者を決定する方法を学びました。また、コードを簡素化してよりモジュール化するためのヘルパー関数を実装する方法も学びました。