今回は、関数による部品(モジュール)化を学習します。
プログラムは、長くなればなるほど判読が大変になってきます。関数を使ってプログラムを整理整頓する癖をつけましょう。
まずはモジュールとは、
電気機器やコンピューター装置などの、構成要素の単位。独立の完成した機能をもち、交換や着脱が可能で、より大きなシステムに構成される。
(大辞泉より引用)
とあります。簡単に言ってしまえば「部品化」ということです。自動車の部品がそれぞれが独立していて異なる車種にも使われるように、プログラムも部品化してやれば他のプログラムに再利用することが可能になります。
また、このモジュール化の最大の利点は「プログラムが見やすくなる」ということです。
そして、その部品化されたものを関数(function)と呼びます。
なぜ日本語の名前として「関数」と付けられたのかは色んな説があるようですが、かつては「函数」と呼ばれていたようです。函に値を入れれば答えを出してくれるということですね。どちらにしても、英語名のfunction(機能)からその性質はよく分かりますよね。
以下がその概念図です。

メインのプログラム内で関数(function)がその都度実行されています。
ここで気を付けなければいけないのは、この考え方が適用できるのは、C言語やBasicなどの手続き型言語になります。手続き型言語は、プログラムが上から下に順番に実行されていく形のものです。JavaやC++などのオブジェクト指向言語はまた違った概念になります(知りたい人はこちら)。
式は以下の形になります。
型 関数名( 型 引数, 型 引数, 型 引数 ・・・)
実は、あなたはもうすでに関数を使っています。ellipse()を例にとってみましょう。
http://processing.org/reference/ellipse_.html
構文(Syntax)の項目は「ellipse(x, y, width, height)」と書かれており、これは、まさに上記の関数の形を取っています。この場合、x, y, width, heightに入る値の型はintかfloatになっています。つまりこの関数は、座標と幅、高さを入力すると円を描いてくれる関数なのです。
ここで、引数という関数に値を渡す機能が出てきます(例題として出てます)が、この引数はいくつでも作ることができます。
しかし、概念的なことだけ説明されても分からないでしょうから、ここで例題をやってみましょう。
以下は、円を描く簡単なプログラムです。

1 2 3 4 5 6 7 8 9 10 11 | void setup() { size(255, 255); //画面サイズ background(255); //画面の色を更新 smooth(); //オブジェクトにアンチエイリアスをかける noStroke(); //縁は描かない fill(0); //黒の ellipse(100, 100, 20, 20); //円を描く fill(127); //グレーの ellipse(200, 200, 20, 20); //円を描く } |
fillとellipseが2回実行されています。よく見ると、色と座標が違うだけで大きさが一緒です。ここで、色のついた円を描く関数を作ってみましょう。
1 2 3 4 | void colorEllipse(int c, int x, int y){ fill(c); //変数cに割り当てられた色の ellipse(x, y, 20, 20); //円を描く } |
この( )の中のint c, int x, int yは引数と呼ばれます。ここに色々な値を入れていくのです。
関数を作ったら、これを実際に使ってみます。すると、以下のような形になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | void setup() { size(255, 255); //画面サイズ background(255); //画面の色を更新 smooth(); //オブジェクトにアンチエイリアスをかける noStroke(); //縁は描かない colorEllipse(0, 100, 100); //黒の円を描く関数を実行 colorEllipse(127, 200, 200); //グレーの円を描く関数を実行 } void colorEllipse(int c, int x, int y) { fill(c); //変数cに割り当てられた色の ellipse(x, y, 20, 20); //円を描く } |
しかし、これだけではcolorEllipse関数を使わない状態との差があまりよく分かりません。もう少し拡張してみましょう。次は、大小2つの円が重なって描かれる関数を作って利用してみます。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | void setup() { size(255, 255); //画面サイズ background(255); //画面の色を更新 smooth(); //オブジェクトにアンチエイリアスをかける noStroke(); //縁は描かない doubleEllipse(0, 100, 100, 100); //黒の円を描く関数を実行 doubleEllipse(127, 255, 200, 200); //グレーの円を描く関数を実行 } void doubleEllipse(int c1, int c2, int x, int y) { fill(c1); //変数c1に割り当てられた色の ellipse(x, y, 50, 50); //外側の円を描く fill(c2); //変数c2に割り当てられた色の ellipse(x, y, 20, 20); //内側の円を描く } |
こうすると、円の数を増やしていくときも、doubleEllipse()の数を増やしていくだけになり、機能も分かりやすくコード自体も短くなっていきます。
さて、上記の関数の宣言の前にvoidとありましたが、これは一体なんでしょう。よく考えてみると、setup関数やdraw関数の前にもvoidが書かれていました。
voidとは、「空(から)」という意味で、戻り値がないという意味なのです。
では、戻り値とは何でしょう。次のサンプルは、int型の戻り値をもつ関数の例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | int x; //x座標 int speed; //円の移動スピード void setup(){ size(300, 300); //画面サイズ smooth(); //オブジェクトにアンチエイリアスをかける speed = 5; //speedの初期値を5に設定 x = 0; } void draw(){ background(255); speed = bounce(x, speed); //折り返しを判定する x += speed; ellipse(x, height/2, 10, 10); } //折り返しを判定する関数 int bounce(int fx, int fspeed){ if(fx > width || fx < 0){ //x座標が画面幅を超えるか、0未満になったら fspeed = -fspeed; //spの値の正負を変更 } return fspeed; //int型の値を返す } |
上の例題では、x座標の折り返しの判定を行い、speedの値を正にしたり負にしたりする関数を作りました。計算結果はreturn fspeedで、int型の値を返します。これが戻り値なのです。
問題:上記の例題を元にして、同じbounce関数を利用する2つの円を作りなさい。setup()の部分までは以下のコードを利用する。
1 2 3 4 5 6 7 8 9 10 | int x1, x2; //x座標 int speed1, speed2; //円の移動スピード void setup(){ size(300, 300); //画面サイズ smooth(); //オブジェクトにアンチエイリアスをかける speed1 = 5; //speedの初期値を5に設定 speed2 = 12; x1 = x2 = 0; } |
また、以下はBoolean型の値を返す関数が使われている例です。
object_pressed_circle
Sorry, comments are closed.