Nodachisoft Nodachi Sword Icon
  
@あまじ✎ 2018年7月1日に更新

第2章26 自作の関数を作ってみる

イチからゲーム作りで覚えるC言語
第2章25 疑似乱数のシードを時間にする : PREV
NEXT : 第2章27 自作関数を作りときプロトタイプ宣言を利用する :

この記事でやること

今回は、新しくプロジェクト「0210_myfunc」を作り、関数を自作する方法についてお話します。いままではすべて main 関数の中でプログラミングをしてきましたが、同じような機能を自作関数にして、必要なときに呼び出すことで、すっきりとコードをまとめて読みやすくしたりすることができます。

自作の関数を作り、利用するプログラム

自作の関数を作り、利用するプログラムを動かして結果を見てみましょう。プロジェクト「0210_myfunc」を新しく作成し、ソースコード「MyFunc.c」を作成してみてください。

 
MyFunc.c
#include <stdio.h>
#include <stdlib.h>

int kinokoHiroi () {
 int kinoko = rand() % 3 + 1;
 return kinoko;
}

int main() {
 for (int i = 0; i < 4; i++) {
   int toretaKinoko = kinokoHiroi();
   printf("ぷらんくは %d 本のキノコを採取しました。\n", toretaKinoko);
 }
}

このコードを実行してみるとこんな結果になったかと思います。

MyFunc.cの実行結果
ぷらんくは 3 本のキノコを採取しました。
ぷらんくは 3 本のキノコを採取しました。
ぷらんくは 2 本のキノコを採取しました。
ぷらんくは 2 本のキノコを採取しました。

ぷらんくはランダムに4回、キノコを採取します。

関数とは

ここまでのお話の中で printf 関数や rand 関数などいろいろな関数を使ってきました。

少しおさらいになります。ざっくりいうとC言語で関数とは便利な機能をあらかじめどこかで定義しておき、定義した引数を設定して呼び出しすることで、なんらかの結果を得ることができる機能です。数学で下のような式をみたことがあるかと思います。

f(x) = x + 5

これは x を引数にもち、x + 5 という計算を行った結果を出す f という名前の関数です。 例えば引数に 1 を入れると、f(1) = 1 + 5 = 6 という結果になります。

C言語でも関数の形はとても似ています。

ただ数学と異なり、プログラムでは「x + 5」などの計算だけではなく、文字を表示したり、ファイルをいじったり、画像を表示したりなど、さまざまなことができます。

C言語での関数の定義の仕方

C言語で関数は下のように宣言&定義/{}することができます。 関数の宣言は「こういう名前で、引数はコレコレの関数を作るよ!」と明示することです。 関数の定義は「この関数の具体的な処理は〇〇だ」と処理を明記することです。

C言語で関数 f を定義するイメージ C言語で関数 f を作るイメージ

他にも宣言の方法はありますが、まずはこちらから。

関数の書き方
戻り値の型  関数名 ( 引数1の型 引数1の変数, 引数2の型 引数2の変数, … 略 … ) {
 関数が行う(複数の)処理;
 return  呼び出し元に返す値;
}

オリジナルの関数を作るには、まず 〇〇するような関数、という宣言からする必要 があります。重要なことですが関数を宣言&定義するだけでは関数に書いたプログラムは動きません

戻り値の型とreturn文

まず関数を宣言するとき「戻り値の型」を書く必要があります。

関数を使うとき、例えば乱数を生成する rand 関数では呼び出した戻り値が整数の乱数となっていたかと思います。具体的には rand 関数の「戻り値の型」は int 型と定義されています。

こういった関数の呼び出し元に返す値の型は自分で決めることができます。具体的にどんな値を関数の呼び出し元に返すかは return 文で決めます。

int型を返す関数の例

例でみてみましょう。

関数の例A
int funcA () {
   return 100;
}

と書くと、int 型の整数 100 を返す関数 funcA を宣言&定義することができます。

ワンポイント

return の右側に 100 と書くことで、 整数100 を返すことができますが、このとき、return ( 100 ); とする必要はありません。 細かな話ですが、関数は「関数名(ほにゃらら)」とする必要がありますが、return は関数ではなく、「return 〇〇」という文(C言語の仕様)の一つとして定義されています。

double型を返す関数の例

同じように double 型(浮動小数点数を代入できる型)を返すような関数を見てみましょう。

関数の例B
double funcB () {
  return 3.1415;
}

上のように書くことで、double型の「3.1415」という浮動小数点数を返す関数 funcB を宣言&定義することができます。

return 文が処理されるとき

関数の中で return 文までたどりついたとき、関数の呼び出し元にその場で戻ります。

その後に書いてある関数の中の処理は実行されないので注意して下さい。例えば、

return文の例
int okanehiroi() {
 printf ("100 枚の銅貨を拾いました。");
 return 100;
 printf ("よくみたら 200 枚の銅貨でした。");
 return 200;
}

のようなコードであれば、3 行目の「return 100;」以降のプログラムは実行されず、関数 okanehiroi を呼び出した元に 100 という戻り値をもって戻ります。

何も値を返さない関数の例

計算結果などは別にないし、特に関数の呼び出し元に値を返す必要のない関数があります。

すでにいままで出てきた例だと、 srand関数(疑似乱数の種を設定する関数)は戻り値が特にありません。ですので、「int kekka = srand(100);」のように書くとエラーとなります。

こういった関数は、ただ文字を表示するだけだったり、内部で事前計算をするだけのときにもよく使われます。例を見てみましょう。

戻り値がない関数の例
void hyouji () {
    printf("文字を出すだけの関数ですよ");
    return ;
}

ただ文字を表示するだけで、関数の呼び出しもと結果を何も返す必要がないときは関数の戻り値に void と書きます。 void は、「空」とか「虚ろ」とかいう意味です。この場合、 return文は省略することができます

main 関数について

今までのプログラムで、それほど意識せずに int main () { … } という形式でソースコードを書てきましたが、これも同じく関数です。

int main () { …関数の中身… }

という書き方ですので、これは main という名前の関数で、int型を返す関数ということになります。 この main 関数はプログラムをビルドして出来上がった「〇〇.exe」というファイル(CPUが理解して実行することのできるバイナリファイル)を実行したとき、 自動的に呼び出しされるようになっています。 exe を実行した後、いろいろと main 関数が実行されるまでにやってる処理もあるのですが、そのあたりの処理は C言語のプログラマは直接意識しなくても良いようになっています。

具体的には、この辺りは C言語のソースコードをビルドするツール達(コンパイラやリンカ等)や、 Windows や Linux、Android、iOSなどの OS(オペレーティングシステム)が処理してくれています。

さてさて、main 関数は int 型を返すように宣言しています。

今までのプログラムでは「 return 〇〇; (〇〇は int 型)」と最後に書いていませんでしたね。でも今までreturn を書かなくともエラーなどは出ていなかったと思います。 実は {uyelllow}main 関数だけは特別に return を省略した場合は main 関数の「}」関数の終わりに到達したとき、「return 0;」と自動的に処理{/}してくれています。

明示的に「return 1;」など書けば、 main 関数の呼び出し元である OS に その値が渡されますが、特に今は意識しなくても大丈夫です。

ソースコードを追ってみよう

冒頭に記載したソースコードを再掲します。 ではでは、今回のソースコードを追ってみましょう!

 
MyFunc.c
#include <stdio.h>
#include <stdlib.h>

int kinokoHiroi () {
 int kinoko = rand() % 3 + 1;
 return kinoko;
}

int main() {
 for (int i = 0; i < 4; i++) {
   int toretaKinoko = kinokoHiroi();
   printf("ぷらんくは %d 本のキノコを採取しました。\n", toretaKinoko);
 }
}

今回のプログラムの中では rand 関数を使いたかったので、ソースコードの頭で「#include <stdlib.h>」を記載していきます。 これで以降のソースコードの中で rand 関数が利用できます。

 
MyFunc.c
#include <stdio.h>
#include <stdlib.h>

オリジナルの関数の作成(定義)

続いて、オリジナルの関数 kinokoHiroi を定義しています。

重要なことですが、定義するだけでは書いてある処理は実行はされません。

main 関数などから呼び出したとき、はじめて実行されます。

 
MyFunc.c
int kinokoHiroi () {
  int kinoko = rand() % 3 + 1;
  return kinoko;
}

その名前の通り、キノコを拾う処理をしてくれる関数をイメージしています。

関数の名前は英数字と一部の記号を使うことができます。

ワンポイント

関数名は日本語でも動くかもしれませんが、あまりお勧めはしません。C言語の開発は英語圏が基本だったこともあり、プログラムの文に日本語を使うことは考慮しきれていないことがよくあります。

関数名の例:

  • myFunc (){ … }
  • getGold100 (){ … }
  • lets_bake_bread(){ … }  ※なお、C言語では関数名の大文字と小文字は区別されるので注意しましょう。

関数 kinokoHiroi の中では具体的にどのような処理をしているか確認しましょう。

 
MyFunc.c
int kinokoHiroi () {
  int kinoko = rand() % 3 + 1;
  return kinoko;
}

5 行目の右辺「rand() % 3 + 1」では 乱数で 1 ~ 3 の整数を生成しています。そして、その計算結果を変数 kinoko に代入しています。

6行目で return 文が登場しています。return 文の右側に kinoko と書いてありますので、kinoko の中身である 1~ 3 のいずれかの乱数を、呼び出し元の関数に返していることになります。return 文がでてきたら関数の処理は終了となります。

main 関数の定義

ここからはいままでもやってきたように、main関数の定義をしています。

あまり意識はしませんが、ソースコードでは関数 kinokoHiroi も、main 関数も定義の仕方は同じような形ですね。 ただ、C言語をプログラムとして実行できるときには、main関数が呼び出される決まりですので、 結果的には実質一番最初に main 関数に書いた処理から実行されることとなります。

 
MyFunc.c
int main() {
 for (int i = 0; i < 4; i++) {
   int toretaKinoko = kinokoHiroi();
   printf("ぷらんくは %d 本のキノコを採取しました。\n", toretaKinoko);
 }
}

for 文で繰り返し処理をするように書かれていて、4回ループすることになります。

ループ処理の中で、自作関数を呼び出ししていますね。

 
MyFunc.c
   int toretaKinoko = kinokoHiroi();
   printf("ぷらんくは %d 本のキノコを採取しました。\n", toretaKinoko);

11行目、自作関数の kinokoHiroi() を呼び出し、結果を変数 toretaKinoko に代入しています。kinokoHiroi() の戻り値は int 型で定義したので、代入先も int 型にしてあげています。

12行目で自作関数 kinokoHiroi() の結果である取れたキノコの量を表示しています。

補足:main関数の他の書き方

この項目は補足です。このシリーズではこの書き方は基本的にしませんので飛ばしてもらってもOKです。 ですが、コンソールプログラムでゲームデータを作るような補助ツールを作ったりするときには有用だと思いますので書いておきます。

main 関数は 「int main () { … } 」以外にもいくつかの種類の書き方があります。C言語の文法を取り決めた、2018年6月時点でほぼ最新のC11(N1570)バージョンには以下の書き方も紹介されています。

int main ( int argc, char* argv[] ) { … }

この書き方にはなにやら二つの引数がついていますね。

VisualStudio などの IDE 上から実行するのではなく、コンソール上からプログラムを呼び出すこともできます。そのとき、引数をつけて 〇〇.exe を実行することもできますが、その引数にどのような文字を設定したのか、この main 関数の書き方であれば引数の「argc」と引数の「argv[]」から取得することができます。

この辺りは必要に応じてお話しようと思います。

あとがき

今回は「キノコを採る」という関数を作ってみました。プレイヤーの決まった動作や、敵の動作など、決まった処理を関数としてまとめておき、必要なタイミングで呼び出すことで分かりやすいソースコードを書くことができます。これは C 言語だけでなく、他のプログラミング言語でも同様の考え方が使えます。

次回も関数について追加でお話したいと思います。

今回はここまで。おつかれさまでした。

非常に参考になったサイトさまや、参考文献など

ページの更新履歴

更新日 更新内容
2018/8/1 初版公開
2018/11/26 トップ画像、アイキャッチ画像追加。文章のハイライト変更。
イチからゲーム作りで覚えるC言語
第2章25 疑似乱数のシードを時間にする : PREV
NEXT : 第2章27 自作関数を作りときプロトタイプ宣言を利用する :
 
 
送信しました!

コメント、ありがとうございます。

なんかエラーでした

ごめんなさい。エラーでうまく送信できませんでした。ご迷惑をおかけします。しばらくおいてから再度送信を試していただくか、以下から DM などでご連絡頂ければと思います。

Twitter:@NodachiSoft_jp
お名前:
 
連絡先:
 
メッセージ:
 
戻る
内容の確認!

以下の内容でコメントを送信します。よろしければ、「送信」を押してください。修正する場合は「戻る」を押してください

お名前:
 
連絡先:
 
メッセージ:
 
Roboto からの操作ではないという確認のため確認キーを入れてください。
確認キー=95
戻る
 / 
送信確認へ
コメント欄
コメント送信確認へ

関連ありそうな記事(5件)です!

ゲーム等で使えるつなぎ目のないループするテクスチャ画像の作り方

#ツール#ゲームプログラミング✎ 2021-01-24
ゲームなどで使えるループ画像、パターンテクスチャのツール、手動での作り方をまとめ
広告領域
追従 広告領域
目次
第2章26 自作の関数を作ってみる
第2章26 自作の関数を作ってみる
この記事でやること
この記事でやること
自作の関数を作り、利用するプログラム
自作の関数を作り、利用するプログラム
関数とは
関数とは
C言語での関数の定義の仕方
C言語での関数の定義の仕方
戻り値の型とreturn文
戻り値の型とreturn文
int型を返す関数の例
int型を返す関数の例
double型を返す関数の例
double型を返す関数の例
return 文が処理されるとき
return 文が処理されるとき
何も値を返さない関数の例
何も値を返さない関数の例
main 関数について
main 関数について
ソースコードを追ってみよう
ソースコードを追ってみよう
オリジナルの関数の作成(定義)
オリジナルの関数の作成(定義)
main 関数の定義
main 関数の定義
あとがき
あとがき
非常に参考になったサイトさまや、参考文献など
非常に参考になったサイトさまや、参考文献など
ページの更新履歴
ページの更新履歴
Nodachisoft © 2020