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

🎯 タスク
このプロジェクトでは、以下を学びます。
- プロジェクトファイルを作成し、必要なライブラリをインポートする方法
- PyGame を初期化し、ゲームウィンドウを設定する方法
- 記号、色、ゲーム状態を定義する方法
- ボタンのプロパティを定義し、ヘルパー関数を作成する方法
- メインゲームループを作成し、ヘルパー関数を実装する方法
- メインゲームループ内の残りのコードを記入する方法
🏆 成果
このプロジェクトを完了すると、以下のことができるようになります。
- Pygame を使ってグラフィカルゲームを作成する
- Pygame を使ってウィンドウにグラフィックを描画する
- ユーザー入力を処理し、ゲーム状態を更新する
- 勝利条件のチェックなどのゲームロジックを実装する
- ゲームを実行し続けるためのゲームループを作成する
プロジェクトファイルを作成する
まず、tic_tac_toe.py という名前の新しいファイルを作成します。好きなテキストエディタでそのファイルを開きます。
cd ~/project
touch tic_tac_toe.py
必要なライブラリをインポートする
tic_tac_toe.py で、必要なライブラリをインポートします。pygame と random です。これらのライブラリは、それぞれゲームグラフィックを処理したり、ランダムな 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

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



