AOYAMA Koji's プログラミングブログ - プログラミングを楽しく体験

【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】プログラミング初心者向け・入門編・基礎編初中級者向けプログラミング解説プログラマー向け実装解説[初心者向けゲーム開発入門]

2026/06/15
【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門]

 40年以上のゲームプログラミング経験をマンガで可視化。 今回は「ゲームオーバー」。 ゲームの終了判定(ゲームクリアやゲームオーバー)を含む、ゲーム終了処理です。
【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門]

プログラミングブログ記事一覧


[PR]

【マンガで感じる】ゲームオーバー ~ゲーム終了処理~


【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 社長 ダーツ投げ 無邪気 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] クリスタル ダーツ投げ プロ風 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 省略コマ 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 盤面 XO. OX. XOO 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 社長「X(私)の手番ですね」 クリスタル控える 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 社長「えいっ!」 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 壁の盤面(Dはダーツ) XOD OX. XOO 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 省略コマ 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 盤面 XOX OX. XOO (社長)「3つ並んだ!」 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 社長「やりましたぞ!」ガッツポーズ 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 社長「・・・」ガッツポーズのまま無言 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 社長「?」ガッツポーズのままきょろきょろ 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 社長「!」理解 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 社長「勝敗判定をお願いします」 クリスタル「承知しました」 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] ゲームオーバー ~ゲーム終了処理~ 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] メカ・ゲームオーバー登場 (クリスタル)「メカ・ゲームオーバー」「ゲーム終了判定と終了処理をお願い」 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] メカ・ロジック[メカ・ロジック]了解 (クリスタル)「ゲームロジック用データは」「ロジックに見せてもらって」 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 盤面 XOX OX. XOO 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] メカ・ロジック タブレットを見せる メカ・ゲームオーバー メカ・ロジックのタブレットを覗き込む 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] タブレット画面(OXとインデックス数値は薄い、012は小さく濃い) XOX 012 212 OX. 345 120 XOO 678 211 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] メカ・ゲームオーバー 真剣にタブレットを見ている 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] メカ・ゲームオーバー「!」発見 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] タブレット画面(OXとインデックス数値は薄い、012は小さく濃い、*線) XOX 012 212 ..* OX. 345 120 .*. XOO 678 211 *.. 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] メカ・ゲームオーバー「Xの勝ちです!」 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] メカ・ゲームオーバー右へ走る 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] メカ・ゲームオーバー 金メダルをかける 社長 金メダルをかけてもらう 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] クリスタル「社長、まいりました」「おめでとうございます」ホッとした表情でおじぎ 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] メカたち「おめでとうございます!」 【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 社長 金メダルをして自慢顔 丸枠 ~OXゲーム開発編 クリア~
次のエピソードへ
【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 交換

OXゲーム開発編 第10話:エピソード「ゲームオーバー」


 本エピソード「ゲームオーバー」は、OXゲーム開発編 第10話です。
 OXゲーム開発編は、OXゲーム(三目並べ・マルバツ)の開発を通じて、ゲームプログラミングの基礎の基礎を解説しています。
 OXゲーム開発編の各エピソードは、それまでのエピソードのマンガ(と解説)を前提としていますので、 もし途中から読み始めた方は、ぜひ最初のエピソード「プログラム」から読み進めてください。

「ゲームオーバー」のソースコード例


JavaScript

//**********************************************************************
// 勝利判定(3マス指定)
//   引数:
//     iPlayerNumber: プレイヤー番号
//     iIndex0,1,2:   盤面のマス位置インデックス
//**********************************************************************
function areAllSamePlayer( iPlayerNumber , iIndex0 , iIndex1 , iIndex2 ) {
    // 3マスすべてが指定プレイヤー番号か
    return (
        aiSquare[iIndex0] === iPlayerNumber &&
        aiSquare[iIndex1] === iPlayerNumber &&
        aiSquare[iIndex2] === iPlayerNumber
    );
}
//********************************************************************** // 勝利判定 // 引数: // iPlayerNumber: プレイヤー番号 //********************************************************************** function isWin( iPlayerNumber ) { // 指定のプレイヤー番号が3つライン上に並んでいるマスがあるか return ( // 左上・中上・右上 areAllSamePlayer( iPlayerNumber , 0 , 1 , 2 ) || // 左中・中中・右中 areAllSamePlayer( iPlayerNumber , 3 , 4 , 5 ) || // 左下・中下・右下 areAllSamePlayer( iPlayerNumber , 6 , 7 , 8 ) || // 左上・左中・左下 areAllSamePlayer( iPlayerNumber , 0 , 3 , 6 ) || // 中上・中中・中下 areAllSamePlayer( iPlayerNumber , 1 , 4 , 7 ) || // 右上・右中・右下 areAllSamePlayer( iPlayerNumber , 2 , 5 , 8 ) || // 左上・中中・右下 areAllSamePlayer( iPlayerNumber , 0 , 4 , 8 ) || // 右上・中中・左下 areAllSamePlayer( iPlayerNumber , 2 , 4 , 6 ) ); }
//********************************************************************** // 勝利プレイヤー表示 // 引数: // iPlayerNumber: プレイヤー番号 //********************************************************************** function alertWin( iPlayerNumber ) { if ( 1 === iPlayerNumber ) { alert( 'Oの勝ちです!' ); } else { alert( 'Xの勝ちです!' ); } }
//********************************************************************** // ゲーム終了判定と処理 // 引数: // iPlayerNumber: プレイヤー番号 //********************************************************************** // 勝利しているか if ( isWin( iPlayerNumber ) ) { // 勝利プレイヤー表示 alertWin( iPlayerNumber ); }

OXゲーム(三目並べ・マルバツ):勝敗判定とゲーム終了処理「ゲームオーバー」実装検証



[PR]

「ゲームオーバー」とは:ゲーム終了処理


 「ゲームオーバー」の本質「ゲーム終了処理」です。
 勝敗が決しているかなどの終了判定を行い、終了していれば、ゲームクリアゲームオーバーの処理をします。
 ゲームオーバーは敵にやられるなどして終了することを指す場合が多いですが、 通常のゲーム終了も意味します。

ソースコードの仕組み


 今回のプログラムは、以下のような構造になっています。

関数定義:勝利判定(3マス指定)

//**********************************************************************
// 勝利判定(3マス指定)
//   引数:
//     iPlayerNumber: プレイヤー番号
//     iIndex0,1,2:   盤面のマス位置インデックス
//**********************************************************************
function areAllSamePlayer( iPlayerNumber , iIndex0 , iIndex1 , iIndex2 ) {
 まず、指定された3マス分の勝利判定を行う関数 areAllSamePlayer を定義します。


勝利判定(3マス)

// 3マスすべてが指定プレイヤー番号か
return (
    aiSquare[iIndex0] === iPlayerNumber &&
    aiSquare[iIndex1] === iPlayerNumber &&
    aiSquare[iIndex2] === iPlayerNumber
);
 関数 areAllSamePlayer の中身はこの return です。
 指定された3マス(iIndex0,iIndex1,iIndex2)それぞれのゲームロジック用データ(aiSquare[マス位置インデックス])と、 プレイヤー番号(iPlayerNumber)を比較して、「すべて」一致していれば true を返します。
 これで、「1ライン揃っているか」の判定が可能になります。


関数定義:勝利判定

//**********************************************************************
// 勝利判定
//   引数:
//     iPlayerNumber: プレイヤー番号
//**********************************************************************
function isWin( iPlayerNumber ) {
 前述の関数を使用して勝利判定を行う isWin 関数を定義します。


指定のプレイヤー番号が3つライン上に並んでいるマスがあるかを返す

// 指定のプレイヤー番号が3つライン上に並んでいるマスがあるか
return ( 
指定のプレイヤー番号が3つ、ライン上に並んでいるマスがあるかを調べて、true または false を返します。


横に揃っているか

// 左上・中上・右上
areAllSamePlayer( iPlayerNumber , 0 , 1 , 2 ) ||
// 左中・中中・右中
areAllSamePlayer( iPlayerNumber , 3 , 4 , 5 ) ||
// 左下・中下・右下
areAllSamePlayer( iPlayerNumber , 6 , 7 , 8 ) ||
【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 横並び  横に揃っているマスがあるか、盤面のマス位置インデックスを指定して調査します。
 この図に対応した、3種類の引数で areAllSamePlayer を呼び出しています。


縦に揃っているか

// 左上・左中・左下
areAllSamePlayer( iPlayerNumber , 0 , 3 , 6 ) ||
// 中上・中中・中下
areAllSamePlayer( iPlayerNumber , 1 , 4 , 7 ) ||
// 右上・右中・右下
areAllSamePlayer( iPlayerNumber , 2 , 5 , 8 ) ||
【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 縦並び  縦に揃っているマスがあるか調査します。 この図に対応した3種類の areAllSamePlayer 呼び出しです。


斜めに揃っているか

// 左上・中中・右下
areAllSamePlayer( iPlayerNumber , 0 , 4 , 8 ) ||
// 右上・中中・左下
areAllSamePlayer( iPlayerNumber , 2 , 4 , 6 )
【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 斜め並び  斜めに揃っているマスがあるか調査します。 この図に対応した2種類の areAllSamePlayer 呼び出しです。


関数定義:勝利プレイヤー表示

//**********************************************************************
// 勝利プレイヤー表示
//   引数:
//     iPlayerNumber: プレイヤー番号
//**********************************************************************
function alertWin( iPlayerNumber ) {
 勝利プレイヤーを表示する関数 alertWin を定義します。


勝利プレイヤー表示

if ( 1 === iPlayerNumber ) {
    alert( 'Oの勝ちです!' );
} else {
    alert( 'Xの勝ちです!' );
}
 勝利プレイヤーを表示します。 プレイヤー番号を O または X に変換しています。


ゲーム終了判定&終了処理

//**********************************************************************
// ゲーム終了判定と処理
//   引数:
//     iPlayerNumber: プレイヤー番号
//**********************************************************************
// 勝利しているか
if ( isWin( iPlayerNumber ) ) {
    //  勝利プレイヤー表示
    alertWin( iPlayerNumber );
}
 今プレイしたプレイヤーがゲームに勝利しているかを判定し、勝利していれば表示するプログラムです。


ゲーム終了判定に関する補足:引き分け未実装


 今回のソースコードでは、引き分け判定が未実装です。
 色々な実装方法がありますので、ぜひ考えてみてください。
 なお、今まで解説したプログラミング要素だけで実装する方法もありますが、 基本アルゴリズム編のエピソード「ループ」で解説したループを用いる方法もあります。 ぜひ挑戦してみてください。

「実装検証」で体験しよう


 前記「実装検証」セクションにて、このプログラムを体験できます。
 またこれにより、ついに完成版OXゲームがプレイ可能です。 ぜひ今までのバージョンと見比べて、ゲーム開発の楽しさを感じてください!

ゲームプログラミングにおける「ゲームオーバー」


 マンガのOXゲーム開発では、1プレイのみの単純なゲームでしたので、単純にどちらかが勝利すればゲームオーバーで、それがすべての終了でした。
 しかし昨今の実際のゲームはより複雑ですので、代表的な事例を紹介します。

ゲームにおける終了判定


 ゲームには様々な終了判定があります。
 敵と戦うゲームでは、敵に勝利した、敗北した、の判定があり、ゲーム進行に直結することも多いです。
 その他にも、ステージクリア、シナリオおよびクエストのクリア、制限時間オーバー、ゲーム内ゲームのクリアなど、大小さまざまな終了判定がおこなれています。 また、バトルロイヤルで最後の1人になった、という終了判定などもあります。

ゲームにおける終了処理


 終了判定を受けた終了処理にも、昨今のゲームには様々なパターンがあります。
 敵に敗北してゲームオーバー表示、制限時間を超えてタイムアップ表示、という単純に見えるものでも、その後のリトライや、タイトル画面に戻るなど、遊びやすさを考慮して作られています。
 他にも、ロールプレイングゲームにおける各バトル勝利の演出やリザルト表示、 最後のストーリーをクリアして幸せな世界を表示したあとにエンドロールを流すなど、 大小様々な処理があり、複数の段階に分かれていることも多いです。 また、アーケードゲームや、マルチプレイヤー対戦ゲームにおけるランキング表示などもあります。
 セーブして終了することをプレイヤーが選んだのを受けて、アプリケーションを終了させるのも、終了処理と言えます。

【プログラミングの醍醐味】勝利判定8パターンに違和感を覚えたら


 例示したソースコードでは、勝利判定で全8パターンの areAllSamePlayer を記述しています。 これを面倒くさいまたは問題があるなどと違和感を覚えたのなら、すばらしいです。
 具体的な問題として、このままでは他のゲームに応用できません。 例えば囲碁の19路盤で5目並べの判定を同様にしようとすると、1000パターン以上の記述が必要で、美しいプログラミングとは言えません。
 つまり本来であれば、8パターンのベタ書きではなく、1つのルールを自動的に繰り返すように処理すべきです。
 これは重要なプログラミングの考え方であり、プログラミングの醍醐味です。
 この繰り返しによるプログラミングテクニックは、 基本アルゴリズム編のエピソード「ループ」で解説しています。 そちらを理解したら、ぜひ本プログラムの改修に挑戦してください。

【職人の視点】&&|| の処理順序とパフォーマンス


 今回のゲーム勝利判定に用いた論理演算子&&(かつ・論理積)と||(または・論理和)は、 主要なプログラミング言語では、左から処理して結果が確定したら、それ以降の処理はしません。
 例えば、 A && B の場合、Afalse なら、Bは実行されません。 同様に A || B の場合、Atrue なら、Bは実行されません。 どちらも、Aを判断した時点で結果が確定するからです。
 例示した isWin 関数内では、8通りの勝利判定が「||」で繋がれています。 つまり1つでも見つかれば(trueになれば)、その時点で他の処理はスキップされます。
 本エピソードのケースでは問題ありませんが、すべての処理が実行される前提で「&&」や「||」を使用すると不具合になりますので、注意が必要です。

【職人の視点】マスに描かれる前に勝利演出


 現在の実装では、最後の OX がWebブラウザー上で表示される前に「~の勝利です!」と表示されています。 【OK】を押してダイアログを消すと、OX が表示されます。
 実際の JavaScript のプログラムを読むと、O または X の描画 → 勝利判定&alert、の順で記述されています。 これを不思議だと感じていただければすばらしいです。
 簡単に理由を書くと、 alert が処理ブロッキングしてしまい、その他のWebブラウザーの処理が動かないからです。 ゲームの実装でも同様のところはありますので、後日解説予定のグラフィックス編のエピソードもご確認ください。

【コラム】OXゲーム開発編 クリア!


 本エピソード(第10話)で、第1話「プログラム」から続く一連の物語、OXゲーム開発編はクリア(終了)となります。 おつかれさまでした!
 プログラミングの基礎的な各要素と合わせて、ひととおりのゲーム開発の流れを感じていただけたでしょうか。
 第1話から第10話まで読んでいただけたら、簡単なゲームを作るための要素は既に感じている状態です。 そしてもっと大きなゲームも、基礎部分は同じです。
 どちらも実際にやってみるとそう簡単ではありませんが、ぜひ、オリジナルのゲーム開発にチャレンジしてみてください。
 本シリーズは、次の章が基本アルゴリズムの解説、その後はより深い解説をしていきますので、引き続き楽しんでまいりましょう。
[PR]

マンガで感じる!本当の基礎から学ぶゲームプログラミングとは


 「マンガで感じる!本当の基礎から学ぶゲームプログラミング」シリーズでは、 主に、ゲーム開発を題材として、プログラミング時に筆者が脳内でイメージするコンピューター内部動作や本質を、マンガにてお伝えします。

プログラミングの本質をマンガで理解


 AI時代のプログラミングは、本質理解が重要です。 本質を理解していれば、あとはAIに任せて、自身を持って完成したプログラムに責任が持てるでしょう。
 そのため本シリーズでは、コーディングの実例や詳細よりも、「本質をイメージとして感じられること」を最優先としています。 まずマンガで、情報をできる限り絞り、プログラミングの仕組みやコンピューターの内部動作を、物理的に可視化してお届けします。
 そして文章の解説で徹底的に深堀りします。

登場人物紹介

【マンガで感じる】ゲームオーバー ~ゲーム終了処理~ 【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 登場人物 社長 クリスタル メカたち  マンガで感じる!本当の基礎から学ぶゲームプログラミングシリーズには、主に社長、クリスタル、およびメカたちが登場します。 ※実在の人物とは関係ありません

社長

 本シリーズの偉い人です。
 マンガでは、指示すなわち「要件定義」を行います。

クリスタル

 社長の指示を、メカを活用して解決します。
 名前は、コンピューター内部で指揮者の役割を果たす「水晶発振器」に由来します。

メカたち

 用途に応じて多数存在し、果たす役割がそれぞれ与えられています。
 クリスタルの指示に従い、ある時はプログラムの変数や関数のように、ある時は電子回路の素子のように振る舞います。

「マンガで感じる!本当の基礎から学ぶゲームプログラミング」にかける想い


 筆者が本シリーズにかける想いや、 より詳しいコンセプトは「マンガで感じる!本当の基礎から学ぶゲームプログラミング」にて語っています。 そちらもぜひご覧ください。

AIを専属の家庭教師にしてゲームオーバーを学ぼう


 本エピソードでは、ゲームの終了判定と終了処理を行う「ゲームオーバー」を解説しました。
 マンガを読んで興味が湧いた、解説のこのキーワードが気になった、などあれば、AIを専属の家庭教師に見立てて対話してみましょう。 各人の理解度に応じた質疑応答ができて、理解が深まりますので強くオススメします。
 本エピソードが少しでも、ゲームオーバーおよびゲームプログラミングの本質理解のお役に立てれば幸いです。

補足

  • 本記事に記載のプログラムソースコードは、悪意のない範囲で自由に使用・改変していただいて問題ありません。ただし、ご自身の判断と責任でお願いします。
  • 記事内容の検討および検証・添削に生成AIの Anthropic Claude と Google Gemini を利用しております。
  • 記事内の画像の作成に生成AIの Google Gemini を利用しております。
  • 画像内のラスタライズ文字フォントにOpen Font LicenseZen Antiqueを使用しております。
  • 画像内のラスタライズ文字フォントにOpen Font LicenseNoto Sans Japaneseを使用しております。
  • ※各社の登録商標または商標について「®」「™」等の表記はしておりません。



カテゴリー:マンガで感じる!本当の基礎から学ぶゲームプログラミング,OXゲーム開発編
[PR]