臨機応変にふるまう(if文)

2019-04-23

本章のあらすじ

  • 条件分岐の必要性
  • Processingと処理分岐
  • 条件式をたくさん書いてみる

現実世界は臨機応変

現実世界は、状況に応じて行動を変えるもの、「もし〜(条件)なら〜(処理)する」であふれています。

  • もしお腹が空いていたら、ごはんを食べる
  • もし信号が赤なら、車を止める
  • もし外が暗くなったら、カーテンを閉める

プログラミングではこれを「条件分岐」と呼び、複雑な処理を実現するためには不可欠な概念です。

  • もし押したボタンが「ブラシ」なら、ツールをブラシに切り替える
  • もし選択中のツールがペンなら、線を引く
  • もし選択したメニューが「保存」なら、保存用のダイアログを表示する

もし〜なら: if

そんな条件分岐を実現するのが if 文です。

if ( 条件式 ) {
  // 条件を満たすときに実行されるブロック
}

if キーワードと丸括弧に続けて、処理を分岐するための条件式と、その条件を満たす場合に実行するブロックを続けて書きます。日本語で具体例を書くなら、例えばこんな感じです。

// もし、テストの点数が60点未満なら、補講を受ける
if ( テストの点数が60点未満 ) {
  補講を受ける
}
if文の流れ

条件式の書きかた

実際のコードで書きかたを見ていきましょう。

// もし mouseX が 300 より大きいなら
if ( mouseX > 300 ) {
  // 塗りを赤色に
  fill(255, 0, 0);
}

mouseX と数値 300 の間に比較用の記号 > が見えます。これには「比較演算子」という名前がついており、いくつか種類があります。どれもよく使うので覚えておいて損はありません。

条件式比較演算子意味
a == b==ab が等しい
a != b!=ab が等しくない
a < b<ab 未満
a > b>ab より大きい
a <= b<=ab 以下
a >= b>=ab 以上

それ以外なら: else

if文には、条件を満たす場合に実行するブロックがあると説明しましたが、その逆で条件を満たさない場合にのみ実行するブロックも書くことができます。 else キーワードをif文の直後に書き足します。

if ( 条件式 ) {
  // 条件を満たすときに実行されるブロック
}
else {
  // 条件を満たさないときに実行されるブロック
}

複数の条件分岐: else if

複数の条件式を書きたい場合、 else if というキーワードが使えます。

if ( 条件式A ) {
  // 条件Aを満たすときに実行するブロック
}
else if ( 条件式B ) {
  // 条件Bを満たすときに実行するブロック
}

else {
  // その他(条件Aも条件Bも満たさないとき)に実行するブロック
}

if文を書いてみよう

表現の幅を少しずつ広げていくために、いくつか新しい機能を紹介します。if文と組み合わせながら理解を深めていきましょう。

マウスのどのボタンが押されたか: mouseButton

Processingでは、最後に押されたボタンの種類を mouseButton で参照できます。 LEFT の場合は左ボタン、 RIGHT の場合は右ボタンです。条件式の == で等しいかどうかを判定します。

これを利用して、左ボタンでドラッグしたときは黒ペン、右ボタンでドラッグしたときは赤ペンになるようなお絵描きツールを作ってみましょう。

void setup() {
  size(600, 600);
  background(255, 255, 255);
}

void mouseDragged() {
  // もし押されたボタンが左なら
  if (mouseButton == LEFT) {
    // 線の色を黒色に
    stroke(0, 0, 0);
  }
  // もしそれ以外で、押されたボタンが右なら
  else if (mouseButton == RIGHT) {
    // 線の色を赤色に
    stroke(255, 0, 0);
  }

  // 線を引く
  line(pmouseX, pmouseY, mouseX, mouseY);
}

void draw() {
}
例:右ボタンで色が異なるペン

現在の時刻・経過時間

Processingには、現在の日時を数値として取得する機能が備わっています。

コード意味12時34分56秒のときの数値
hour()12
minute()34
second()56

さらにもうひとつ、 millis() はプログラムが起動してから経過した時間をミリ秒で取得できます。

いろいろ楽しめそうな予感がしませんか?例えば、 second() で得た秒数を2で割った余りを条件式に組み込めば、「偶数秒だけ色を変える」といった条件分岐が実現できます。

void mouseDragged() {
  // もし秒数が2で割り切れる(=偶数秒)なら
  if (second() % 2 == 0) {
    // 塗りを赤色に
    fill(255, 0, 0);
  } 
  // それ以外(=奇数秒)なら
  else {
    // 塗りを白色に
    fill(255, 255, 255);
  }

  ellipse(mouseX, mouseY, 100, 100);
}

(→second_pen

例:偶数ミリ秒だけ赤になるペン

(→millis_pen

高度な条件:複数の条件式の組み合わせ

条件式には、複数の条件を書くこともできます。複数条件を同時に満たす場合は && を、ひとつでも満たしていればよいのであれば || でつなげます。

書きかた読みかた意味
a == b && b == cANDab が等しい、かつbc が等しい
a == b || b == cORab が等しい、またはbc が等しい
// mouseX が 300 以下かつ、 mouseY が 300 以上のとき
if (mouseX <= 300 && mouseY >= 300) {
  
}

練習:条件式千本ノック

条件式に慣れるために、自分の頭で考える問題をいくつか解いてみましょう。まずは土台として、カーソルを動かすと黒色の円を描くスケッチを準備します。

void setup() {
  size(600, 600);
  background(200, 200, 200);
  noStroke();
}

void mouseMoved() {
  // 塗りを黒色に
  fill(0, 0, 0);
  ellipse(mouseX, mouseY, 100, 100);
}

void draw() {
}

このまま改造して、カーソルの位置に応じてあるところでは白色、あるところでは黒色となるようにif文を書いてみましょう。 fill() の部分を書き換えます。

void mouseMoved() {
  // もし  mouseX が 300 未満 のとき
  if (mouseX < 300) {
    // 塗りを黒色に
    fill(0, 0, 0);
  }
  else {
    // それ以外は白色
    fill(255, 255, 255);
  }

  ellipse(mouseX, mouseY, 100, 100);
}

カーソルのX座標で条件分岐したので、キャンバスの左右で色が綺麗に分かれました。さて、このまま条件式を書き換えて、以下のパターンの再現にチャレンジしてみてください。

(→patterns

レベルアップしていくとやりたいことも複雑になっていきますから、いつか複雑な条件式を書く局面が来るはずです。今のうちに仲よくなっておきましょう。

本章のまとめ

  • 現実世界には条件分岐がたくさん
  • Processingでは if文で条件分岐できる