【マンガで感じる】関数 ~ひとまとめにした指示~ 開発効率を格段に高める【本当の基礎から学ぶゲームプログラミング】

[初心者向けゲーム開発入門]
2026/05/11
![【マンガで感じる】関数 ~ひとまとめにした指示~ 開発効率を格段に高める【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門]](../img/pc/pcFunction/pcFunction00.webp)
40年以上のゲームプログラミング経験をマンガで可視化。 今回は「関数」(かんすう)。 複数の指示をひとまとめにして、名前が付けられます。 再利用にも便利ですし、プログラムの可読性も上げられ、有効利用することで開発効率を格段に高めます。
![【マンガで感じる】関数 ~ひとまとめにした指示~ 開発効率を格段に高める【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門]](../img/pc/pcFunction/pcFunction00.webp)
プログラミングブログ記事一覧
[PR]
【マンガで感じる】関数(かんすう) ~ひとまとめにした指示~
OXゲーム開発編 第5話:エピソード「関数」
本エピソード「関数」は、OXゲーム開発編 第5話です。
OXゲーム開発編は、OXゲーム(三目並べ・マルバツ)の開発を通じて、ゲームプログラミングの基礎の基礎を解説しています。
OXゲーム開発編の各エピソードは、それまでのエピソードのマンガ(と解説)を前提としていますので、 もし途中から読み始めた方は、ぜひ最初のエピソード「プログラム」から読み進めてください。
「関数」のソースコード例
JavaScript
//********************************************************************** // マス位置インデックスから縦横のマス位置(それぞれ0から2)を求める // 引数: // iIndex: 盤面のマス位置インデックス // 012 // 345 // 678 // 返り値: // [ 横位置(0から2) , 縦位置(0から2) ] //********************************************************************** function getXYByIndex( iIndex ) { // 3で割った余りが横のマス位置 let iX = iIndex % 3; // 3で割って小数点以下を切り捨てた値が縦のマス位置 let iY = Math.floor( iIndex / 3 ); // 値を返す return [ iX , iY ]; }
//********************************************************************** // 線を描画 // 引数: // oContext: 描画対象キャンバスのコンテキスト // iFromX,iFromY: 線分を書き始める座標 // iToX,iToY: 線分を書き終わる座標 //********************************************************************** function drawLine( oContext , iFromX,iFromY , iToX,iToY ) { // ペンを移動する oContext.moveTo( iFromX , iFromY ); // 線を引く oContext.lineTo( iToX , iToY ); }
//********************************************************************** // X を描画 // 引数: // oContext: 描画対象キャンバスのコンテキスト // iIndex: 盤面のマス位置インデックス //********************************************************************** function drawX( oContext , iIndex ) { // コンテキストに線の色と太さを設定 oContext.strokeStyle = 'blue'; oContext.lineWidth = 10; // インデックスを縦横のマス位置(それぞれ0から2)に分解 let [ iX , iY ] = getXYByIndex( iIndex ); // マスの左上座標を求める let iSquareLeft = iX * 100; let iSquareTop = iY * 100; // Xの上下左右座標を求める let iTop = iSquareTop + 10; let iBottom = iSquareTop + 90; let iLeft = iSquareLeft + 10; let iRight = iSquareLeft + 90; // 左上から右下の線 drawLine( oContext , iLeft,iTop , iRight,iBottom ); // 右上から左下の線 drawLine( oContext , iRight,iTop , iLeft,iBottom ); }
OXゲーム(三目並べ・マルバツ):OやXを描く「関数」実装検証
[PR]
「関数」とは:ひとまとめにした指示
「関数」の本質は「ひとまとめにした指示」です。
関数は、プログラマーが作ることができます。 既存の処理をつなぎ合わせてまとめて、新たな機能と名前をもつ関数を作ることができます。
関数は再利用可能
作られた関数は、その名前で呼び出すことで、何度でも再利用することができます。
そして、さらに関数と関数をつなぎ合わせてまとめて、新しい関数を作っていくことが可能です。 本エピソードの主人公の関数
drawX も、関数 getXYByIndex と、関数 drawLine を使用しています。これを繰り返すことで、プログラムを再利用してどんどん大きくしつつ、大規模なプログラムを構築することができます。
関数に引数を渡して様々な設定で呼び出し可能
関数は、引数(ひきすう)により、違う設定での呼び出しが可能です。 上手に関数を作ることで、マンガの例のように、X を描く関数1つで、すべての位置に X を描くことができます。
関数は値を返すことが可能
関数内からは戻り値を返すことが可能です。 JavaScript など多くのプログラミング言語では
return という命令を用います。可読性を高める関数
各指示を適切にまとめて関数化して名前を付けることで、可読性を高めることができます。 以下はそのシンプルな例です。
initGame(); // ゲーム初期化
startGame(); // ゲーム開始
ソースコードの仕組み
マンガで登場した X を描画する関数
drawX について、
drawXから呼び出される関数から順に、ひとつひとつ解説します。縦横のマス位置を返す関数 getXYByIndex
getXYByIndex は、指定されたインデックス情報に基づき、盤面のマスの縦横位置を返す関数です。具体的には、インデックスの数値を、演算子を活用して、横(iX)と縦(iY)に分解します。 それぞれ 0 から 2 の値を取ります。
マンガでは、メカ・インデックスが担っている役割です。
関数 getXYByIndex を定義
まずは関数を定義します。
//********************************************************************** // マス位置インデックスから縦横のマス位置(それぞれ0から2)を求める // 引数: // iIndex: 盤面のマス位置インデックス // 012 // 345 // 678 // 返り値: // [ 横位置(0から2) , 縦位置(0から2) ] //********************************************************************** function getXYByIndex( iIndex ) {
function で定義します。
続く getXYByIndex が関数名です。
さらに () で囲まれた中身が引数を定義しています。
引数 iIndex : 盤面のマスの位置インデックス
iIndexは盤面のマスの位置を番号で表したものです。0から8の値を取ります。
マンガの例ではインデックス4番が指定されていました。 この関数を
getXYByIndex( 4 ) として呼び出すことで、iIndex の値に 4 が入ります。
3で割った余りが横のマス位置
マスの横位置iX は以下のプログラムで求めます。
// 3で割った余りが横のマス位置 let iX = iIndex % 3;
% 3すなわち 3 で割って余りを求めると、0から2の整数値になります。左が0、中央が1、右が2になることを、
iIndex に色々な値を入れて確かめてみてください。
3で割って小数点以下を切り捨てた値が縦のマス位置
iY は以下のプログラムで求めます。
// 3で割って小数点以下を切り捨てた値が縦のマス位置 let iY = Math.floor( iIndex / 3 );
/ 3すなわち 3 で割り、Math.floorというJavaScriptに用意されている関数を用いて小数点以下を切り捨てると、0から2の整数値になります。上が0、中段が1、下が2になることを、
iIndex に色々な値を入れて確かめてみてください。
計算結果を返す
// 値を返す return [ iX , iY ];
return にて、計算結果を返します。これらにより、関数を呼び出す側からは
getXYByIndex( 4 ) が [1,1] と同じ意味になります。線を引く関数 drawLine
drawLine は、キャンバスに線を引く関数です。始点座標
(iFromX,iFromY)と終点座標(iToX,iToY)を引数に取ります。
そして、エピソード「プログラミング」で解説した moveTo と lineTo を呼び出します。マンガでは、メカ・ラインが担っている役割です。
関数 drawLine を定義
//********************************************************************** // 線を描画 // 引数: // oContext: 描画対象キャンバスのコンテキスト // iFromX,iFromY: 線分を書き始める座標 // iToX,iToY: 線分を書き終わる座標 //********************************************************************** function drawLine( oContext , iFromX,iFromY , iToX,iToY ) {
function で、引数に oContext および、2点の座標を取る関数 drawLine を定義します。
引数 oContext : 描画対象キャンバスのコンテキスト
oContext は描画対象のキャンバスのコンテキストと呼ばれるものです。
キャンバスに描画をする場合に、このコンテキストを使用して行います。引数 iFromX,iFromY : 線の始点
iFromX と iFromY は、線の始点です。まず、この座標にペンを動かします。
引数 iToX,iToY : 線の終点
iToX と iToY は、線の終点です。この座標まで線を引きます。
ペンを移動して線を描画
// ペンを移動する oContext.moveTo( iFromX , iFromY );
moveToで、座標 (iFromX,iFromY) へペンを動かします。
ペンを移動して線を描画
// 線を引く oContext.lineTo( iToX , iToY );
lineToで、座標 (iToX,iToY) へ線を引きます。Xを描画する関数 drawX
本エピソードの主役は、X を描画するメカ・ドローXであり、この関数
drawX です。
その中身を解説します。
関数 drawX を定義
//********************************************************************** // X を描画 // 引数: // oContext: 描画対象キャンバスのコンテキスト // iIndex: 盤面のマス位置インデックス //********************************************************************** function drawX( oContext , iIndex ) {
function で、引数に oContext と iIndex を取る関数 drawX を定義します。
引数 oContext : 描画対象キャンバスのコンテキスト
描画対象キャンバスのコンテキストです。引数 iIndex : 盤面のマスの位置インデックス
iIndexは盤面のマスの位置を番号で表したものです。0から8の値を取ります。
線の色と太さを設定する
// コンテキストに線の色と太さを設定 oContext.strokeStyle = 'blue'; oContext.lineWidth = 10;
インデックスを縦横(それぞれ0から2)に分解する
// インデックスを縦横のマス位置(それぞれ0から2)に分解 let [ iX , iY ] = getXYByIndex( iIndex );
getXYByIndex を呼び出して、引数で渡された iIndex を、マスの位置に分解します。例えば
iIndex が 4 であれば、getXYByIndex( iIndex ) は [1,1] を返します。
それが、この行のプログラムで iX と iY にそれぞれ 1 が入ります。
つまり、縦横のマス位置に分解されます。なお、ここでは JavaScript の分割代入の機能を使用して、戻り値を複数の変数に直接代入していますが、プログラミング言語によっては書き方に工夫が必要です。
マスの左上座標を求める
// マスの左上座標を求める let iSquareLeft = iX * 100; let iSquareTop = iY * 100;
盤面のマスの左上座標は、マスの位置 [iX,iY] を利用して、このソースの式で得られます。ここで使用しているキャンバスが
(300,300) の大きさで、マスが 3×3 という前提です。
具体的には図の通りです。iX と iY に色々な値を入れて確認してみてください。
上下左右の座標を求める
// Xの上下左右座標を求める let iTop = iSquareTop + 10; let iBottom = iSquareTop + 90; let iLeft = iSquareLeft + 10; let iRight = iSquareLeft + 90;
この式で、X を描画するための、左(iLeft)、右(iRight)、上(iTop)、下(iBottom)を求めます。
図解の通りです。
端から 10 だけ空けたところを結んで線を引きます。iSquareLeft と iSquareTop に色々な値を入れて確認してみてください。X の線は「左上から右下」と「右上から左下」に線を引きます。 そのため上下左右の端がわかれば (左,上)-(右,下) と (右,上)-(左,下) に線を引けば良いことになります。
drawX では、対象マスの左上の座標からの相対座標で、以下のように上下左右を求めます。
線を引く
// 左上から右下の線 drawLine( oContext , iLeft,iTop , iRight,iBottom ); // 右上から左下の線 drawLine( oContext , iRight,iTop , iLeft,iBottom );
例えばマンガのインデックス4番であれば、座標 (110,110) から (190,190) と、(190,110) から (110,190) の線になります。
社長の指示の呼び出し方
マンガにおける社長の指示の、マス位置 4 に X を描くプログラムでの呼び出し方は以下になります。
drawX( oContext , 4 );
「実装検証」で体験しよう
前記「実装検証」セクションにて、解説した X を描く関数
drawX を体験できます。
O を描く関数 drawO も試せますので、ぜひ検証して、「関数」を感じてください。ゲームプログラミングにおける「関数」
関数は、ゲームプログラミングを含めたすべてのプログラミングの基本要素です。
上手に関数にまとめられると、可読性が高い(読みやすい)プログラム作成が可能です。 その結果、不具合が少なく、保守性の高いプログラミングが可能になります。
【プログラミングの醍醐味】共通ルールを発見し1つの関数にまとめる
マンガおよびソースコード例では、インデックスの数値を指定することで、9箇所あるどの位置にでも、関数
drawX にて X を描くことができました。これは、インデックスの値から線の座標を計算する方法、つまり共通ルールを発見したから実現できたことです。 このような方法を発見したら、難しいパズルを解いたような達成感がありますよね!
これぞプログラミングの醍醐味です。
【コラム】「めんどう!」への対応は積極的にしよう
マンガでは、社長が「めんどう!」とワガママを言ったので、対応することになりました。
これは実社会だと避けたい状況ですが、実はプログラミングの世界において「面倒くさいから簡単にする」というのは、とても重要です。 面倒なことはパッパと関数にまとめて、以降は簡単にしてしまいましょう。
筆者が大学生のときの実習で、あるプログラミングをした理由を「面倒くさいから」と説明したら、先生に褒められました。 今でも強烈に印象に残っています。 怠惰による効率化、うまくサボることは、プログラミングの世界では昔も今も推奨されます。
[PR]
マンガで感じる!本当の基礎から学ぶゲームプログラミングとは
「マンガで感じる!本当の基礎から学ぶゲームプログラミング」シリーズでは、 主に、ゲーム開発を題材として、プログラミング時に筆者が脳内でイメージするコンピューター内部動作や本質を、マンガにてお伝えします。
プログラミングの本質をマンガで理解
AI時代のプログラミングは、本質理解が重要です。 本質を理解していれば、あとはAIに任せて、自身を持って完成したプログラムに責任が持てるでしょう。
そのため本シリーズでは、コーディングの実例や詳細よりも、「本質をイメージとして感じられること」を最優先としています。 まずマンガで、情報をできる限り絞り、プログラミングの仕組みやコンピューターの内部動作を、物理的に可視化してお届けします。
そして文章の解説で徹底的に深堀りします。
登場人物紹介
マンガで感じる!本当の基礎から学ぶゲームプログラミングシリーズには、主に社長、クリスタル、およびメカたちが登場します。
※実在の人物とは関係ありません社長
本シリーズの偉い人です。マンガでは、指示すなわち「要件定義」を行います。
クリスタル
社長の指示を、メカを活用して解決します。名前は、コンピューター内部で指揮者の役割を果たす「水晶発振器」に由来します。
メカたち
用途に応じて多数存在し、果たす役割がそれぞれ与えられています。クリスタルの指示に従い、ある時はプログラムの変数や関数のように、ある時は電子回路の素子のように振る舞います。
「マンガで感じる!本当の基礎から学ぶゲームプログラミング」にかける想い
筆者が本シリーズにかける想いや、 より詳しいコンセプトは「マンガで感じる!本当の基礎から学ぶゲームプログラミング」にて語っています。 そちらもぜひご覧ください。
AIを専属の家庭教師にして関数を学ぼう
本エピソードでは、プログラミングに重要な役割を果たす「関数」について解説しました。
マンガを読んで興味が湧いた、ソースコードや解説のこのキーワードが気になった、などあれば、AIを専属の家庭教師に見立てて対話してみましょう。 各人の理解度に応じた質疑応答ができて、理解が深まりますので強くオススメします。
サンプルも大規模になってきました。焦らずひとつひとつ理解していきましょう。 本エピソードが、関数およびゲームプログラミングの本質理解に少しでもお役に立てれば幸いです。
補足
- 本記事に記載のプログラムソースコードは、悪意のない範囲で自由に使用・改変していただいて問題ありません。ただし、ご自身の判断と責任でお願いします。
- 記事内容の検討および検証・添削に生成AIの Anthropic Claude と Google Gemini を利用しております。
- 記事内の画像の作成に生成AIの Google Gemini を利用しております。
- ※各社の登録商標または商標について「®」「™」等の表記はしておりません。
カテゴリー:マンガで感じる!本当の基礎から学ぶゲームプログラミング,OXゲーム開発編
[PR]
![【マンガで感じる】関数 ~ひとまとめにした指示~ 開発効率を格段に高める【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] 条件分岐](../img/tn/pcIf00Tn.webp)
![【マンガで感じる】関数 ~ひとまとめにした指示~ 開発効率を格段に高める【本当の基礎から学ぶゲームプログラミング】[初心者向けゲーム開発入門] プログラム](../img/tn/pcProgram00Tn.webp)