いきなりですが問題です.Cで書かれた,次のコード断片をご覧ください.
while (n > 0) { /* nの値を出力 */ m = marble(n); /* pが0なら「Alice」,1なら「Bob」を出力 */ /* 何個取ったかを出力 */ n = n - m; p = 1 - p; }
marbleは,おはじきのことです(おはじき取りのゲームのルール,ナレーションやり直しにルールを書いています).「m = marble(n);」は,おはじきの残りの数nに対して何個取るかを(関数marbleで計算して,その結果を)mに代入し,「n = n - m;」により,おはじきの残りの数を減らします.
では「p = 1 - p;」は何を行うのでしょうか.
さっそくですが解答です.3行前に「pが0なら「Alice」,1なら「Bob」を出力」と書かれています.そこでpのとり得る値は,0と1のいずれかとみなします.そうすると,「p = 1 - p;」により,pの値は,0なら1に,1なら0になります.より具体的にはこうです.
- この式を評価する前の,pの値が0なら,p = 1 - 0で,1がpに代入されます.
- この式を評価する前の,pの値が1なら,p = 1 - 1で,0がpに代入されます.
先週の授業で解説を行いました.また上記のコード(コメントはprintfなどにして)は,昨年度と今年度の第2クォーター科目の最終回に公開した,プログラミング科目の「Cコース」向け説明資料に,第3クォーターの科目ではこういうコードを含むプログラムを作成・実行しますと,解説していたのでした.
「p = 1 - p;」であり,「p = p - 1;」ではありません---これだと,whileループの繰り返しの回数だけ,pを1ずつ減らしていくことになります.
授業から離れ,ただしint型の変数pが0と1のいずれかしかとらないと仮定して,反転させるコードは,他にいくつか考えられます.最も字数が短い*1のは「p = !p;」です.1増やして,2になったら0にするという方針で,式を書くなら,「p = (p + 1) % 2;」で,これは少しアレンジして他の課題に取り入れました.排他的論理和の演算子を使用して「p = p ^ 1;」と書くこともできます.1つの式にとらわれなければ,「if (p == 0) { p = 1; } else { p = 0; }」や「if (p) p = 0; else p = 1;」というのも認められます.後者のif文をもとに三項演算子で書き換えると,「p = p ? 0 : 1;」となります.
しかしながら,「おはじき取りのゲームのプログラム」を学習してもらうにあたり,「p = 1 - p;」を他のコードに置き換えよという課題は,良いものとは言えません.むしろ,「手番の交代(AliceからBobに,BobからAliceに)」を,変数を使ってどのように表現すればよいかを学ぶことが,最も大事です.
直接的にはif~elseですが,中括弧も含めると5行のコードを,1行に減らせるというのが,「p = 1 - p;」の面白いところと,思っています.「p = p - 1;」との違いは,(面白さの)2番目の要素です.
昨年度の105分×7回の授業の資料の説明内容は,先週のうちに終わってしまいまして,今週木曜,第8回の授業資料を新たに作成中です.課題も新作となります.まずはサポート教員とTAに見てもらい,最終調整と,水曜にナレーションを行い,授業日に視聴やダウンロードなどをしてもらいます.
クォーター科目・セメスター科目のいずれも,来週木曜は予備日となっています.1年生は引き続き履修する,第4クォーターのプログラミング科目は再来週からです.
*1:空白文字は字数に入れないものとします.