見出し画像

フローチャートのススメ(変数のスコープを少し)

宿題

前回の宿題、『ループのループ』のフローチャート。
理解できた!これだっ!

size(400, 300);

for( int d =50 ; d > 0 ; d = d-10){
for(int x = 40; x < width; x = x+50){
ellipse(x,height/4, d, d);}
}

スクリーンショット 2020-04-25 13.38.49

画像1

これを分解して考えると、以下のような順序で作図されていることがわかります。

画像3

まず最初に実行されるのは中に入っているループの部分。直径が外のループで50になり固定されます。それからd>0でテストを経てループに入ります。
このループでは直径50の円はそのままに、Xの値だけが50ずつ増える=横にずれていくので上記のように丸が描かれます。丸が幅 x < width のテストでfalse(xは画面幅より小さいか、いいえ)の場合にdの部分が更新されます。

画像4

①でdの値が40になるのでこのループで描かれる円の直径は40です。d > 0のテスト結果はtrue(直径dは0より大きいか、はい)なので、再度中のループに入ります。中のループで③初期化 (int x =40) が実行されるのでxの値がもどり円の位置はまた一番左端に戻ります。そこから先は最初のループと同じです。

結果は同じになりますが、違う方法で描くことも可能です。
このループでは

同じ大きさの丸を右端まで描く
次に小さい円を左端から右端まで描く
さらに小さい円を。。。。

という順序ですが、

左端の円を小さい円まで描く
その隣に同じものを描く

といった順序で描くことも可能です。
その場合はこのループの外と中がひっくり返るだけです。

わかると単純ですが、いままで『なんとなぁーく』やってしまっていたので、フローチャートは目からウロコです。

フローチャートのルール

前回の投稿の際にフローチャートの描き方には一定のルールがあるらしい。と書きました。

このサイトを見たのですが、まだまだ初心者の私には縁のないものが多すぎて『どこで使うのこれ?』みたいなものばかりでした。

今回のコードで使ったのは主に3つだけ(ページ内 4.フローチャートの基本ルール(記号)参照)
①開始・終了 プログラムのスタートと終了 丸っこい四角で囲む

②処理 角ばった四角 中には処理する内容が書かれています

③条件分岐 菱形 trueとfalseのようにわかれるところに使います

あとは、ま、追々ってことで。。。

 あと、フローチャート作りに使ったのはこのサイトです

前回のフローチャートはイラレで作ったのですが、今回のは上記サイトで作りました。
こっちの方が倍ぐらい作りやすいです。矢印もついてくるし、さすがチャート作りに特化したアプリなだけあります。ぜひ使ってみてください。

変数のスコープ

setup()とdraw()の関数のところでこの変数のスコープが出てきます。setup()は文字通りセットアップに使われるもので、これは一度しか実行されません。対してdraw()は繰り返し実行されます。

int x = 0;

void setup(){
 size(200 , 150);
}

void draw(){
 delay(500);
 ellipse(x, height/2, 20, 20);
 x += 20;
}

タイトルなし

動きの速度を調整するためdelay();という関数を足しています。

delay(milliseconds) 

数値の単位はミリ秒(1/1000)です。その時間の分だけプログラムを一時停止します。この場合0.5秒の停止時間になります。(しかしgifアニメを作るアプリの方でも調整しているので上記のgifはこの数値にはなっていません)

saveFrame();でpngファイルを出力してそれを放り込めばgifアニメーションにしてくれます。すごい簡単で重宝しそう。

saveFrame(filename);
filename 任意の文字+ #### + 拡張子(.tif, .tea, .jpg, .png)

少しそれましたが、上記の変数は int x = 0; 
この宣言はsetup()とdraw()の{}の外側にいます。
この時の変数をグローバル変数と呼びます。

ここで宣言されたものは、以後すべての箇所で使用することが可能です。
対してsetup()内、draw()内で宣言されたものはその中でしか使えません。

例えばこの宣言をdraw()内に入れてしまうとどうなるか。

スクリーンショット 2020-04-25 17.15.10

これだけです。繰り返しの中に入ってしまったので、宣言も繰り返されることになり最後の x += 20; が打ち消されてしまいアニメーションになりません。

本題

で、今日は実はここが本題です。
本に書いてある例題でマウスの位置を判定するものがあります。
中心に書いてある小さな白い円にカーソルを合わせると、黒くなってどんどん大きくなります。円の外にカーソルを外すと、大きさがその場で止まり、白い円にもどります。

int x = 400; 
int y = 300;
int radius = 12; 

void setup(){
 size(800, 600); 
 ellipseMode(RADIUS); 
}

void draw(){
 background(204);
 float d = dist(mouseX, mouseY, x, y);
 if(d < radius){
   radius ++;
   fill(0);
 }else{
   fill(255);
 }
 ellipse(x, y, radius, radius);
}

キャンバスサイズだけ変更してあります。(大きくて見やすいのが好みなので)
この例題ではxとyの値が最初に宣言されており、それが画面の中心になっています。

画面の中心なら、いままでのもののようにwidth/2、height/2が使いたい!

なぜなら数字をできるだけみたくないから!!(数字アレルギー)

ということで、こう変換しました。

int x = width/2; 
int y = height/2;
int radius = 12; 

void setup(){
 size(800, 600); 
 ellipseMode(RADIUS); 
}

void draw(){
 background(204);
 float d = dist(mouseX, mouseY, x, y);
 if(d < radius){
   radius ++;
   fill(0);
 }else{
   fill(255);
 }
 ellipse(x, y, radius, radius);
}

すると

スクリーンショット 2020-04-25 17.40.12

?????
なんで?????

いままで中心にあったものが、左上に移動してしまいました。
スコープの話があったので、同じものをdraw()の中に入れてみました。

int radius = 12; 

void setup(){
 size(800, 600); 
 ellipseMode(RADIUS); 
}

void draw(){
 int x = width/2; 
 int y = height/2;
 background(204);
 float d = dist(mouseX, mouseY, x, y);
 if(d < radius){
   radius ++;
   fill(0);
 }else{
   fill(255);
 }
 ellipse(x, y, radius, radius);
}

スクリーンショット 2020-04-25 17.44.02

あ、戻ってきた。

解せぬ。

数値は同じはずなのに、グローバル変数にしたとたん、数値がずれてしまう。
何故。何故だー!!!

このモヤモヤを書きたいが為に変数のスコープに触れました。
長い時間考えましたが、よくわからないので、ちょっと無視して進もうと思います。また、わかった時にこれは解決しようと思います。

無期限の宿題!


この記事が気に入ったらサポートをしてみませんか?