2.6 if文の理解

さて、次はif、 else if、 elseといった条件分岐を学びます。このif文は、プログラミングには必須の構文です。
まずは、for文の節での例題を少し変えてif文を使ってみます【リスト2.6-a】。int eSizeの値を色々変えて実行してみてください。このサンプルでは、for文の中の変数名はxにしています。この変数名は基本的に自由なのですが、慣習的にはiが使われることが多く、座標に関連する場合にはx, y, zなどが使われることが多いのが現状です。

2.6.1 if (もし〜だったら)

2016_05_29_0_58
図2.6-a
リスト2.6-a
int eSize = 10;  //円の直径を設定する

size(400, 400);
background(255);
fill(255); //初めは白の塗りを設定

//xは0から始まって、ウィンドウの横幅以下の場合は繰り返され、
//繰り返すたびに20が加算されていく
for (int x = 0; x <= width; x += 20) {

  if (x >= 200) {  //もし、xの値が200以上だったら、

    fill(255, 0, 0);  //赤を設定 
  }

  ellipse(x, height/2, eSize, eSize);  //円を描画
}

この式は、xが200以上のときに円を白で塗りつぶします。
構文は次のとおりです。if文の条件式はかならず{}(ブレース)で囲みます。

if(条件式) { 
  処理 
}

処理の流れは以次のとおりになります。

if
図2.6-b

2.6.2 if文の条件式で使われる比較演算子

比較演算子は、すでにfor文の節で学習しましたが、if文でも使われます。次の6パターンあることを思い出してみましょう。

カテゴリ演算子説明使用例
比較演算子"=="等しいif (a == b)
!=異なるif (a != b)
<未満if (a < b)
>超(超える)if (a > b)
<=以下if (a <= b)
>=以上 if (a >= b)

一見分かりにくいのは>=と>の違い、<=と<の違いです。しかし、この=があるかないかによって大きな違いがあります。実際に例題を見てみましょう。次の例題は>=の場合です。

2016_05_29_0_53
図2.6-c
リスト2.6-b
int eSize = 20;  //円の直径を設定する

size(400, 400);
background(255);
fill(255); //初めは白の塗りを設定

//xは0から始まって、ウィンドウの横幅以下の場合は繰り返され、
//繰り返すたびに20が加算されていく
for (int x = 0; x <= width; x += 40) {

  if (x >= 200) {  //もし、xの値が200以上だったら、

    fill(200, 0, 0);  //赤を設定 
  }

  ellipse(x, height/2, eSize, eSize);  //円を描画
}

次に、>の場合です。

2016_05_29_0_52
図2.6-d
リスト2.6-c
int eSize = 20;  //円の直径を設定する

size(400, 400);
background(255);
fill(255); //初めは白の塗りを設定

//xは0から始まって、ウィンドウの横幅以下の場合は繰り返され、
//繰り返すたびに20が加算されていく
for (int x = 0; x <= width; x += 40) {

  if (x > 200) {  //もし、xの値が200超だったら、

    fill(200, 0, 0);  //赤を設定
  }

  ellipse(x, height/2, eSize, eSize);  //円を描画
}

結果を見て分かるようにx = 200の時に処理が実行されるかされないかの違いが出ます。

2.6.3 else (さもなくば)

elseは、かならずif文とセットで使われます。if文で使ったサンプルをアレンジしてみましょう。if文で定義された条件式に当てはまらない場合は、elseの処理が実行されます。このサンプルでは、if文の条件に当てはまらない場合は青で描画するよう記述されています。

2016_05_29_1_01
図2.6-e
リスト2.6-d
int eSize = 10;  //円の直径を設定する

size(400, 400);
background(255);
fill(255); //初めは白の塗りを設定

//xは0から始まって、ウィンドウの横幅以下の場合は繰り返され、
//繰り返すたびに20が加算されていく
for (int x = 0; x <= width; x += 20) {

  if (x >= 200) {  //もし、xの値が200以上だったら、

    fill(255, 0, 0);  //赤を設定
    
  }else{  //さもなくば
    
    fill(0, 0, 255);  //青を設定
  }    
  
  ellipse(x, height/2, eSize, eSize);  //円を描画
}

構文は次のとおりです。

if(条件式) { 
  処理 
}else{
  処理 
}

処理の流れは次のとおりです。

if_else
図2.6-f

2.6.4 else if(もしくは〜だったら)

else ifを使うことによって更に複雑な条件分岐が可能になります。if、 else ifの2種類の場合、if, else if, elseの3種類を使う場合があります。

●ifとelse ifを使った場合

2016_05_29_2_46
図2.6-g
リスト2.6-e
int eSize = 10;  //円の直径を設定する
 
size(400, 400);
background(255);
fill(255); //初めは白の塗りを設定
 
//xは0から始まって、ウィンドウの横幅以下の場合は繰り返され、
//繰り返すたびに20が加算されていく
for (int x = 0; x <= width; x += 20) {
 
  if (x < 200) {  //もし、xが200未満だったら、
 
    fill(255, 0, 0);  //赤を設定
 
  }else if(x >= 200){  //xが200以上だったら
 
    fill(0, 0, 255);  //青を設定
  }    
 
  ellipse(x, height/2, eSize, eSize);  //円を描画
}

構文は次のとおりです

if(条件式) { 
  処理 
}else if(条件式) {
  処理 
}
if_elseif
図2.6-h

●if, else if, elseを使った場合

加えて、最後にelseを使うこともできます。ifとelse ifの条件に当てはまらなかった時に、elseの処理が実行されます。

2016_05_29_2_49
図2.6-i
リスト2.6-f
int eSize = 10;  //円の直径を設定する
 
size(400, 400);
background(255);
fill(255); //初めは白の塗りを設定
 
//xは0から始まって、ウィンドウの横幅以下の場合は繰り返され、
//繰り返すたびに20が加算されていく
for (int x = 0; x <= width; x += 20) {
 
  if (x < 200) {  //もし、xが200より少なかったら、
 
    fill(255, 0, 0);  //赤を設定
 
  }else if(x >= 300){  //xが300以上だったら
 
    fill(0, 0, 255);  //青を設定
    
  }else{  //さもなくば
    
    fill(0, 255, 0);  //緑を設定
  }
 
  ellipse(x, height/2, eSize, eSize);  //円を描画
}

構文は次のとおりです

if(条件式) { 
  処理 
}else if(条件式) {
  処理 
}else{
  処理 
}

処理の流れは次のとおりです。

if_elseif_else
図2.6-j

2.6.5 if文の落とし穴

if文は概念的には難しくないかもしれませんが、実際に使ってみると難しく感じることもあります。例えば、x = 200の時にだけ円を赤に塗りたいとします。次のサンプルを実行してみましょう。

リスト2.6-g
int eSize = 20;  //円の直径を設定する
 
size(400, 400);
background(255);
fill(255); //初めは白の塗りを設定
 
//xは0から始まって、ウィンドウの横幅以下の場合は繰り返され、
//繰り返すたびに40が加算されていく
for (int x = 0; x <= width; x += 40) {
 
  if (x == 200) {  //もし、xの値が200だったら、
 
    fill(255, 0, 0);  //赤を設定 
  }
 
  ellipse(x, height/2, eSize, eSize);  //円を描画
}

一見、このコードで良さそうです。しかし、結果はx >= 200と同じ結果になってしまいます。

2016_05_29_20_39
図2.6-k

これは、x == 200の時にfill(255, 0, 0)(赤を塗る)が実行されると、その後のコードで何も指定されなければ、この指示が継続されてしまうからです。
ですので、x == 200の時にだけ赤を塗りたい場合には、ifと合わせてelseを使う必要があります。

リスト2.6-h
int eSize = 20;  //円の直径を設定する
 
size(400, 400);
background(255);
fill(255); //初めは白の塗りを設定
 
//xは0から始まって、ウィンドウの横幅以下の場合は繰り返され、
//繰り返すたびに40が加算されていく
for (int x = 0; x <= width; x += 40) {
 
  if (x == 200) {  //もし、xの値が200だったら、
 
    fill(255, 0, 0);  //赤を設定 
    
  }else{
    
    fill(255);  //白を設定 
  }
 
  ellipse(x, height/2, eSize, eSize);  //円を描画
}

こうすると、x == 200以外は白になりました。

2016_05_29_20_42
図2.6-l

2.6.6 &&(かつ)

if文の中の条件文で使える演算子は、実は比較演算子だけではありません。
&&(かつ)や ||(もしくは)などの条件を設定することもでき、これらは論理演算子と呼ばれます。
比較演算子と論理演算子の組み合わせによって、非常に複雑なコードも記述可能です。
次のサンプルを見てください。
&&(かつ)は、英語の ANDと同じです。

2016_05_30_1_26
図2.6-m
リスト2.6-i
int eSize = 10;  //円の直径

size(400, 400);  //画面のサイズ
background(255);  //背景色(0~255)

//20ピクセルごとに繰り返す
for (int x = 0; x <= width; x += 20) {

  //条件式 1
  if (x < 100) {  //もし、xの値が100未満だったら

    fill(255, 0, 0);  //円の色を赤にする

    //条件式 2
    //100以上かつ200未満の場合
  } else if (x >= 100 && x < 200) {

    fill(0, 0, 255);  //円の色を青にする

    //条件式 3
  } else if (x >= 200) {    //200以上の場合

    fill(0, 255, 0);  //円の色を緑にする
  }

  ellipse(x, height/2, eSize, eSize);
}

ここで、それぞれの条件式がx座標のどの範囲を指しているかを確認してみます。

if_range
図2.6-n

条件式1は100を含まず、条件式2は100を含んでいます。このように、それぞれの条件式が示す範囲を重複させないようにすることが重要です。

2.6.7 ||(もしくは)

この論理演算子は、英語のORと同じ意味になります。

2016_05_30_16_07
図2.6-o
リスト2.6-j
int eSize = 10;  //円の直径

size(400, 400);  //画面のサイズ
background(255);  //背景色(0~255)

//20ピクセルごとに繰り返す
for (int x = 0; x <= width; x += 20) {

  //条件式 1
  //もし、xの値が100か300だったら
  if (x == 100 || x == 300) {  

    fill(255, 0, 0);  //円の色を赤にする
  } else {

    fill(255);  //それ以外は白
  }

  ellipse(x, height/2, eSize, eSize);
}

ちなみに、この論理演算子は一度に何回でも使うことができるので、こんな使い方もできます。

if (x == 100 || x == 200 || x == 300) {
  処理
}

条件式に使われる演算子が分からなくなった場合は「2.4.5 演算子の一覧」を参照してください。
2.4.5 演算子の一覧

2.6.8 &&と||の組み合わせ

これらの論理演算子は、組み合わせると更に複雑な条件を設定することができます。
次のサンプルを実行してみましょう。

リスト2.6-k
int eSize = 10;  //円の直径

size(400, 400);  //画面のサイズ
background(255);  //背景色(0~255)

//20ピクセルごとに繰り返す
for (int x = 0; x <= width; x += 20) {

  //xの値が100超の200以下、もしくは300だったら、
  if ((x > 100 && x <= 200) || x == 300) {

    fill(255, 0, 0);  //円の色を赤にする
  } else {    //それ以外のときには。

    fill(255);  //白にする
  }

  ellipse(x, height/2, eSize, eSize);
}

次のような結果になります。

2016_05_30_16_18
図2.6-p

2.6.9 for文のネストとの組み合わせ

それでは、今までに学習したfor文のネスト(入れ子構造)と組み合わせてみましょう。
次のサンプルを実行してみてください。

2016_05_30_16_24
図2.6-q

今までの実習を理解していれば、さほど難しい問題ではないですよね。

解答

リスト2.6-l
int eSize = 10;  //円の直径

size(400, 400);  //画面のサイズ
background(255);  //背景色(0~255)

//20ピクセルごとに繰り返す
for (int y = 0; y <= height; y += 20) {
  for (int x = 0; x <= width; x += 20) {

    //もし、xの値が100超かつ300未満だったら、
    if (x > 100 && x < 300) {

      fill(255);  //円の色を白にする
      
    } else {    //それ以外のときには。

      fill(255, 0, 0);  //赤にする
    }

    ellipse(x, y, eSize, eSize);
  }
}

 
それでは、次はどうでしょうか?これは、自分で考えてみてください。

2016_05_30_16_53
図2.6-r

解答

リスト2.6-m
int eSize = 10;
size(400, 400);
background(255);

for (int y = 0; y <= 400; y += 20) {
  for (int x = 0; x <= 400; x += 20) {

    //もし、xが100超の300未満、yが100超の300未満だったら、
    if (x > 100 && x < 300 && y > 100 && y < 300) {

      fill(255);  //白にする
      
    } else {   //それ以外は、

      fill(255, 0, 0);   //赤にする
    }

    ellipse(x, y, eSize, eSize);
  }
}

 
これまでの実習内容で、かなり複雑なパターンを作る事ができます。次のサンプルも、forとifしか使っていません。ここから先は、みなさんのアイデア次第です。

2016_05_30_20_14
図2.6-s

解答

リスト2.6-n
int eSize = 7;  //円のサイズ
float c;  //色彩用の変数

size(400, 400);  //画面のサイズ
background(255);  //背景色(0~255)
noStroke();

for (int y = 0; y <= height; y += 10) {
  for (int x = 0; x <= width; x += 10) {

    //左上
    //xが200未満, yの値が200未満
    if (x < width/2 && y < height/2) {

      c = map(x, 0, width/2, 0, 255);

      fill(c, 255, 255);  //シアン

      //右上
      //xが200以上, yの値が200未満
    } else if (x >= width/2 && y < height/2) {

      c = map(y, 0, height/2, 0, 255);

      fill(255, c, 255);  //マゼンタ

      //左下
      //xが200未満, yの値が200以上
    } else if (x < width/2 && y >= height/2) {

      c = map(y, height/2, height, 0, 255);

      fill(255, 255, 255-c);  //黄

      //右下
      //xが200以上, yの値が200以上
    } else if (x >= width/2 && y >= height/2) {

      c = map(x, width/2, width, 0, 255);

      fill(255, 255-c, 255-c);  //赤
    }

    ellipse(x, y, eSize, eSize);
  }
}

map()の使い方を忘れてしまった場合は、「2.5.5 for文を使用したグラデーション」を復習してみましょう。

2.6.10 if文と剰余を組み合わせる

剰余( % )というのはちょっと特殊で、「c = a % b」は「aをbで割った余りをcに代入する」という意味になります。
この場合、値は必ず整数になります。float型の変数に剰余の結果を代入しないようにしましょう。
言葉だけでは分かりにくいので、実例を見てみます。
次の例は、aが10でbが5〜10に変化していった場合の計算結果を表示しています。要は、整数同士の割り算の場合、割り切れない場合は余りが出ることになり、その余りの値がcに代入されます。

リスト2.6-o
int a = 10;
int b = 5;
int c; 

c = a % b;  // 10 / 5 = 2, 余り0
println("c = " + c);  //cを出力

b = 6;
c = a % b;  // 10 / 6 = 1, 余り4
println("c = " + c);  //cを出力

b = 7;
c = a % b;  // 10 / 7 = 1, 余り3
println("c = " + c);  //cを出力

b = 8;
c = a % b;  // 10 / 8 = 1, 余り2
println("c = " + c);  //cを出力

b = 9;
c = a % b;  // 10 / 9 = 1, 余り1
println("c = " + c);  //cを出力

b = 10;
c = a % b;  // 10 / 10 = 1, 余り0
println("c = " + c);  //cを出力

「まあ、なんとなく分かったけれど、これって一体何に使うの?」と思うかもしれませんが、この剰余は様々な場面で使用されます。その一例を挙げます。
次のサンプルでは、1ピクセルごとに白い縦線が描かれているのですが、iが3の倍数の時に赤、13の倍数の時に緑の線が描画されています。

mod
図2.6-t
リスト2.6-p
size(400, 400);
 
for (int i = 0; i < width; i ++) {
 
  if(i % 3 == 0) {  //iが3の倍数の時だけ実行
    stroke(255, 0, 0);
  }else if (i % 13 == 0) {  //iが13の倍数の時だけ実行
    stroke(0, 255, 0);
  } else {
    stroke(255);  //それ以外は白
  }
  line(i, 0, i, height);  //lineを描画
}

このように、設定された数値の倍数になった時の条件を記述する場合に非常に便利です。
自分で色々と数値を変えて試してみましょう。