練習: 形状が指定されている魚
// 定数 int[] fish = new int[] { // 魚の形状 (体の中心=原点) 0, 0, 70, 30, // 胴体の相対位置(x,y)・横幅・縦幅 -38, 0, 15, 25 // 尾びれの相対位置(x,y)・横幅・縦幅 }; final int bodyX = 0; final int bodyY = 1; final int bodyLength = 2; final int bodyWidth = 3; final int finX = 4; final int finY = 5; final int finLength = 6; final int finWidth = 7; // 変数 int x; // 魚の中心の x座標 int y; // 魚の中心の y座標 size(400, 400); // ウィンドウのサイズ noStroke(); // 輪郭線を無効に background(63, 63, 255); // 背景色 fill(63, 31, 31); // 塗る色 // 魚の姿の描画 for (int i = 0; i < 5; i++ ) { x = i * 50 + 100; y = i * 50 + 100; ellipse(x + fish[bodyX], y + fish[bodyY], fish[bodyLength], fish[bodyWidth]); // 胴体 ellipse(x + fish[ finX], y + fish[ finY], fish[ finLength], fish[ finWidth]); // 尾びれ }
これもまたfor文を使わない場合,以下のようになる.
// 定数 int[] fish = new int[] { // 魚の形状 (体の中心=原点) 0, 0, 70, 30, // 胴体の相対位置(x,y)・横幅・縦幅 -38, 0, 15, 25 // 尾びれの相対位置(x,y)・横幅・縦幅 }; final int bodyX = 0; final int bodyY = 1; final int bodyLength = 2; final int bodyWidth = 3; final int finX = 4; final int finY = 5; final int finLength = 6; final int finWidth = 7; // 変数 int x; // 魚の中心の x座標 int y; // 魚の中心の y座標 size(400, 400); // ウィンドウのサイズ noStroke(); // 輪郭線を無効に background(63, 63, 255); // 背景色 fill(63, 31, 31); // 塗る色 // 魚の姿の描画 x = 0 * 50 + 100; y = 0 * 50 + 100; ellipse(x + fish[bodyX], y + fish[bodyY], fish[bodyLength], fish[bodyWidth]); // 胴体 ellipse(x + fish[ finX], y + fish[ finY], fish[ finLength], fish[ finWidth]); // 尾びれ x = 1 * 50 + 100; y = 1 * 50 + 100; ellipse(x + fish[bodyX], y + fish[bodyY], fish[bodyLength], fish[bodyWidth]); // 胴体 ellipse(x + fish[ finX], y + fish[ finY], fish[ finLength], fish[ finWidth]); // 尾びれ x = 2 * 50 + 100; y = 2 * 50 + 100; ellipse(x + fish[bodyX], y + fish[bodyY], fish[bodyLength], fish[bodyWidth]); // 胴体 ellipse(x + fish[ finX], y + fish[ finY], fish[ finLength], fish[ finWidth]); // 尾びれ x = 3 * 50 + 100; y = 3 * 50 + 100; ellipse(x + fish[bodyX], y + fish[bodyY], fish[bodyLength], fish[bodyWidth]); // 胴体 ellipse(x + fish[ finX], y + fish[ finY], fish[ finLength], fish[ finWidth]); // 尾びれ x = 4 * 50 + 100; y = 4 * 50 + 100; ellipse(x + fish[bodyX], y + fish[bodyY], fish[bodyLength], fish[bodyWidth]); // 胴体 ellipse(x + fish[ finX], y + fish[ finY], fish[ finLength], fish[ finWidth]); // 尾びれ
以上から,最初の魚からx,y座標が100,150,200,250,300と変化していくことが分かる.魚を描画する際,変化しているところが,x = 0 * 50 + 100;と y = 0 * 50 + 100;の 0,1,2,3,4の箇所だけなので,これをfor文を用いてカウント用の変数iに置き換えることでプログラムを短くすることができるわけである.
次に演習に備えて,魚を一匹だけ描くようにする.
// 定数 int[] fish = new int[] { // 魚の形状 (体の中心=原点) 0, 0, 70, 30, // 胴体の相対位置(x,y)・横幅・縦幅 -38, 0, 15, 25 // 尾びれの相対位置(x,y)・横幅・縦幅 }; final int bodyX = 0; final int bodyY = 1; final int bodyLength = 2; final int bodyWidth = 3; final int finX = 4; final int finY = 5; final int finLength = 6; final int finWidth = 7; // 変数 int x; // 魚の中心の x座標 int y; // 魚の中心の y座標 size(400, 400); // ウィンドウのサイズ noStroke(); // 輪郭線を無効に background(63, 63, 255); // 背景色 fill(63, 31, 31); // 塗る色 // 魚の姿の描画 x = 100; //x = 0 * 50 + 100; y = 100; //y = 0 * 50 + 100; ellipse(x + fish[bodyX], y + fish[bodyY], fish[bodyLength], fish[bodyWidth]); // 胴体 ellipse(x + fish[ finX], y + fish[ finY], fish[ finLength], fish[ finWidth]); // 尾びれ
これは以下のように書き換えることができる.(プログラムA)
// 定数 int[] fish = new int[] { // 魚の形状 (体の中心=原点) 0, 0, 70, 30, // 胴体の相対位置(x,y)・横幅・縦幅 -38, 0, 15, 25 // 尾びれの相対位置(x,y)・横幅・縦幅 }; // 変数 int x; // 魚の中心の x座標 int y; // 魚の中心の y座標 size(400, 400); // ウィンドウのサイズ noStroke(); // 輪郭線を無効に background(63, 63, 255); // 背景色 fill(63, 31, 31); // 塗る色 // 魚の姿の描画 x = 100; //x = 0 * 50 + 100; y = 100; //y = 0 * 50 + 100; ellipse(x + fish[0], y + fish[1], fish[2], fish[3]); // 胴体 ellipse(x + fish[4], y + fish[5], fish[6], fish[7]); // 尾びれ
これはさらに以下のように書き換えることができる.(プログラムB)
// 変数 int x; // 魚の中心の x座標 int y; // 魚の中心の y座標 size(400, 400); // ウィンドウのサイズ noStroke(); // 輪郭線を無効に background(63, 63, 255); // 背景色 fill(63, 31, 31); // 塗る色 // 魚の姿の描画 x = 100; //x = 0 * 50 + 100; y = 100; //y = 0 * 50 + 100; ellipse(x + 0, y + 0, 70, 30); // 胴体 ellipse(x + -38, y + 0, 15, 25); // 尾びれ
プログラムA,Bの方が短いプログラムなのに,なぜ練習問題は
ellipse(x + fish[bodyX], y + fish[bodyY], fish[bodyLength], fish[bodyWidth]); // 胴体 ellipse(x + fish[ finX], y + fish[ finY], fish[ finLength], fish[ finWidth]); // 尾びれ
と書くのか? それは
ellipse(x + fish[0], y + fish[1], fish[2], fish[3]); // 胴体 ellipse(x + fish[4], y + fish[5], fish[6], fish[7]); // 尾びれ
や
ellipse(x + 0, y + 0, 70, 30); // 胴体 ellipse(x + -38, y + 0, 15, 25); // 尾びれ
だと,fish[0]〜fish[7],もしくは0〜25の値が何を意味しているのかプログラムを書いてる本人しかわからないためである(また,大抵書いている本人も時間の経過で忘れる).
プログラムを仕事で書く場合,基本的に書いたプログラムは他人に見せるものであるので,特に事前知識のない人でも読みやすいように書くことが求められる.そこで,多少プログラム全体が長くなっても,
ellipse(x + fish[bodyX], y + fish[bodyY], fish[bodyLength], fish[bodyWidth]); // 胴体 ellipse(x + fish[ finX], y + fish[ finY], fish[ finLength], fish[ finWidth]); // 尾びれ
と記述すれば,事前知識のない人にプログラムを見せても,それぞれ何の値を表しているのか定数名から推測できるというわけである.
演習問題では魚が動く=アニメーションが必要であるので,setup関数とdraw関数を導入する.
int[] fish = new int[] { // 魚の形状 (体の中心=原点) 0, 0, 70, 30, // 胴体の相対位置(x,y)・横幅・縦幅 -38, 0, 15, 25 // 尾びれの相対位置(x,y)・横幅・縦幅 }; final int bodyX = 0; final int bodyY = 1; final int bodyLength = 2; final int bodyWidth = 3; final int finX = 4; final int finY = 5; final int finLength = 6; final int finWidth = 7; // 変数 int x; // 魚の中心の x座標 int y; // 魚の中心の y座標 void setup(){ size(400, 400); // ウィンドウのサイズ noStroke(); // 輪郭線を無効に fill(63, 31, 31); // 塗る色 } void draw(){ background(63, 63, 255); // 背景色(画面は毎フレームリセット(一色に塗りつぶす)必要があるのでここに移動 // 魚の姿の描画 x = 100; //x = 0 * 50 + 100; y = 100; //y = 0 * 50 + 100; ellipse(x + fish[bodyX], y + fish[bodyY], fish[bodyLength], fish[bodyWidth]); // 胴体 ellipse(x + fish[ finX], y + fish[ finY], fish[ finLength], fish[ finWidth]); // 尾びれ }