初心者でも始められるプログラミング生活:第2回目~if文とは?条件に応じて処理をかえる!~
はじめに
前回は変数を使ったプログラムの組み方について学びました。変数を使うことによりその場その場の状態を保持することができました。
しかし、前回のようなプログラムでは毎回同じ処理しか行うことができません。ゲームを想像してみたらわかりますが、攻撃を食らったときやアイテムを拾ったときなど様々な場面に応じて処理を変えないといけません。今回は条件に応じて処理を変えるif文について扱っていきます。
if文
まずは実際にif文を用いたプログラムを見てどういったものなのか理解していきましょう。
void setup(){ int score = 100; if(score > 60){ println("合格"); } }
上のif(score > 60){ ... }にあたる部分がif文と呼ばれるものです。上のプログラムを実行させてみるとコンソール(下の黒い場所)に合格の文字が表示されたと思います。ではint score = 50;に変更して再び実行したらどうでしょうか?今度は何も実行されないはずです。
さあ、if文がどういうものなのかもう少し詳しく見てみましょう。if文は、
if ( 条件式 ) { 命令列; }
であらわされます。条件式の結果が正しいときに{ }ないで囲まれた命令列を実行し、正しくないときは命令列を実行しません。上のプログラムではscore > 60が条件式にあたりましたが、scoreに入っているのが100の時は100 > 60が成り立つために合格の文字が表示され、scoreに入っているのが0の時は0 > 60が成り立たないために何も表示されなかったわけです。
比較演算子
条件式では二つの値を比較することが多いですが、二つの値を比較するためには > のような比較演算子が必要です。以下に比較演算子をまとめた表を載せます。
比較演算子 | 例 | 説明 |
---|---|---|
> | a > b | aがbよりも大きい値か |
>= | a >= b | aがb以上の値か |
< | a < b | aがbよりも小さい値か |
<= | a <= b | aがb以下の値か |
== | a == b | aがbと等しい値か |
!= | a != b | aがbと等しくない値か |
以上や以下の判定をするときに>=や<=を使いますが、=>や=<のようなミスに気を付けてください。=は右側であることに注意!
また等しいかどうかを調べるときは==のように、=を二つ重ねます。x = yのように書くミスが初めは多いですが、これは代入文にになってしまうので気を付けましょう。
また、複数の比較演算をつなげたい場合は論理演算子を使います。
まずは具体的なプログラムを見てみましょう。
void setup(){ int score = 1500; if(score < 0 || score > 100){ println("不正な値です"); } score = 61; if(60 <= score && score <70){ println("合格ぎりぎりの点数です"); } }
最初のif文ではscoreの値が0点より下、または、100点より上の場合を表すために二つの比較演算を||で結んでいます。さらに次の文ではscoreの値が60点以上、かつ、70点未満の場合を表すために&&で結んでいます。
論理演算子 | 例 | 説明 |
---|---|---|
|| | a || b | aかbのどちらかが正しいとき、もしくはどちらも正しいとき |
&& | a && b | aとbの両方が正しいとき |
! | !a |
aが正しくないとき |
真偽値
正しいか正しくないかを真偽値と呼びます。正しいのをtrue(真)、正しくないのをfalse(偽)と言います。今までは正しい、正しくないでif文を実行するかしないか説明してきましたがいいかえれば、条件式がtrueの時に実行するといえます。この真偽値は変数に保存することもできます。
void setup(){ boolean isOk = true; boolean isNotOk = false; if(isOk){ println("OK"); } if(isNotOk){ println("not OK"); } if(!isNotOk){ println("not not Ok"); } }
真偽値を入れる変数に宣言する型はbooleanで、値に入れるのはtrueやfalseの真偽値だけでなく、比較演算などでも構いません。
上のプログラムではisOkにtrue(真)、isNotOkにfalse(偽)を入れているので、一つ目のif文は実行され二つ目のif文が実行されないのはわかると思います。ただ、三つ目のif文はどうでしょうか?一瞬isNotOkを使っているため実行されないように思えますが、! isNotOkとしています。このビックリマークは先ほどやった論理演算子の一種ですが、真偽値をひっくり返すものなのでfalseがtrueになり実行されます。
else文
条件を満たしているときの処理はif文を用いて書くことができましたが、条件を満たしていないときの処理を書く場面もあります。例えば先ほどのプログラムで、合格点以上の成績が取れなかった場合、つまり、60点より下の点数を取った場合に不合格と表示させたい場合はどうするのでしょうか。
ここで用いるのがelse文です。
void setup(){ int score = 50; if(score >= 60){ println("合格"); }else{ println("不合格"); } }
ifのあとに続けてelse{ 命令列; }とかくと、条件を満たさなかった場合の処理がかけます。上のプログラムではif文の中の条件式がscore >= 60なので、そうじゃない場合というのは score < 60となります。
else if文
条件が複数ある場合も考えられます。例えば、先ほどのプログラムの場合ではscoreが90点以上の時はA+と表示し、80点以上のときはAと表示し、70点以上のときはBと、条件を分けたい場合はどうすればよいのでしょうか。
ここで使うのがelse if文です。
void setup(){ int score = 70; if(score >= 90){ println("A+"); }else if(score >= 80){ println("A"); }else if(score >= 70){ println("B"); }else if(score >= 60){ println("C"); }else{ println("D"); } }
書き方はif文のあとにelse if ( 条件式 ){ 命令列; }を連ねて書きます。else ifは任意の個数つなげて書くことができます。上から順に条件式を見ていきますが、どこかの条件式を満たせば以降のelse if文の条件式は見ません。
上のプログラムではscoreに70が与えられているので、最初のif文で70 >= 90を見て正しくないのでelse ifに入ります。最初のelse ifでは70 >= 80を見てこれが正しくないために次のelse if文に行きます。ここで70 >= 70を満たすのでそこのif文の処理であるprintln("B")が実行されてコンソールにBが表示されます。
ここでAの成績を表示するときに条件式を80 <= score && score < 90にしなくてよいのかと思う人がいるかもしれません。もちろんそれでも動くのですがこれは冗長です。なぜかというと、前の処理でscore >= 90かどうかを見ているのでscore >= 80を見るころにはscore < 90であることが確定しているのです。
このような理由から調べる順番は大事なのです。同じようなプログラムですが以下のプログラムは間違ったプログラムです。
void setup(){ int score = 70; if(score >= 60){ println("C"); }else if(score >= 70){ println("B"); }else if(score >= 80){ println("A"); }else if(score >= 90){ println("A+"); }else{ println("D"); } }
一見同じプログラムに見えますが、これではBと表示されてほしいところがCと表示されてしまいます。そうです、最初のif文の条件式でscore >= 60を満たしてしまうためCが表示されてしまい、以降のelse if文は見られなくなってしまいます。このようにelse if 文を使う場合はつなげ方に気を付けましょう。
Processingでif文
if文の使い方を学んだところで、コンソールだけでなく動きのあるProcessing風なプログラムを書いてよりif文についての理解を深めていきましょう!
ループする四角
前回の動く四角形は画面を超えたら最後、一生もとには戻ってきませんでしたがif文を使えば帰ってくることができます。
int x = 0; int y = 100; void setup(){ size(500,300); noStroke(); //四角形の枠線を描画しない } void draw(){ background(255); //背景を真っ白に fill(52,152,219); //四角形のいろを青に rect(x,y,100,100); //四角形を描画 x = x +5; //ちょっとずつ右にずらす if(x > width){ //四角形が画面を超えてしまったら x = -100; //左端に戻す } }
if文の条件式のところにwidthという単語が出てきましたがこれはProcessingの特別な変数です。widthで返ってくる値は実行ウィンドウの幅です。ここではsize(500, 300);を指定しているために500が返ってきます。ちなみにheightという特別な変数もあり、こちらは実行ウインドウの高さが返ってきます。
このif文の条件式を満たしたとき、つまり四角形の左端が画面サイズを超えてしまったときにxの値を-100と左端に戻すことで四角形がループしているわけです。
まるばつクイズ
今度はマウスカーソルの場所に応じて処理を変えるプログラムを書いてみます。
void setup(){ size(500,500); noStroke(); //四角形の枠線を描画しない } void draw(){ rectMode(CORNER); background(255); //背景を真っ白に if(mouseX < width/2){ //もしマウスカーソルが真ん中より左にあったら //左側の背景を青色に fill(52,152,219); rect(0,0,width/2,height); //円を二つ重ねて中身がない円を描画 fill(255); //円の色を白に ellipse(width/4,height/2,100,100); fill(52,152,219); //円の色を青に ellipse(width/4,height/2,75,75); }else{ //そうでないとき、つまりカーソルが右側にあったら //右側の背景を赤色に fill(231,76,60); rect(width/2,0,width/2,height); //バツ印を描画。以下のプログラムはちょっとだけ複雑なので理解しなくて大丈夫! fill(255); rectMode(CENTER); translate(width/4*3,height/2); rotate(PI/4); rect(0,0,20,100); rotate(PI/2); rect(0,0,20,100); } }
またも新しい特別な変数が出てきました。mouseXです。mouseXは実行画面中のカーソルのx座標を返してくれる変数です。これを用いてif文の条件式を mouseX < width/2としているのでwidth/2、つまり幅の半分よりも左側にカーソルがあった場合の処理と、そうでないとき、つまりカーソルが右側にあった時の処理をelse文を使うことでわけています。ちなみに、mouseYという変数もありこちらはカーソルのy座標を取ってくることができます。
MYペイント
自分だけのお絵かきプログラムを書いてみましょう。
void setup(){ size(800,800); background(255); //背景を真っ白にするのは最初の一回のみ int r = 5; //ペンや消しゴムの太さ strokeWeight(r); //ペンや消しゴムの太さを設定 } void draw(){ if(mousePressed){ //もしマウスが押されていて if(mouseButton == LEFT){ //マウスの左ボタンが押されていれば stroke(0); //ペンの色を黒に line(mouseX,mouseY,pmouseX,pmouseY); //線をひく }else if(mouseButton == RIGHT){ //そうでなくてマウスの右ボタンが押されていれば stroke(255); //ペンの色を白に(消しゴムの役割) line(mouseX,mouseY,pmouseX,pmouseY); } } }
if文の中にif文を書くこともできます。最初のif文の条件式にあるmousePressedはProcessingの特別な変数でマウスのボタンが何かしら押されていたらtrueが、押されていなければfalseがかえってきます。
さらにmouseButtonというのも特別な変数でマウスで押されているボタンの種類(LEFT, RIGHT, CENTER)が返ってきます。左ボタンが押されているかどうか見たいときはmouseButton == LEFT、右ボタンが押されているかどうか見たい場合はmouseButton == RIGHTと書いてあげればオッケーです(すべて大文字であることに注意!)
if文の話とは関係ないですが、このプログラムではdraw()の中にbackground()をかかないようにしましょう。background()を書いてしまうと何も書けなくなってしまいます。このお絵描きを実装するにあたって、いままでかいた線を消さないで残しておくという手法をとっているためdraw()の中にbackground()を入れてしまうと毎回書いたものをそこで消されてしまうのです。それゆえ、かいたものを消す際には白いペンでなぞるという方法で実現しています。
pmouseX, pmouseYは1つ前のマウスカーソルの位置座標が返ってきます。1つ前の座標と現在の座標の間に線を引くことによってマウスカーソルの下に線を引いています。
課題
課題2ー1
一番下に行ったら一番上から再び出てくる、移動する四角形をかく。(「ループする四角」を参考に)
課題2-2
まるばつクイズの問題をコンソールに出力し、正しい正解の方をクリックすると"正解"とコンソールに出力し、間違った答えをクリックすると"不正解"とコンソールに出力するプログラムを作る。
課題2-3
お絵描きプログラムを発展させる。例えば、色を変えられるようにしたり、丸をかけるようにしたりなどなど。