3.制御構文


3−1.条件判断文

単なるイベントシーンではなく、ゲームの動作を制御しようとした場合には、「○○だった場合には××する」というプログラムが必要になります。 以下のように記述します。

===============
if (height>=1500) { //heightの値が1500以上ならば以下の行を実行
    //何かの処理を記述、上記の式が成り立つ場合のみ実行される。
}
===============

ifで始まる記述を『if文』または『条件判断文』と呼びます。中括弧「{〜}」の中には一つまたは複数の文が記述できます。

2つの値の比較だけでなく、式を記述できるため以下のような記述も可能です。この式のことを『条件式』と呼びます。

===============
if (hp<50 || gettime(0)>300) {  //hpの値が50未満になるか、
                                //経過時間が5分を超えたら以下の行を実行
    何かの処理を記述、上記の式が成り立つ場合のみ実行される。;
}
===============

条件式の計算結果が真になる場合のみ、中括弧「{〜}」の中が実行されます。四則演算と変数の項で出てきた論理演算子は、主にこのif文と、後述の繰り返し文で使用します。

条件式の値が偽になる場合の処理を記述することが出来ます。

===============
/*xの絶対値をaに代入します。*/
if (x<0) {  //xが負の値なら以下の行を実行
    a=-x;   //xが負の値なのでマイナスの値をaに代入する。結果的にaはxの絶対値になる。
} else {    //xがゼロ以上なら以下の行を実行
    a=x;    //xが正の値なのでそのままaに代入
}
===============

elseの次にifを記述することも、if文の実行内容の中にさらにifを記述することも出来ます。

===============
if (条件式1) {
    条件式1が真のときに実行される内容;
    if (条件式2) {
        条件式1が真で、条件式2も真の時に実行される内容;
    }
} else if (条件式3) {
    条件式1が偽で、条件式3が真のときに実行される内容;
} else {
    条件式1が偽で、条件式3も偽のときに実行される内容;
}
===============

上記のプログラムは条件判断後の記述を括弧で囲っていますが、1行だけの場合は括弧は不用です。以下のように記述することも出来ます。

===============
if (x<0) a=-x;
else a=x;
===============

この記述は文法上は100%正しいですが、「読みにくいし、他人がいじるときに間違えやすい」という理由から推奨していない人もいます。このようにしたほうが読みやすくなる、という特別な理由がある場合を除いては、{}を使うほうがいいかもしれません。


3−2.繰り返し文

同じ処理を複数回実行したい場合、一番単純な方法は同じ内容を何度も書くことです。

===============
print_string("この文字列を4回表示します。\n");
print_string("この文字列を4回表示します。\n");
print_string("この文字列を4回表示します。\n");
print_string("この文字列を4回表示します。\n");
===============

では、50回表示したい場合はどうでしょうか?50行同じ内容を書く方法が非常識なのは分かると思います。ここでは「50回繰り返す」というための機能が欲しくなります。 具体的には以下のように記述できます。

===============
count=0;                    //カウンタに使う変数を初期化
while(count<50) {           //iが50未満の間はループを実行
    print_string("この文字列を50回表示します。\n");
    count ++;               //何回目の処理が終わったか計算する。countに1を加算する(インクリメント演算子)。
}   //whileの書いてある行へ戻る
===============

上記のwhileで始まる一連の記述を『while文』または『繰り返し文』と呼びます。 whileの()の中の条件式が真である限り、次の{}で囲まれた内部を何度でも繰り返して実行します。 なお、条件判断を繰り返して実行する部分を指して『whileループ』などと呼ぶ場合があります。 上記の例ではcountという変数名を使用していますが、変数や式は何でもかまいません。 初期化して、1づつ加算しながら、50回実行するまでループします。

while文は以下の構文をとります。

===============
while (ループするかどうか毎回評価される式) {
    この中身が何度も実行される;
}
===============

上記のwhile文だけで全てのループプログラムは記述できますが、以下の構文を使うことでまとめて書くことが出来ます。

===============
for (count=0 ; count<50 ; count++) {
    print_string("この文字列を50回表示します。\n");
}
===============

上記のforで始まる一連の記述を『for文』と呼びます。これも繰り返し文の一つですが、紛らわしいので、一般的には「while文」「for文」という呼び方のほうを使います。 while文の繰り返し部分をwhileループと呼ぶのと同様に、for文の繰り返し部分を『forループ』と呼ぶことがあります。 ちょっと分かりにくいのですが、ifの次の()の中のセミコロンで分けられた箇所は、それぞれ以下のような役割があります。

===============
for (最初に1回だけ実行される式 ; 毎回ループの前に評価される式 ; 毎回ループの最後に実行される式) {
    この中身が何度も実行される;
}
===============

慣れればかなり複雑な制御が出来ますが、大抵の場合は以下のような形で使います。

===============
for (変数名=0 ; 変数名<繰り返し回数 ; 変数名++) {
    繰り返し実行する内容;
}
===============

これは以下のように書いても同じで、一見すると「1回目」から数えるので自然のようにも思えますが、あまりこういう書き方はしません。 コンピュータの基本的な発想として「ゼロから物を数える」というルールがあるからでしょう。後述の添え字もゼロから数えるので、合わせておいたほうが良いです。

===============
for (変数名=1 ; 変数名<=繰り返し回数 ; 変数名++) {  //プログラム上は全く正常に動く
    繰り返し実行する内容;
}
===============

上の例では変数名にcountを使用していますが、毎回countと書くのが面倒だからか、特に回数指定以外の強い意味の無いforループの場合、専らi、j、k...という変数名を使います。 また、if文同様に何重にも重ねることが出来ます。このように重ねることを『入れ子にする』または『ネストする』などと呼ぶことがあります。

===============
for (i=0 ; i<10 ; i++) {
    for (j=0 ; j<10 ; j++) {
        for (k=0 ; k<10 ; k++) {
            繰り返し実行する内容;
        }
    }
}
===============

ループの外であれば同じ変数名が使えますが、多重ループの中で同じ変数を使うと正しい動作をしないので注意してください、上級者でもやってしまいがちなミスです。

===============
for (i=0 ; i<10 ; i++) {
    繰り返し実行する内容;
}
for (i=0 ; i<10 ; i++) {    //上のforループの外なので同じ変数名を使えるが・・・
    for (j=0 ; j<10 ; j++) {
        for (k=0 ; k<10 ; i++) {    //ここで間違えてiをインクリメントしているので、無限ループしてしまう。
            繰り返し実行する内容;
        }
    }
}
===============

whileもforも、ちょっと記述を誤ると簡単に無限ループに陥ってしまうので、よく処理を考えて使ってください。

なお、while文、for文も、if文同様に、{}なしで、ループ内容を1行だけ指定することが出来ます。 ただしif文の時と同じく、「読みにくく間違えやすい」という理由から、以下の書き方を推奨していない人もいます。

===============
/*変数fが1未満になるまで割り続ける(while文で{}を使わないことはあまり見ません)*/
f=123.0;
while(f>1.0) f/=2;

/*25回繰り返し(for文の{}を使わない場合は頻繁に見られます)*/
for (i=0;i<25;i++) print_string("この文字列を25回表示する\n");
===============

なお、if文、while文、for文をひっくるめて『制御構文』と呼ぶことがあります。 「コンパイル時に決められた順番にしたがって、1ステップずつプログラムを実行する」というルールから逸脱して、条件次第で下に飛んだり上に戻ったりできるのは制御構文だけという特徴があります。


3−3.意図的な無限ループ

練習プログラムでは絶対にありえませんが、実用のゲームの主処理を行う場合など、意図的に無限ループを記述することがあります。具体的には以下のように記述します。

===============
while(1)
{
    system();    //システムに処理を返さないと本当に無限ループしてハングアップするので、ここで処理を一旦返す。
    /*
    ゲームの処理
    */
}
===============

while文の条件式の部分が「1」となっていますが、SphereScriptの仕様として「0以外」は必ず真となり「0」は必ず偽となります。そのため、while(1){...}と記述することで、無条件でループすることになります。


3−4.ループからの脱出と再開

本格的なプログラムを書く段階になると、頻繁に使うことになるループですが、ループの終了判断が1箇所というのは意外に不便です。具体的にはこんなとき。

===============
while(1)
{
    ...
    if (time>600) {
        タイムアップのメッセージ表示;
        ここでwhileループを抜けたい;      ←こんなとき!
    }
    ...別の処理がたくさんある
}
===============

『break文』により、この処理を記述できます。

===============
while(1)
{
    ...
    if (time>600) {
        ...     //タイムアップのメッセージ表示処理
        break;  //whileループを抜ける
    }
    ... //別の処理がたくさんあるが、タイムアップ後には実行したくない。
}
//上記のbreakでここにジャンプしてくる
===============

breakを使うことにより、一つ上のwhileループまたはforループの下へジャンプします。if文のネストは無視されます。複雑なbreakの例を挙げます。

===============
while(1) {
    for (i=0;i<256;i++) {
        ...         //何かの処理(下記のbreakが実行された場合、ここはもう実行されない。)
        if (i>=128) {
            if (get_hp(i)==0) {
                break;
            }
        }
    }
    //上記のbreakでここにジャンプしてくる。
}
===============

ループを抜けるのではなく、最初に戻りたい場合は『continue文』が使えます。break文がループの外へジャンプするのに対して、continue文はループの最後にジャンプします。

===============
while(1) {
    ...         //何かの処理
    if (get_hp(2)<=50) {
        continue;
    }
    ...         //何かの処理(上記のcontinueが実行された場合、ここは実行されない。)
    //上記のcontinueでここにジャンプしてくる。
}
===============

通常、ゲームのイベント処理などではbreakやcontinueを使うことはまずありませんが、システム記述を行おうとすると必須の機能となります。存在だけは覚えておいて、必要になったら読み返して試してみてください。


最初のページへ戻る