ループ文その2

ループ文を途中で抜け出したいと思うときがあると思います。
そんなときのための構文もACSでは用意されています。
また、ループ文その1で紹介した方法以外にもループの方法はあります。
また、このページでは、文字列と配列の組み合わせることによって文字列を使う方法を紹介します。
※第二版の流用がほとんどです。(^_^;)


break文(ループ文からの脱出)

ループ文では条件を偽(FALSE)にしてループ文から脱出する方法以外にもループ文から脱出する方法があります。
ループ文の中に次の言葉を付け足しましょう。

break;

ループ文の途中で、breakと出会ったとき、そのループ文から強制的に脱出して、ループ文は終了します。
(ループ文の次の行に移ります。)

(ちなみに、switch文でbreak文を見かけましたよね。役割は大体同じだと思います。)

例を見てみましょう。


#include "zcommon.acs"

//ENTERではなく(void)になっています。
Script 1 (void)
{

//Tidが999のモンスターが存在していればループを続けます。
while(ThingCount(0,999) > 0){

if(GameSkill () == SKILL_VERY_HARD)break;

//{,}を省略していますが、if文の内容はbreak;で終わりです。

delay(35*5);

Thing_Spawn(100,T_MEDKIT,0,0);

}
}

//GameSkill関数・・・現在のゲームのスキルに対応する値を返します。
//SKILL_VERY_HARDは"Nightmare!"を表す定数です。


このScriptの目的は、
「5秒おきにTidが999のモンスターの生存数を確認して、生存していればTidが100のMapSpotにMedikitを出す。」です。
ただし、難易度が"Nightmare!"のときには、Medikitは出ません。

実際に実行してみると・・・(Baron of HellがTid999のモンスターです。)

難易度が"UltraViolence"のとき。
Medikitが出ます。(画面中央)
難易度が"Nightmare!"のとき。
Medikitが出ません。

例のように、通常はif文と組み合わせて使います。

このように、break文は、すぐにループ文から脱出させる役割を果たしています。


continue文(ループ文での繰り返し)

ループ文の最後まで進むと、ようやくもう一度ループしますが(条件が真の場合)、ループ文の途中でも強制的にループ文のはじめまで戻ることができます。
ループ中に次の言葉を付け足しましょう。

continue;

ループ文の途中でcontinueに出会ったとき、そのループのはじめの部分から実行し直します。
ループをループ文の途中で起こそうとするときに便利です。
ただし、ループのための条件の確認や、for文で与えられている制御用の変数に与える操作などは実行されます。
無条件でもう一度ループというわけではありません。

具体例ですが、私が知る限り、ACSでほとんどcontinue文を見かけないので(使わないので)、重要性は(ACSでは)低いと思います。
骨組みだけを紹介します。(第二版で具体例が無かったのも理由ですが・・・)


while(/*条件1*/){

//内容1

if(/*条件2*/)continue;
//条件2が真なら内容2へ進めない。
//{,}を省略していますが、if文の内容はcontinue;で終わりです。

//内容2

}


こんな感じでif文と組み合わせて使います。
(余談ですが、旧Mars Flag(invasion風のあれです。)ではif文と組み合わせてさりげなくcontinue文を使っています。)

このように、continue文は、すぐにループ文のはじめまで戻す役割を果たしています。


do while(until)ループ

do while(until)ループはほとんどwhile文(until文)と同じですが、
「ループするための条件を一度だけ無視して、ループ文を実行する。」
という特徴を持っています。
つまり、初めてwhile文(until文)に入るときに調べるループのための条件を無視してループの内容を実行します。(その後はwhile文(until文)と同じです。)

これも骨組みだけ紹介します。


do{

//内容

}while(/*条件*/);
//最後のセミコロンを忘れずに


do{

//内容

}until(/*条件*/);
//最後のセミコロンを忘れずに


この場合、最初の1回目は必ず"内容"が実行されます。

do whileループとdo untilループの違いはwhile文とuntil文の違いと同様「ループのための条件の真偽の違い」です。


restart文

restart文を使用すると、実行しているScriptを最初からもう一度やり直すことができます。
具体例を見て下さい。


#include "zcommon.acs"

Script 1 ENTER
{
HealThing (5);
//プレイヤー(このScriptの起動者)の体力が5回復します。
delay(1);
restart;
//Scriptをやりなおします。
}


スタート地点の付近にSpiderMastermindを配置してテストプレイをしてみます。

こんな感じでボコボコにやられても死ぬことはありません。
なぜそうなるか、さきほどのACSを見てみましょう。

HealThing (5);

はプレイヤーの体力が5回復する関数です。(回復の対象はこのScriptを起動したThingです。ENTER型のScriptの起動者はPlayerでしたよね。)

delay(1);

はこのScriptを1/35秒だけ停止させる関数です。

restart;

このrestart文にやってくると、このScriptは最初から実行され直されます。
つまり、
「5回復」→「1/35秒待機」→「5回復」→...
という操作を永遠に行っています。
つまり最大で毎秒175まで体力を回復することができるのでボコボコにやられても大丈夫だったわけですね(^_^;)

ループ文の時も述べましたが、同じ時間帯で永遠にループする仕掛けを作らないようにしましょう。
途中でdelay関数を挟むなどして必ず時間帯をずらしてください。

このように、restart文は、Scriptを最初から実行し直させる役割を果たしています。

ループ文で言うcontinue文に対応しています。


terminate文

terminate文を使うと、現在実行しているScriptを終了させることができます。
さきほどのrestart文のACSに次の様な一文を追加しましょう。


#include "zcommon.acs"

Script 1 ENTER
{
HealThing (5);

if(!ThingCount(0,999))terminate;
//{,}の括弧は省略していますが、terminate;の部分のみがif文の内容です。

delay(1);
restart;
}


さきほどのSpiderMastermindのTidをすべて999にしてテストプレイをしてみましょう。

チートコードなどを使ってSpiderMastermindを全員倒すと・・・

このように、体力が回復しなくなります。

赤い字の部分を見てみましょう。

if(!ThingCount(0,999))terminate;

どこかで見たことがあるような構文ですよね。
ただし、ThingCount関数の手前に"!"演算子があることに注意して下さい。
"!"演算子の役割は「右オペランドが0でないなら0を、0なら1を返す」です。
つまり、SpiderMastermindが全滅したらterminate文が実行され、実行しているScriptが終了します。
(このために、体力が回復しなくなったわけですね。)

このように、ternimate文は、Scriptをその場で終了させる役割を果たしています。

ループ文で言うbreak文に対応しています。


文字列・配列とループ文

変数の型の章(その6)でstr型の実用的な使い方はループの章で紹介すると書きました。
ここでは、実際にループ文と配列と文字列を組み合わせてACSを作っていきます。

まずは文字がカウントダウンされるScriptを作ってみましょう。


#include "zcommon.acs"

str countdown[3] = {"One","Two","Three"};

//カウントダウン中に表示される文字列。

Script 1 ENTER
{
for(int counter=2;counter>=0;counter--){

//counter--になっていることに注意。

print(s:countdown[counter]);
//ここでカウントダウンの文字列を表示する。
//配列の要素を指定する番号(添え字)は変数でも良い。

delay(35);
//Scriptを1秒(35/35秒)停止させる。

}

print(s:"Fight!");
}


このACSを実行すると、

と1秒間隔で表示されます。
(文字列が配列と組み合わされている点を除けば、構造は今までのループ文と変わりません。)

このように、文字列を変数として扱うときは、配列を組み合わせて使うことがほとんどだと思います。(これは私感ですのでもちろん例外はあります。)

この例のACSを応用すれば文字列と配列の組み合わせは大抵作れます。あとは自分なりに作ってみて下さい。


まとめ

・break文を実行するとループ文から強制的に脱出する。
・continue文を実行すると強制的にループ文の最初の行まで戻る。
このとき、ループのための条件の確認や、for文で与えられている制御用の変数に与える操作などは実行される。
・do while(until)ループを実行すると、ループのための条件を一度だけ無視してループする。そのほかの点はwhile(until)文と同じ。
・restart文を実行すると、実行しているScriptの最初の行まで戻る。
・terminate文を実行すると、実行しているScriptを強制的に終了させる。
・文字列と配列は組み合わせて使うことができる。(まとめになっていませんね(^_^;))


Home Back Next