※この記事は、「実はややこしくないif文(前編)」の続きです。
if文の練習:比較演算
……え、if文これで終わりですか!? イメージよりもだいぶ簡単で拍子抜けしちゃいました。
プログラミングにおいて、if文で躓く方は少なくないように思います。しかし、if文自体は本当に単純で、問題はifの中に何を書くかなのです。
なるほど……?
if文の理解のために、今回も問題を用意しました。今までのことを思い出しながら取り組んでみましょう。
はい!
まずは比較演算のif文です。次のプログラムの実行結果を予想してみてください。
int number1 = 100;
int number2 = 100;
if(number1 <= number2){
print("yes");
} else{
print("no");
}
丸括弧の中がtrueかfalseか、ってことですよね。number1もnumber2も中身は100だから、「100 <= 100」は「100は100以下ですか」って読めて、100は100を含んでるので、丸括弧の中はtrueですね。……ってことは、答えは「yes」です!
実行結果yes
その調子です。では2問目。
int number1 = 100;
int number2 = 100;
if(number1 < number2){
print("yes");
} else {
print("no");
}
「100は100より小さいですか」だけど、100は100より小さくない! つまり……falseだ! 答えは「no」です!
実行結果no
素晴らしいです。「<=」「>=」「<」「>」の使い方をきちんと覚えていますね。
比較演算はちょっとこんがらがったので、何回か復習し直しました。
では、もう1問だけ比較演算の問題を出しましょう。
int number1 = 200;
int number2 = 100;
if(number1 >= number2){
print("yes");
} else {
print("no");
}
number1は200でnumber2は100だから、「200は100以上ですか」になるので、文句なしのtrue。文句なしのyes。
実行結果yes
いいですね。
(そろそろ「天才の姫野さん」って言ってくれないかなー)
このように、比較演算は演算結果がtrueまたはfalseとなるので、丸括弧内に記述することができます。同様に、論理演算も丸括弧内に記述可能です。
if文の練習:論理演算
ってことは、次は論理演算とif文を組み合わせた問題をやるんですね!?
はい。実用的な例を挙げてみます。「東京または大阪在住のプレミアム会員向けの、期間限定キャンペーン」があるとして、その対象かどうかを判定するプログラムです。
bool isPremiumMember = true; //プレミアム会員:true
bool isExpired = false; //期限切れ:false
bool isLiveInTokyo = true; //東京在住:true
bool isLiveInOsaka = false; //大阪在住:false
if(isPremiumMember && !isExpired && ( isLiveInTokyo || isLiveInOsaka ) ){
print("キャンペーン対象");
} else {
print("キャンペーン対象でない");
}
何か一気にすごくカッコいいプログラムになりましたね!?
変数は効率的に用いましょう。まずはどこから演算すると思いますか?
ええと……。ifの丸括弧の中にある、( )の中でしょうか? ( )は優先順位が高いから。
その通りです。(isLiveInTokyo || isLiveInOsaka)はどうなるでしょうか。
バーバーは確か、「東京在住true」と「大阪在住false」にはtrueが含まれますか……ですよね。東京在住のほうにtrueが含まれてるから、trueを返します!
この時の状況はif(isPremiumMember && !isExpired && true)になりますね。
はい。それで次に計算するのは、「!」の演算子がついてる!isExpiredです! 期限切れfalseを逆転させるので、trueになりますね。そうすると、if(isPremiumMember && true && true)になるから……。
いい調子です。
まずは左側の「&&」から考えるとして、「プレミアム会員true」と「true」は両方ともtrueですか……。答えはtrueです。そうするとif(true && true)になりますよね。
仰る通りです。
「true」と「true」は両方ともtrueだから、if(true)ってことになりますね! そうしたら、ifのすぐ後ろの中括弧を実行するから、実行結果は「キャンペーン対象」です!
実行結果キャンペーン対象
(ドヤァ)
さすがは天才の姫野さんですね。
(「天才の姫野さん」やっときたー!)
ここで、「東京または大阪在住のプレミアム会員向けの、期間限定キャンペーン」 のif文の組み立て方を考えてみましょう。
あれ? 問題のコードと順序が違いますよね? でも、A && BとB && Aは実質一緒だから書く順番は別に気にしなくてもいっか。
基本的にはそう理解していただいて構いません。
基本的には?
はい。応用的な話になるので聞き流してもらっても構いませんが、厳密に言うと順番が大切になる場合があります。
なるほど? 天才なので何となくわかった気がします。
if文の練習:入れ子
では、そんな天才の姫野さんには、もう少し難しい問題を解いていただきましょう。
天才の姫野さんにお任せあれ!
こちらはif文の中にif文が入っている、「入れ子」の問題です。
bool readable = true; //読込可能
bool writable = false; //書込不可
if(readable){
print("読込可能");
if(writable){
print("読込可能・書込可能");
} else {
print("読込可能・書込不可");
}
} else {
print("読込不可");
if(writable){
print("読込不可・書込可能");
} else {
print("読込不可・書込不可");
}
}
えー、何ですかこれー! すごく複雑そう。
先程言った通り、if文そのものは単純です。実行結果はどうなると思いますか?
ぱっと見た印象なんですけど、多分「読込可能・書込不可」的なのが表示されるんですよね?
姫野さんは勘が鋭いですね。なぜそのように表示されるのか、考えてみましょう。
うーんと……。4行目のifから考えていくんですよね。readableはtrueだから、trueの時に実行する中括弧の中身も見なくちゃいけないわけですね。
はい。ですから、初めに「読込可能」を表示します。
で、その次に6行目の、入れ子になってるifを考えるんでしょうか。writableはfalseだから、elseより後ろの中括弧の中身を見るんですよね。そうしたら、「読込可能・書込不可」ですか?
そうなります。とすると、最終的な実行結果は?
「読込可能」と「読込可能・書込不可」の2つが出るんでしょうか?
実行結果読込可能
読込可能・書込不可
読込可能・書込不可
その通りです。では、類題として、readableをfalseに、writableをtrueに書き換えたものはどうなるでしょうか?
readable = false; //読込不可
writable = true; //書込可能
if(readable){
print("読込可能");
if(writable){
print("読込可能・書込可能");
} else {
print("読込可能・書込不可");
}
} else {
print("読込不可");
if(writable){
print("読込不可・書込可能");
} else {
print("読込不可・書込不可");
}
}
今の話の流れだと、「読込不可」「読込不可・書込可能」になりますかね。
そうですね。理由も説明してみてください。
4行目のreadableがfalseだから、5行目から10行目までは無視して、11行目にあるelseの後の中括弧の中身を実行します。そうするとまず「読込不可」って出て……。その後、writableを見るわけですが、これはtrueだから、ifの直後の中括弧の中身「読込不可・書込可能」が出ます。
実行結果読込不可
読込不可・書込可能
読込不可・書込可能
素晴らしいです。
中括弧の中身がどこまでなのかを意識したら、意外と簡単にできました!
姫野さんの仰る通りで、if文では中括弧の範囲を把握することがとても重要です。複雑な入れ子構造になったプログラムはあまりいいプログラムとはいえないのですが、if文を実際に扱うと、入れ子が複雑になる場合があります。しかし、その場合でも、中括弧の範囲を意識していれば、苦労することはありません。
if文、楽しいですね! readableとwritableのやつって、変数のtrueとfalseをちょっといじるだけで、表示させるものを自由に変えられるんですよね。おもしろいなあ。
はい。元々組み立てておいた式と結果が正しければ、変数を変えても結果は正しいままです。
何だかワクワクしちゃいます! カッコいいプログラムって感じがします!
(姫野さんの言う「カッコいいプログラム」って何なんだろう)
if文の実際:検索プログラム
先生、if文って実際にどんな感じで使われてるんですか?
例えば検索アプリで使われます。
そうなんですか? ちょっと書いてみたいです。どうやればいいでしょう?
それでは、テキストnekoの中に特定の言葉keywordが含まれているかどうかを検索するプログラムを組んでみましょうか。
検索するのって何を使えばいいんでしょうか?
containsを用います。A.contains(B)は「AにはBが含まれます」と翻訳でき、AにBが含まれていればtrueを、そうでなければfalseを返します。このcontainsを用いて、検索アプリを再現してみましょう。
なるほど! containsは文字列の検索で使える子なんですね!
以下に変数を用意しました。ifとcontainsを用いて、keyword1~3を検索するプログラムを書いてみてください。
String neko = "吾輩は猫である。名前はまだ無い。"
+ "どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所で"
+ "ニャーニャー泣いていた事だけは記憶している。";
String keyword1 = "猫";
String keyword2 = "ニャー";
String keyword3 = "にゃー";
頑張ってみます! containsは真偽値を出すからifの丸括弧の中に入れて……。else ifを使えばいいのかな? 便利だし。
if(neko.contains(keyword1)) {
print("$keyword1を含みます");
} else if(neko.contains(keyword2)) {
print("$keyword2を含みます");
} else if(neko.contains(keyword3)) {
print("$keyword3を含みます");
} else {print("いずれの検索ワードも含みません");
}
実行結果猫を含みます
あれー!? 本当は「ニャー」も含んでるのに、猫しか含んでない!
else ifを用いたからですね。else ifでは、ifの内容が実行される場合に、それ以降のelse ifの内容が実行されません。
そっか……。そうすると、普通にifを3つ使えばいいんでしょうか?
if(neko.contains(keyword1)) {
print("$keyword1を含みます");
}
if(neko.contains(keyword2)) {
print("$keyword2を含みます");
}
if(neko.contains(keyword3)) {
print("$keyword3を含みます");
}
実行結果猫を含みます
ニャーを含みます
ニャーを含みます
その通りです。
やったー! でも、言葉を1つだけ検索するときはこれでいいですけど、例えば「猫」「ニャー」「にゃー」のどれかが入ってるかとか、全部入ってるかとか知りたい時って、どうするんでしょう?
いい質問です。先程のプログラムに論理演算を少し組み込めば、AND検索やOR検索を行うこともできます。こちらがAND検索です。
if(neko.contains(keyword1) && neko.contains(keyword2) && neko.contains(keyword3)) {
print("「$keyword1」「$keyword2」「$keyword3」を全て含みます");
} else {
print("「$keyword1」「$keyword2」「$keyword3」を全ては含みません");
}
実行結果「猫」「ニャー」「にゃー」を全ては含みません
すごい! AND検索では「&&」が使えるんですね! ってことは、OR検索をしたかったら、「&&」を「||」に変えればいいんでしょうか? こんな感じで……。
コード if(neko.contains(keyword1) || neko.contains(keyword2) || neko.contains(keyword3)) {
print("「$keyword1」「$keyword2」「$keyword3」のいずれかを含みます");
} else {
print("「$keyword1」「 $keyword2」「$keyword3」のいずれも含みません");
}
実行結果「猫」「ニャー」「にゃー」のいずれかを含みます
はい、「||」を用いるとOR検索ができます。
ここで注意しておきたいのが、AND検索とOR検索の特徴です。AND検索の例では「全て含む/そうではない」ということは判別できますが、「全ては含みません」と表示された時の理由(どのキーワードが含まれていなかったのか?)はわかりません。同様にOR検索の例では「いずれかを含みます」と表示された時の理由(どのキーワードが含まれていたのか?)はわかりません。この特徴を理解して、先程のif文を3つ使う場合と上手く使い分けたり、組み合わせて使ったりしてくださいね。
ここで注意しておきたいのが、AND検索とOR検索の特徴です。AND検索の例では「全て含む/そうではない」ということは判別できますが、「全ては含みません」と表示された時の理由(どのキーワードが含まれていなかったのか?)はわかりません。同様にOR検索の例では「いずれかを含みます」と表示された時の理由(どのキーワードが含まれていたのか?)はわかりません。この特徴を理解して、先程のif文を3つ使う場合と上手く使い分けたり、組み合わせて使ったりしてくださいね。
わかりました! AND検索とOR検索を上手く使えば、例えばですけど、知り合いの男の子がどんな子なのかを登録しておいて検索するみたいなアプリも作れるんですかね?
……はい?
検索ワードに「イケメン」とか「天才」とか「料理上手」って入れると、「イケメンの検索結果:Aくん」「天才の検索結果:Bくん」「料理上手の検索結果:Cくん」「全てに該当:Dくん」みたいに出る感じの……。
なるほど……。でしたら、このようなプログラムはいかがでしょうか。
//検索ワード
String word1, word2, word3;
word1 = "イケメン";
word2 = "天才";
word3 = "料理上手";
//検索対象
String manA, manB, manC, manD;
manA = "Aくんはイケメンでお金持ち";
manB = "Bくんは天才で何でも卒なくこなす";
manC = "Cくんは料理上手で家庭的";
manD = "Dくんはお金持ちでイケメンで天才で料理上手だけど、ちょっとヴァイオレンス";
//word1の単体検索
print("「$word1」の検索結果");
if(manA.contains(word1)) { print("Aくんが該当します"); }
if(manB.contains(word1)) { print("Bくんが該当します"); }
if(manC.contains(word1)) { print("Cくんが該当します"); }
if(manD.contains(word1)) { print("Dくんが該当します"); }
実行結果Aくんが該当します
Dくんが該当します
Dくんが該当します
キーワードword1~word3を入力すると、その性質を持つ人物をmanA~manDから検索します。検索したい人物が増える度、変数などを入力し直す必要がありますが。
Dくんあなた……!
世の中に完全無欠な人はいないと僕は考えています。
(何か先生の闇を見た気がする)
「word1の単体検索」を参考にして、「word2, word3のAND検索」のプログラムを書いてみましょう。
頑張ってみます! まずは // でコメントを書いて……。改行したら、「「word2」かつ「word3」の検索結果」が出るように文字列結合。かぎ括弧に1つずつダブルクォーテーションを入れてくの地味にめんど……大変ですけど、DartPadで"を打つと自動的にもう1個"を打ってくれるのは嬉しいですね。
その調子です。if以下は「word1の単体検索」をコピーして改変するとよいでしょう。
そうします。word2とword3のAND検索だから「&&」で繋ぐとして……Aくんのifの中身、if(manA.contains(word2) && manA.contains(word3))で大丈夫ですか?
はい、合っていますよ。その次の中括弧はコピー元と同じままで結構です。
そしたらBくん以下も同じようにする、と。こんな感じでどうでしょう?
//word2,word3のAND検索
print("「$word2」かつ「$word3」の検索結果");
if(manA.contains(word2) && manA.contains(word3)) { print("Aくんが該当します"); }
if(manB.contains(word2) && manB.contains(word3)) { print("Bくんが該当します"); }
if(manC.contains(word2) && manC.contains(word3)) { print("Cくんが該当します"); }
if(manD.contains(word2) && manD.contains(word3)) { print("Dくんが該当します"); }
大変よくできています。実行結果は何になると思いますか?
天才で料理上手なのはDくんだけなので、「Dくんが該当します」が出ると思います。
実行結果Dくんが該当します
個人的にはDくんのこと検索結果から除外したいですね。
彼のような人材が必要になる場合もあります。
(また先生の闇が垣間見えた気が……)
では最後に、「word1, word3のOR検索」にも取り組んでみましょう。先程作成したコードをコピーして改変してみてください。
わかりました! まずはコメントと「検索結果」のところを変えて……。次はword2をword1にして、「&&」を「||」にする。これでどうでしょう! これは多分、AくんCくんDくんが出ますね!
//word1,word3のOR検索
print("「$word1」または「$word3」の検索結果");
if(manA.contains(word1) || manA.contains(word3)) { print("Aくんが該当します"); }
if(manB.contains(word1) || manB.contains(word3)) { print("Bくんが該当します"); }
if(manC.contains(word1) || manC.contains(word3)) { print("Cくんが該当します"); }
if(manD.contains(word1) || manD.contains(word3)) { print("Dくんが該当します"); }
実行結果
Aくんが該当します
Cくんが該当します
Dくんが該当します
非常に素晴らしいです。
やっぱりDくんは除外したい気もしますけど。むしろ「要注意人物」みたいに表示させたい気もしますけど。そういうのって作れますか?
可能ですよ。姫野さんは当初、「プログラミングでハッカーのようなことがしてみたい」と仰っていたかと思いますが、今はもう少し具体的に、例えば、複雑な検索をおこなうプログラムを組んでみたいと思いますか?
ちょっと興味あるかも……?
目標があることはとてもよいことです。次回は検索とも関連してくる「リスト」についてお話ししようと思っています。
ちょっと難しそうな気配もしますが、楽しみです!
if文の復習もお忘れなく。
わかりました!
今回のまとめ
【付録】ジャンケンゲーム
最後に、if文を用いた実用的なプログラムを用意しました。ジャンケンを見守るプログラムです。
えっ、if文だけでジャンケンできちゃうんですか!?
if文だけではありませんが、その解説は追々。試しに動かしてみてください。
すごい! プレイヤー2人がジャンケンするんですね! ちゃんと勝ったり負けたりあいこになったりしてます!
でもこれ、どういう仕組みなんですか?
以下にコードを示します。
import 'dart:math' as math;
void main() { int hand1;
hand1 = math.Random().nextInt(3); //0〜2の整数をランダムに生成
print("ランダム数字 プレイヤー1:$hand1");
if(hand1 == 0){
print("プレイヤー1 グーを出しました");
} else if(hand1 == 1){
print("プレイヤー1 チョキを出しました");
} else {
//0でも1でもない場合は、絶対に2
print("プレイヤー1 パーを出しました");
}
print("");
int hand2;
hand2 = math.Random().nextInt(3); //0〜2の整数をランダムに生成
print("ランダム数字 プレイヤー2:$hand2");
if(hand2 == 0){
print("プレイヤー2 グーを出しました");
} else if(hand2 == 1){
print("プレイヤー2 チョキを出しました");
} else {
//0でも1でもない場合は、絶対に2
print("プレイヤー2 パーを出しました");
}
print("");
if(hand1 == hand2){
print("あいこです");
} else if(hand1 == 0){
if(hand2 == 1){
print("プレイヤー1の勝ちです");
} else {
print("プレイヤー2の勝ちです");
}
} else if(hand1 == 1){
if(hand2 == 2){
print("プレイヤー1の勝ちです");
} else {
print("プレイヤー2の勝ちです");
}
} else if(hand1 == 2){
if(hand2 == 0){
print("プレイヤー1の勝ちです");
} else {
print("プレイヤー2の勝ちです");
}
}
}
カッコいいー!!
if文が随所で用いられていることが確認できたでしょうか?
思ってた以上にifだらけでした! 「○○の勝ちです」を表示するのはイメージしやすいですけど、グー、チョキ、パーのどれを出すかもelse ifで決められるんですね!
はい。if文はそれ単体ではなく、様々な構文と組み合わせて用いられることが多いですね。
あ、よく見たら勝ち負けのところでelse ifの中にif elseが入ってます!
さすがは天才の姫野さん、ご慧眼です。勝敗判定は特にこだわったポイントで、else ifの中にif elseを入れ込んだ構造にしてあります。変数hand1の値を0、1、2と順番に表記してあり、変数hand2との組み合わせ方や、どちらが勝つのかが一目瞭然です。else if の中でif elseを用いずに全ての勝敗パターンを列挙する方法もありますが、こちらのほうがシンプルで美しいと思いませんか? また、タブがあると見やすいというのもよくわかるかと思います。
(先生がかつてないほどに生き生きとしている……!)
姫野さん、いかがでしょうか?
すごいです。カッコいいです。こういうの、わたしも書けるようになれるでしょうか?
可能ですよ。一つ一つ積み重ねていくことが重要です。一緒に頑張っていきましょう。
はい、頑張ります!