ロボットに複雑な動作をさせようとすると、 当然プログラムの方も複雑になってきます。 そこでプログラムが複雑になっても デバッグ(プログラムの間違い探し)がしやすく、 また改良もしやすいように、 なるべく一連の動作を部品にわけて記述しましょう。 以下部品に分かる方法をいくつか紹介します。 目次 #contents * 6.1 サブルーチンを使う [#d4e4939d] #define TURN_TIME 200 // 旋回に必要な時間 sub turn_left() { OnRev(OUT_A); OnFwd(OUT_C); Wait(TURN_TIME); Off(OUT_A+OUT_C); } sub turn_right() { OnFwd(OUT_A); OnRev(OUT_C); Wait(TURN_TIME); Off(OUT_A+OUT_C); } task main() { OnFwd(OUT_A+OUT_C); Wait(300); // 3秒間直進 turn_left(); // 左に曲がる OnFwd(OUT_A+OUT_C); Wait(300); // 3秒間直進 turn_right(); // 右に曲がる } サブルーチンを定義するには sub というキーワードを使います。 * 6.2 関数を使う [#a7a6e4cb] #define TURN_TIME 200 void turn_left() { OnRev(OUT_A); OnFwd(OUT_C); Wait(TURN_TIME); Off(OUT_A+OUT_C); } void turn_right() { OnFwd(OUT_A); OnRev(OUT_C); Wait(TURN_TIME); Off(OUT_A+OUT_C); } void go_straight(int t) // 関数は引数を取ることができる { OnFwd(OUT_A+OUT_C); Wait(t); // t/100 秒直進する Off(OUT_A+OUT_C); } task main() { go_straight(300); // 3秒間直進 turn_left(); // 左に曲がる go_straight(300); // 3秒間直進 turn_right(); // 右に曲がる } C言語などでは、関数が返す値の型 (例えば int や double) を関数の名前の前に書きます。 一方、例えば、ある文字列を表示するだけ、という関数のように値を返さない関数の場合には void というキーワードを 書きます。 ところで実は NQC の場合、値を返す関数というのがサポートされていないので、 全ての関数が void という型なります。 もし何かの値を返したい場合には、その値を大域変数として定義しておいて 関数の中でその変数に値を代入するようにすれば、 一応同等のことができます。 また、サブルーチンと違って関数はコンパイル時に展開されてしまうので、何度も関数を呼ぶようなプログラムを書けば、プログラムのサイズがとても大きくなってしまいます。 6.3 マクロを使う #define TURN_TIME 200 #define turn_left OnRev(OUT_A);OnFwd(OUT_C);Wait(TURN_TIME);Off(OUT_A+OUT_C); #define turn_right OnFwd(OUT_A);OnRev(OUT_C);Wait(TURN_TIME);Off(OUT_A+OUT_C); #define go_straight(t) OnFwd(OUT_A+OUT_C);Wait(t);Off(OUT_A+OUT_C); task main() { go_straight(300); // 3秒間直進 turn_left; // 左に曲がる go_straight(300); // 3秒間直進 turn_right; // 右に曲がる } 定数を定義するのと同じように、#define を使ってマクロを定義することができます。 しかし、サブルーチンや関数と違って必ず一行で書く必要があります。 また関数と同様にマクロは引数を取ることができます。 そして、これも関数と同様、マクロはコンパイル時に展開されます。 ★ 練習問題 6.4 これまでに書いたプログラムを サブルーチンや関数やマクロを使って わかりやすいプログラムに書き換えなさい。