【pygame|Extra3】オセロ(リバーシ)を作ろう

【Pygame入門編】
Chapter1:pygame入門|画面を表示しよう
Chapter2:簡単なノベルゲームを作ろう
Chapter3:簡単なアクションゲームを作ろう
【Pygame実践編】
Extra1:ブロック崩しを作ろう
Extra2:シューティングゲームを作ろう
Extra3:オセロ(リバーシ)を作ろう ◁今回はここ
Extra4:ナインゲームを作ろう
Extra5:横スクロールのアクションゲームを作ろう
本記事では、オセロ(リバーシ)のサンプルコードを公開します。
これまでのチャプターで学んだpygameの知識を活かし、本格的なゲーム制作に挑戦できる内容です。



なお、ゲームコードの詳しいコードの解説は、記事内では行いません。
コード内に各処理のポイントをコメントとして詳しく記載していますので、そちらを参考に読み進めてください。
あなたの手でさらに拡張していける内容となっていますので、サンプルを気に入った方はぜひフルバージョンのご購入もご検討ください!
オセロ(リバーシ)の概要
オセロ(またはリバーシ)は、白と黒の石を交互に置き、相手の石を自分の石で挟むことで裏返していくボードゲームです。
最終的に盤上の石が多い方が勝ちという、シンプルながら戦略性の高いゲームです。
Pygame でオセロを作ると、ゲーム開発の基本要素をバランスよく学ぶことができます。
たとえば以下のような技術要素が自然に身につきます👇
- 2次元配列(リスト)で盤面を管理する方法
- マウス入力の処理(クリックしたマスの特定)
- 画面描画の制御(マス目・石・ボタンの描画)
- ゲームループとシーン管理(スタート/対戦/結果の切り替え)
- 簡単なCPUロジックの実装(合法手からランダム選択)
オセロはルールが明確で、「状態の更新」と「描画の反映」が分かりやすいゲームなので、Pygame の学習題材として非常に優れています。
この記事では、実際に動くオセロゲームを作りながら、Pygame の基本構造を理解することを目指します。
オセロゲームのファイル構成
オセロゲームのファイル構成は以下のようになっています。
Othello/ ├── main.py # ゲーム全体の起動・メインループ・シーン制御 │ └── osero_lib/ # オセロ専用ライブラリ群 ├── __init__.py # パッケージ初期化用(空ファイル) ├── board.py # 盤面の生成と初期配置設定 ├── config.py # 各種設定(色・サイズ・フォントなど) ├── draw.py # 盤面・石・文字・ボタンなどの描画関数 ├── logic.py # ゲームロジック(置ける判定・反転・勝敗判定) ├── player.py # プレイヤー(人間/CPU)の管理 ├── start_result.py # スタート画面・結果画面の描画とボタン処理 └── units.py # 汎用関数(石のカウントなど補助処理)
各チャプターの学習記事では全てを1つのコード内に書いてきましたが、こちらはPythonのオブジェクト指向を活用し、役割毎に分けています。
こうすることにより各コードの内容が分かりやすくなり、また修正する際にもポイントを探しやすくなっています。
この中の一つ、「logic.py」のコードを先に公開します。
正規版の各コードにどのような解説コメントが書かれているかをご確認下さい。
- サンプルコード:logic.py
-
logic.pyは、オセロのルールに基づくゲームロジックを処理するモジュールです。
# ============================================== # logic.py # ---------------------------------------------- # オセロのルールに基づくゲームロジックを処理するモジュール。 # 有効手の判定、石の反転、盤面の満杯判定、勝敗判定などを行う。 # ============================================== from osero_lib import config # 石を置いたときに調べる8方向を定義したリスト。 # それぞれ (x方向, y方向) を表す。 # 例:(-1, 0) は「左」、(1, 1) は「右下」方向。 DIRECTIONS = [(-1,-1), (-1,0), (-1,1), # 左上、左、左下 (0,-1), (0,1), # 上、 下 (1,-1), (1,0), (1,1)] # 右上、右、右下 # 指定したマス (x, y) に石を置けるかどうかを判定する関数。 # 「相手の石を1つ以上挟んで自分の石にできる」なら True を返す。 def is_valid_move(board, x, y, color): if board[x][y] is not None: # すでに石があるマスには置けない return False # 自分の色に応じて相手の色を決める opponent = config.WHITE if color == config.BLACK else config.BLACK # 8方向すべてに対して調べる for dx, dy in DIRECTIONS: nx, ny = x + dx, y + dy # 次に調べるマスの位置 found_opponent = False # 間に相手の石があるかを記録するフラグ # 盤面の範囲内で、同じ方向に1マスずつ進みながら調べる while 0 <= nx < config.BOARD_SIZE and 0 <= ny < config.BOARD_SIZE: if board[nx][ny] == opponent: # 相手の石があれば進み続ける found_opponent = True elif board[nx][ny] == color and found_opponent: return True # 自分の石で挟めていれば置ける else: break # 空マスや端に来たらその方向は終了 nx += dx ny += dy return False # どの方向でも挟めなければ置けない # 石を置いたときに、相手の石を自分の色にひっくり返す関数。 # 8方向すべてを調べて、挟まれた相手の石を順に反転させる。 def flip_stones(board, x, y, color): # 自分の色に応じて相手の色を決定 opponent = config.WHITE if color == config.BLACK else config.BLACK # 8方向すべてをチェック for dx, dy in DIRECTIONS: stones_to_flip = [] # この方向で裏返す石を一時的に記録しておくリスト nx, ny = x + dx, y + dy # まずは隣のマスから調べ始める # 盤面の範囲内で進みながらチェック while 0 <= nx < config.BOARD_SIZE and 0 <= ny < config.BOARD_SIZE: if board[nx][ny] == opponent: # 相手の石なら、裏返し候補に追加 stones_to_flip.append((nx, ny)) elif board[nx][ny] == color: # 自分の石に当たった場合 # 間にある相手の石をすべて自分の色に変える for fx, fy in stones_to_flip: board[fx][fy] = color break # この方向の処理を終了 else: break # 空マスや範囲外なら何もせず終了 nx += dx # 次のマスへ進む ny += dy # 指定されたマス (x, y) に石を置き、反転処理を行う関数。 # 「石を置く」と「裏返す」をまとめて実行する。 def place_stone(board, x, y, color): board[x][y] = color # そのマスに自分の石を置く flip_stones(board, x, y, color) # 周囲の相手の石をひっくり返す # 盤面がすべて埋まっているかを調べる関数。 # 空マス(None)が1つもなければ True を返す。 def is_board_full(board): return all(None not in row for row in board) # 各行にNoneが含まれていないか確認 # 指定したプレイヤー(色)が、どこかに置ける場所を持っているかを調べる関数。 # 1つでも有効な手があれば True を返す。 def has_valid_move(board, color): return any(is_valid_move(board, x, y, color) # どのマスか1つでも置ける場所があるかをチェック for x in range(config.BOARD_SIZE) for y in range(config.BOARD_SIZE)) # 盤面上の石の数を数えて、どちらが勝ったかを判定する関数。 # 黒が多ければ「Black Wins!」、白が多ければ「White Wins!」、同数なら「Draw!」を返す。 def judge_winner(board): black = sum(row.count(config.BLACK) for row in board) # 各行の黒い石の数を合計 white = sum(row.count(config.WHITE) for row in board) # 各行の白い石の数を合計 if black > white: # 黒の石が多いとき return "Black Wins!" elif white > black: # 白の石が多いとき return "White Wins!" return "Draw!" # 同じ数なら引き分け
ゲームコードのダウンロードはこちら
こちらから、オセロ(リバーシ)の全コードをダウンロードできます。
ダウンロードファイルにはソースコード一式と画像一式、そして詳しい解説コメントが含まれています。
ここからは有料記事です。どこよりも安いこの教材を、是非ご利用下さい^^
PDF等でダウンロードする場合は こちら から購入(会員登録不要)。
このサイト内で読み進める場合は↓↓から会員登録してください。
すでに購入済みの方はこちら


