※当ブログ内容はPRを含みます

プログラミング入門6.関数を身に付けてラクをしよう!

 

こんちゃっす、ダイブツです。

今回は関数という内容について学習していきましょう。

 

あなたは今までプログラミングを学習してきて、「あー、また似たような処理書かなくちゃいけない…。めんどくさいな~」と感じたことはありませんか?

今回学ぶ関数は、そんな不満を解消する為に使うものです。

 

「関数さえ身に付ければ、あなたはもう同じようなプログラムを書く必要が無くなります」

さぁ、関数を身に付けてラクをしましょう!

 

なぜ、関数でラクができるのか?

関数を学ぼうとしても、まず関数が何か分かりませんよね。

名前だけ見ると、変数の一種かな?と思うかもしれませんが、全くの別物です。

 

関数とは、ある一連のまとまった処理を行うプログラムのことです。

 

例えば、あなたが朝起きる時のことを想像してください。

「起きる」といっても細かく言えば色んな行動をしますよね?

僕だったら

・目覚ましを止める。
・布団から出る。
・カーテンを開ける。

の3つのことをします。

 

関数は、上で言う「起きる」と表現している言葉のことです。

色んな行動を行なうことをまとめて1つで表しているんですね。

 

なので、プログラムでも同じようにいくつかのまとまった処理を1つの括りとして関数としているんです。

関数を使うことによって、プログラミングの効率を約5倍ほど上昇させることができます。

 

また例を出しますね。

もし、あなたがある処理を行うプログラムを5時間かけて作成したとします。

その後、同じ処理をプログラムの別箇所で使いたくなったらどうでしょう?

関数を使わなければもう1度同じプログラムを5時間かけて作らなければいけません。

でも関数を使えば、同じ処理を呼び出しさえすればいいので一瞬で作業が終わります。

つまり、関数を使うか使わないかで5時間もプログラムの作成時間が変わってくるってこと。

これが、関数を使うことでラクができるということです。

 

プログラマーが関数を使うタイミング

ただ初めのうちは、どんな処理を関数にしたらいいか分からないと思います。

なので、プログラマーがどんな時に関数を作るかポイントを書き出しました。

このポイントさえ押さえておけば間違いないです!

 

関数を作る基準
1、色んな箇所で同じ処理を使用する時
2、プログラムを整理して、読みやすくしたい時

 

1の内容は最初に書いていた、ラクをしたいからという理由と同じですね。

同じ処理を使うなら関数にしておいて、後から使いまわそうよ、という考えです。

特に複数人でプログラムを作成する時は、他の人が必要になる関数を予め作っておくと感謝されますよw

関数を作ることが思いやりのようになってるんです。

 

2の内容は、単純にプログラムを整理して分かりやすくしたいというだけです。

プログラムの要点だけ知りたいだけなのに、1000行も処理が続いているようなプログラムなんてもう・・・全く読む気力が湧きません。

なので、1つの関数には長くても100行に納まるプログラムを意識しておくと、要点がまとまって読みやすいプログラムになりますよ!

関数には引数や戻り値も設定できるので使いやすいですしね~。

 

引数(ひきすう)とは

引数とは、関数の処理を実行する時に、他の処理から関数に渡す値のことです。

例えば、↓の関数の座標と幅の箇所が引数になります。

rect(左上頂点のx座標,左上頂点のy座標,x方向の幅,y方向の幅);

 

戻り値とは

戻り値とは、関数が結果を返す値のことです。

1つの関数に対して、引数は複数設定できるんですが、戻り値は1つしか設定できません。
戻り値の使用例については、後程説明します。

 

これさえ覚えておけば間違いない3つの関数例

関数の書き方はパターンさえ覚えちゃえば簡単です。

これさえ覚えておけばないという関数の例を3つ出しますので、まずはこの3パターンを使えるようになりましょう。

 

関数例1:引数、戻り値が無い場合

void test_function(){
  関数の処理
}

 

関数例2:引数が2つ、戻り値が無い場合

void test_function(int iHikisu1, int iHikisu2){
  関数の処理
}

 

関数例3:引数が2つ、戻り値が有る場合

int test_function(int iHikisu1, int iHikisu2){
  関数の処理
}

 

関数の型の部分にvoidと書いたのは、「型が何も無いよ」ということを表しています。

もしかすると、あなたは「関数の型にはvoidを書くのに引数には書かねーのか!」と思うかもしれません。

実際僕もそう思いますw

ですが、引数が無い時は何も書かないですね。

これはルールだと思って覚えてしまいましょう。

 

それと、上の関数名でも書いていますが、関数のことはよくfunctionと呼ばれることがあります。
人によって関数と言ったりfunctionと言ったりややこしいんですが、よく出てくる言葉なので覚えておきましょう。

 

もう1つ、関数以外でも言えることなんですが、処理をくくる時に{}を使っていますよね?

よく見ると、{の次の行から文字の開始位置が少しずれているのが分かります。

これは、字下げ、もしくはネストと言って、プログラムを読みやすくする為にルールとして行われていることです。

勝手に入力してくれることもよくありますが、自分で入力する時はTabボタンを使って入力するようにしましょうね。

この字下げのTab入力はめっちゃ使うので、癖にしていった方がいいですよ!

 

Processing特有の関数実行順番

実は、どのプログラミング言語でもそうなんですが、まず最初にプログラムが実行される関数があります。

Processingでは、それがsetup()になるんです。

 

setup()の中は、プログラムを実行した時、最初に1回だけ実行されます。

その後draw()という名前の中の処理が繰り返し実行されるようになっているんです。

実行の順番を書いてみるとこんな感じですね。

 

setup(1回実行)⇒ draw ⇒ draw ⇒ ・・・

 

なので、ウィンドウのサイズ設定等、最初だけやれば十分な処理はsetup()の中に書いて、繰り返し行いたい処理はdrawの中に書いていく。という書き方になります。

実際に例を作ったので見てみてください。

 

例1:setup()から作成した関数を呼び出す

最初の例は、setup()から関数を呼び出す例です。

 

四角形を横に2つ描く処理を1つの関数として、引数には四角形を描き始める座標を渡しています。
戻り値には、次に四角形を描き始めるx座標を返すようにしていますね。

四角形を2つ描く処理を関数にしているので、今までと全然違う位置に四角形を表示したくなった時でも、関数を呼び出すだけで四角形を表示できちゃいます。

 

 

void setup(){
  int iRectStartPosX = 20;
  int iRectStartPosY = 20;
  final int RECT_NUM_Y = 3;
  final int RECT_INTERVAL_Y = 75;
  
  size(600,400);
  
  for(int i = 1; i <= RECT_NUM_Y; i++){
    iRectStartPosX = draw_multi_rect(iRectStartPosX, iRectStartPosY);
    iRectStartPosY = iRectStartPosY + RECT_INTERVAL_Y;
  }

  draw_multi_rect(100, 300);
}

int draw_multi_rect(int iStartPosX,int iStartPosY){
  int iRectSize = 50;
  int iRectPosX = iStartPosX;
  final int RECT_NUM_X = 2;
  final int RECT_INTERVAL_X = 75;
 
  for(int i = 1; i <= RECT_NUM_X; i++){
    rect(iRectPosX,iStartPosY,iRectSize,iRectSize);
    iRectPosX = iRectPosX + RECT_INTERVAL_X;
  }
  
  return iRectPosX;
}

 

例2:draw()から作成した関数を呼び出す

次はdraw()を使用した例です。

draw()は繰り返し処理を実行するので、四角形の位置を徐々に変更させてみました。

このように表示が変わっていく所を見れるのがProcessingの醍醐味ですね!

渦巻きのような四角形を表示する処理を関数にして、毎回draw()の中で呼び出すようにしています。

background(209.209,209);は表示を毎回リセットする為に、関数に指定している座標は毎回1を足して、四角形が斜めに移動しているように見せていますよ。

 

 

int iRectStartPosX = 20;
int iRectStartPosY = 20;

void setup(){
  size(600,400);
}

void draw(){
  background(209.209,209);
  
  draw_spiral_rect(iRectStartPosX, iRectStartPosY);
  iRectStartPosX++;
  iRectStartPosY++;
}

void draw_spiral_rect(int iStartPosX,int iStartPosY){
  int iRectSize = 50;
  int iRectPosX = iStartPosX;
  int iRectPosY = iStartPosY;
  final int RECT_NUM = 5;
  final int RECT_INTERVAL = 5;
 
  for(int i = 1; i <= RECT_NUM; i++){
     rect(iRectPosX,iRectPosY,iRectSize,iRectSize);
    
    iRectPosX = iRectPosX + RECT_INTERVAL;
    iRectPosY = iRectPosY + RECT_INTERVAL;
    
    iRectSize = iRectSize - (2 * RECT_INTERVAL);
  }
 
  return;
}

 

ここで1つ注意しておかなきゃあいけないことがあります

iRectStartPosXの変数を見てください、この変数は関数の外で宣言されていますよね?

もうあなたは薄々気付いているかもしれませんが、この変数が関数の外で宣言されているのには、ちゃんとした理由があります。

 

実は、関数の中で宣言した変数は、関数の処理が終わると値が無くなってしまうんです!!

なので、もし↓のようなプログラムを書いていたら、draw_spiral_rectに渡す引数の値は毎回20になってしまうってことなんです。

 

void draw(){
  int iRectStartPosX = 20;
  int iRectStartPosY = 20;

  background(209.209,209);
  
  draw_spiral_rect(iRectStartPosX, iRectStartPosY);
  iRectStartPosX++;
  iRectStartPosY++;
}

 

ただ、関数の外に変数を宣言しておけば、関数の処理が終わっても値をそのまま保持してくれます。

draw_spiral_rect()に渡す引数の値は保持しておきたかったので、関数の外に宣言していたんです。

そして、この関数の外に宣言する変数のことをグローバル変数と呼びます。

ただ!!

グローバル変数が便利だからってむやみやたらにグローバル変数を宣言するのは絶対に絶対に止めてください!!

 

グローバル変数は使えば使うほどプログラムが読みにくくなってきます。

グローバル変数だらけになって意味が分からなくなったプログラムを今までたくさん見てきました。

なので、必要にならない限りグローバル変数は使わない!という意識でプログラムを作るようにしてください。

 

問題:関数を使って下記の図を描け

今までの知識があれば解けるはずです。

「描画情報」
・黄色の指定は(255,255,0)でできる。

 

 

お疲れ様でした!

これでプログラミング入門の関数編が終了です。

 

 

段々とプログラミングに必要なスキルが身に付いてきましたね!

次回はプログラミングの醍醐味の1つであるif文について説明していきます。

このif文をマスターすれば、もうどんなプログラムでも書けるようになりますよ。

あと少し一緒に頑張っていきましょう!

 ⇒第7回:あなたはif文をマスターしていますか?

 ⇒講座一覧へ戻る

 

2 Comments

アバター T.T

はじめまして。こんにちは。
T.Tと申します。
プログラミング入門の記事、とても興味深く拝見しております。
ありがとうございます。
入門5までは割とスムーズにわかったのですが、
入門6でちょっとつまづきました。
下記のプログラムで同じ図を描くことはできたのですが、
setup()とdraw()、returnの意味がよくわかっていません。
なくても描けちゃったのですが、ダメですよね??^^;

size(600,400);
int iCircleSize = 100;
final int CIRCLE_POS_Y = 200;
final int CIRCLE_NUM = 5;
final int CIRCLE_INTERVAL = 20;
for (int i = 1; i <= CIRCLE_NUM; i++){
fill(0,255,0);
ellipse(100,CIRCLE_POS_Y,iCircleSize,iCircleSize);
fill(255,255,0);
ellipse(300,CIRCLE_POS_Y,iCircleSize,iCircleSize);
fill(255,0,0);
ellipse(500,CIRCLE_POS_Y,iCircleSize,iCircleSize);
iCircleSize = iCircleSize – CIRCLE_INTERVAL;
}
教えていただけるとありがたいです。
よろしくお願いいたします。

返信する
ダイブツ ダイブツ

>T.Tさん

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

確かにT.Tさんが書いたプログラムでも目的の図は書けるんですが、この入門6では「関数を使って」と指定しているので関数を使うようにしてみましょう。
setup()とdraw()は、「Processing特有の関数実行順番」に書いている順番で実行される関数ですよ。
returnは、例1で書いているように戻り値を設定するものになります。

関数はめちゃめちゃ使うので、是非できるようにしましょう!

返信する

気軽にコメントどうぞ!

内容を確認してから、下記の「コメントを送信する」ボタンを押してください。