もし〜〜なら〜〜、ランダムに動かしてみよう

if分岐、乱数発生(Mathクラス)


そろそろ本領発揮、AS講座第07回です。
今回は、複雑な処理関係のこれまで2回の内容を生かして
ゲーム製作には、いや、プログラミングするなら
絶対に必要な「条件分岐」をやってみましょう。

ダン☆おにでもそこかしこに使われています。
たぶん、どこのAS見ても、ifという二文字を見ないことはないでしょう。

さて、では、久々のソースダウンロードをお願いします。

今回使うソースをダウンロード



07_00.pflを開いてください。




こんなSWFのソースですね。

おにぎりをクリックするとおにぎりがまわります。
そして、その回数をカウントします。

いきなりやや複雑なソースですので、がんばって解読してください。
今までこの講座でやってないことはつかってないですし、
一番長いASでも5行なので、大丈夫だと思いますが。

さて、今は何回でもぐるぐる回ります。
これを、5回までしか回らないようにしてみましょうか。


どうやってやるか、勘のいい人はなんとなく気づいたかもしれません。
最初にifって単語書きましたしね。
ifは「もし〜〜なら」という意味です。

そう、「クリックしたときに回る」というASを、
「クリックしたときにもし回転回数が5回未満なら回る」にしてみましょうか。
この部分を書き換えればいいわけですね。




で、実際にifを使うにはどうすればいいでしょうか。
if構文は、次のような形で書きます。


if(条件式){
	条件式が真なら実行して欲しい命令;
}


真って言葉は高校数学をまじめにやらなかった人には
あまりなじみがないかもしれませんが、
条件が正しいことを真(true)、正しくないことを偽(false)と言います。

条件式は、等号や不等号を使って書きます。
例えば、
a<3
と書けば、aが3未満なら(aが3は偽)、ということになります。
a>=5
で、aが5以上なら(aが5は真)、になります。
注意しなければならないのは、等号条件です。
aが4ならば、をうっかり
a=4
と書かないようにしましょう。
=はこの世界では、右辺を左辺に代入しろ、という代入演算子であって、
左辺と右辺が等しいかどうかを比較判断しろ、という比較演算子ではありません。

aが4ならば、というのは、
a==4
と、=を2つ重ねて書きます。
これ、ASに慣れてきてもよくミスします。
むしろ、半端に慣れて来たころが一番ミスします。
よくよく気をつけてください。

今回は、_root.kaisuuが5未満なら、というのを書きたいので、
_root.kaisuu<5
もしくは
_root.kaisuu<=4
を条件にすればいいですね。
なお、一応注意書きしておくと、この2つの条件式は同一じゃないですからね。
_root.kaisuuが小数にもなりえる場合だと、4.5の場合とかに真偽がかわります。

{ }の中身は、今までonイベントハンドラの中にあったものをそのまま書けばいいので、
こんな感じになりますね。




{ }が1重増えたので、TAB字下げを1つずつ追加してます。


ともあれ、これで、
4回以下の場合は条件式が真なので、
回数カウント増加命令+回転命令が実行され、
カウントが5回になると条件式が偽なので、
クリックしてもifの{ }の中はごっそり無視されて、
何もおきない、ということになります。

5回までまわしたいから、と、うっかり
_root.kaisuu<=5
と書くと、6回まわっちゃうので、
こういう制限をする場合は注意してください。


次の内容に進む前に、条件式に使える関係演算子を一覧にしておきます。
aとbは何かの変数なり数字なり文字列なりの代わりです。


a==b aとbが等しければ。
1=="1"は真。(数字と文字列でも、中身は同じ)
a===b aとbが変数型も含めて等しければ。
1==="1"は偽。(左辺は数字、右辺は文字列なので)
a!=b aとbが等しくなければ。
1!="1"は偽。
a!==b aとbが変数型も含めて等しくなければ。
1!=="1"は変数型が違うので真。
a>b aがbより大きければ。
等しい場合は偽。
a>=b aがb以上ならば。
等しい場合は真。
a<b aがbより小さければ。
等しい場合は偽。
a<=b aがb以下ならば。
等しい場合は真。


まぁ、===と!==はまず使わないと思いますが、
他の6つは確実に使いこなせるようにしましょう。
なお、0<=a<1みたいな不等号を2つ書く書き方はできません。
これに相当する書き方をしたい方はPlusOneへどうぞ。



さて、Trainingもなしで次の内容へ行きます。
次の内容といっても、全く新しい内容ってわけでもなく、
if分岐の残り半分という感じですが。
こっちができてこそ、ifは真価を発揮します。
というか、if「分岐」って言ってるのに、まだ分岐してないですし。

さっき「回転数が5回未満なら、{ }の中を実行」というASを

if(_root.kaisuu<5){
	真なら実行する命令;
}

と書きました。
この場合、5回以上回ってたら、何もおきません。
ですが、こういうところで、5回以上なら別のASを実行して欲しい
ということも、非常によくあります。
そんな場合にはどうやって書いたらいいでしょうか?


if(_root.kaisuu<5){
	真なら実行する命令;
}
if(_root.kaisuu>=5){
	別の命令;
}

できたー!

まぁ、たしかにあながち間違ってもないんですが、
いつもいつもこういう書き方だと、困ることもあります。
気まぐれに「5回じゃなく7回にしよう!」とか思ったときに
上だけ7に書き換えて、うっかり下を書き換え忘れた結果、
6の時に両方実行される、なんてトラブルもありえますしね。
てことで、別の書き方を紹介します。

それは、「そうじゃなかったら」、という、
条件式が偽の場合に実行する文を書く方法です。



if(条件式){
	真なら実行する命令;
}else{
	偽なら実行する命令;
}


これなら、条件式をちょっと変えても、うっかり両方実行されたり、
うっかり両方とも実行されなかったりすることはありません。
条件式も1回しか比較されないので、さっきの書き方より処理も軽くなります。

こういう書き方をすると、if「分岐」といわれるのも納得ですね。
条件を見て、どっちを実行するか選ぶ感じになるわけです。
ためしに、さっき改造したのを、6回目以降は逆回転にしてみましょうか。


まず、そのためにはMC内に逆回転の動きを作らなきゃいけませんね。
まず、スプライト内のloop以下をコピペで2つに増やして、
片方を左回転にしましょう。
ラベル名がloopじゃわかりにくいので、
leftとrightに変えましょうか。
ラベル名変えたので、AS中のラベル名全部探して書き換えなければなりません。

こういう事態になるのを俗に設計ミスといいます。
・・・ごめんなさい。


ということで、以上のことを全部やったのが、07_01.pflです。
ちゃんと自分でいじった方、お疲れ様でした。
その手間は決してマイナスにはならないので、
がっかりしないでくださいね。

さて、これで下準備完了です。
「5回目までは右回転、6回目以降は左回転」にしましょう。
「5回目までは右回転」はすでにできているので、
「6回目以降は左回転」を書けばいいわけですね。
ですが、それを正直に書くよりも、
「それ以外の場合は左回転」と書いたほうがいいのは今までお話したとおりです。

} の後にelseと書いて、さらに{ }をつけ、
その中に、「それ以外の場合」に実行して欲しいことを書きましょう。

これまでのことを見直したりしつつ、考えて書いてみましょう。

・・・できましたか?
・・・動作のチェックもしましたか?

できたら答えあわせです。



こう書いた人が多いと思います。
今回初めてifやelseというものを知った方ならこれで大正解です。
初めて使う、全く慣れてない人のASなら動けば十分です。
ここから先の話を「へぇ〜」と眺めつつ先へどうぞ。

ですが、もとからifやelseというものを知りつつなぜか読んでる方なら、
この書き方は正解とはいえません。
真の場合と偽の場合、最初の2行が同じですね。
ということは、この2行はif文の結果に関係なく実行される文なので、
わざわざ2回書くのは無駄だし、わかりにくいし、重くなるしでいいことなしです。
今回は短いし1箇所だけなので大差ないですが、
極力下のような書き方にすることを心がけましょう。




数字を足してからif判定しているので、
5未満じゃなく5以下になってるのに注意。







さて、ついでにもう1歩ステップアップ。
6回目以降ずっと左ってのもあれですよね。
右に5回、そのあと左に5回、合計10回まわったら、
それ以上まわらない、なんてのを試してみましょうか。


「_root.kaisuuが5未満ならrightに、5以上10未満ならleftに、それ以外なら動かない」
を書けばいいわけですが、果たしてどうすればいいでしょうか。

何か新しいことを覚えなきゃいけなさそうですが、意外とそうでもありません。
ifとelseを2回使えば大丈夫です。


if(_root.kaisuu<5){
	5未満なら実行する命令A;
}else{
	if(_root.kaisuu<10){
		5以上10未満なら実行する命令B;
	}else{
		10以上なら実行する命令C;
	}
}


まず、5未満なのかそれ以外なのか、を判断します。
5未満なら、そのままAが実行されます。
5未満が偽、つまり5以上の場合は最初のelseの中に入って、
さらに10未満かどうかを2つめのifで判断します。
10未満が真の場合、最初の5未満では偽となってるわけですから、
Bが実行されるのは5以上10未満の場合ということになります。
両方とも偽となるのは10以上の場合で、その場合Cが実行されます。

ややこしいですが、ついてこれてますか?
慣れるまでちょっと理解するまでに時間がかかるかもしれませんが、
がんばってください。

ただ、この書き方は分岐の数が増えると、
分岐の数だけ{ }が重なって、あまりに複雑なことになるので、
(特に、TAB字下げの数が異常なことになるので)
もうちょっと簡単な書き方が許されています。
if(_root.kaisuu<5){
	5未満なら実行する命令A;
}else if(_root.kaisuu<10){
	5以上10未満なら実行する命令B;
}else{
	10以上なら実行する命令C;
}


こんな感じに、else if(条件式2)と書くと、
いくら分岐の数が増えても{ }が分岐の数だけ増えることはなく、
多少は見やすくなるので、普通はこっちで書きます。
「そうじゃない場合のうちこんな場合は」みたいな感覚ですね。
10以上なら何もしない場合は、最後のelse以降はいりません。


では、これを踏まえて、
「_root.kaisuuが5未満ならrightに、5以上10未満ならleftに、それ以外なら動かない」
を書いてみてください。

できたら動作チェックのあと答え合わせ。




こう書けたら大正解。文句なしです。


ところで、さっきの「もともとifやelseを知ってた方〜〜」というのを見て
こう書いた方はいるでしょうか。




これ、今回の場合は間違いです。
動作チェックをしてみてください。
10回以降もカウントだけが増えていきませんか?

このカウントを増やすASは、10回以上は実行されると困るASなので、
if文の外に出すことはできません。
たぶん、コンピューターにとってベスト書き方は、こんな感じだと思いますが、
人間にとって若干わかりにくいので、ここまで無理はしなくていいと思います。












Training


6回目以降ずっと左なのもあれだけど、10回で止まるのもなぁ。
ということで、5回ずつ右左入れ替わりにしてみましょう。

といきたいところですが、やや難しいので1回ずつの交互をやってみましょう。
1回目は右、2回目は左、3回目は右、・・・という感じですね。
else ifをたくさん重ねればいいのでしょうか?
でも10回までしか書かなければ10回までしか動きませんね。
100回書いても101回目は動きませんね。
10000回くらい書けば10001回もまわす人はいなさそうですが、
逆にelse ifを9999回も書くわけにもいきません。重すぎです。

さて、どうやってうまくif分岐すればいいのでしょうか?


以下、反転でその方法の解説です。
すでにわかった人と、しばらく考えてわかんなかった人のみどうぞ。

if(_root.kaitenが偶数かどうか)というのを書ければいいことは
自力で思いつくかどうかは別にして、すぐに理解できると思います。

問題はそれをどうやって書くかですが、
前回やった演算子の中に、四則演算に混ざって
見慣れないものが1つあったのを覚えているでしょうか。
そう、割り算の余りを計算する、%ってやつですね。
今こそこいつの出番です。
というか、こういう使い方以外では
%の出番はほとんどないといっていいくらいです。

偶数とは、2で割り切れる数字、つまり、
if(_root.kaiten%2==0)と書けばいいわけですね。
最初の方でも言いましたが、=0じゃなく==0なので気をつけてください。
偶数なら真、奇数なら偽ときれいに分けれるので、
else ifは実は使う必要はないのでした。ちゃんちゃん。
あ、1回目を右回りにするように、
どっちにright、どっちにleftを書くかよく考えてくださいね。


余裕がある人は、1〜5回目は右、6〜10回目は左、11〜15回目は右、・・・
というのにも挑戦してみましょう。









さて、ではお次の話題です。
なんかの条件で判断じゃなく、ランダムに分岐したいなぁ。
ってこと、ありませんか?
いや、今までifなんて知らなかった人はないかもしれませんけれども。
でも、さっきからおにぎりぐるぐるまわしてて、
「回数関係なく右や左にランダムにまわせんもんかいな?」とか思ったりしませんでした?

ということで、やってみましょう。乱数発生
0から1までのランダムな数字を出させて、それが0.5より大きいか小さいか、を判断すれば、
確率1/2ずつで2種類のASをランダムに実行させることができるわけです。

で、肝心のどうやるか、なんですが、
詳しいことははしょって、0以上1未満の乱数を発生させる方法を書くと、
Math.random()
と書くと、計算実行時にそこを0以上1未満の乱数に置き換えてくれます。
どの乱数が出たかをどこかに保存しておきたい場合は、
ransuu1=Math.random();
とかしておけば、同じ乱数を何度も使うことができます。
逆に、毎回Math.random()を書くと、毎回別の乱数になります。

ちなみに、私は毎回変数に保存しておいて、
別の変数を使いたければもう1回同じ変数に別の乱数を代入しています。
あとから改造するときにその乱数を別の場所で使いこともありますしね。
この講座を見ているみなさんがどうするかは自由だと思います。

ともかく、これで0以上1未満のランダムな小数を発生できました。
あとはこれが0.5より大きいか小さいかでif分岐すれば、
5割の確率で左回り、5割の確率で右回りというのができます。




なお、この07_02.pflは、ダウンロードファイルに入れようかと思いましたが、
自分で書いてみた方が練習になると思うので、
あえて入れませんでした。
自分で書いて、本当にランダムに回るか確認してみてください。

ついでに、ランダムな挙動の動作チェックをする場合のご注意。
私がこのランダム回転のテストをしたとき、
最初から5回連続左回転になって、「あれ?」ってなりました。
あくまでランダムに出るのであり、均等に出るわけではないので、
片方の挙動ばっかりすることがありますのでご注意を。


できましたか?理解しましたか?

では問題です。
今は左右半々でしたが、
「ほとんど右回りでたまに左回り」にしたいと思います。
思ったことにしてください。
そうですね、10回に1回くらい左回りにしましょうか。
さて、上の画像のどこの数字を何に変えればいいでしょうか?
考えてみてください。




0.5を0.1に変えれば、と思った人はこの講座の最初からやり直し。
それ、本当に「たまに左」になりますか?
実際にやってみましたか?
普通のテストと違って、自分でやってみれば正解かどうかわかりますから、
こういう時はどんどん積極的に実験してみましょうね。

一応正解は反転で。
ifの中に書いてあるのは右回りなので、
0.5から書き換えるべき数字は右回りの確率である0.9が正解です。





さて、まわるおにぎりの話はここまで。
次はもうちょっと複雑な乱数の使い方をやってみましょう。

次につくるのは確率の問題でおなじみ、サイコロです。
といっても立方体がころがるアニメーションを作るのではなく、
1から6までの数字をランダムに出力させてみようというだけです。
いや、アニメーションも作るなら止めはしませんけど。

実は、一応今までやった方法でも作ることが出来ます。
まずはどうすればいいのかちょっと考えて、実験してもらいましょうか。
traceで、1から6が1/6ずつランダムででるスクリプトを書いてください。





_root.ransuu=Math.random();
if(_root.ransuu<1/6){
	_root.me=1;
}else if(_root.ransuu<1/3){
	_root.me=2;
}else if(_root.ransuu<1/2){
	_root.me=3;
}else if(_root.ransuu<2/3){
	_root.me=4;
}else if(_root.ransuu<5/6){
	_root.me=5;
}else{
	_root.me=6;
}
trace("_root.me="+_root.me);


一応meという変数に、確率1/6ずつで1から6が入ります。
この例の場合は同じ乱数を何度も判断に使うことになるので、
乱数を一度hensuuという変数に保存してあります。
うっかり

if(Math.random()<1/6){
	_root.me=1;
}else if(Math.random()<1/3){
	_root.me=2;
}else if(Math.random()<1/2){
	_root.me=3;
}else if(Math.random()<2/3){
	_root.me=4;
}else if(Math.random()<5/6){
	_root.me=5;
}else{
	_root.me=6;
}
trace("_root.me="+_root.me);


なんて書くと、2や3ばっかり出て6が非常に出にくい
恐ろしく偏ったサイコロになるので注意してくださいね。

で、さっきの書き方でもちゃんと結果はでるのでいいのはいいんですが、
いかんせんサイコロ1つ作るだけにしてはややこしいASですよね。
だいたい、サイコロの目は数字なんだから、
わざわざifなんて使わなくても乱数から何か計算で出せそうなもんです。


じゃあ、何とかしてみましょう、ということで、
突然ここでちょっとMathクラスのお話。

本当に唐突ですが、一部が次の話に必要なことなので。
はじめてASに触る人、数学が苦手な人は頭がくらくらするかもしれませんが、
ここでする話がすぐに全部は理解できなくても大丈夫なので、
わかんなかったらMathクラスのお話が終わるまで流し読みでけっこうです。


さて、乱数を発生させる時、Math.random()と書きました。
randomは読んで字の如しです。
()は、stop()とかのかっこと同じようなものでしょう。
では、Mathって一体なんでしょう?

実は、Mathというのは、平たく言えば、
複雑な数学計算をするための計算方法が入った道具箱みたいなもんです。
四則演算という道具はしょっちゅう使うのでいつも部屋においてありますが、
例えば小数の四捨五入、例えば三角関数、例えば乱数発生、
こういった複雑な道具は、Mathという道具箱に入って倉庫の奥に眠っています。
というイメージでだいたい間違ってないと思います。

Math.random()というのは、
Mathっていう道具箱にrandom()っていう道具があるから
それ探してきて使ってね
といった意味なわけです。

となれば気になるのは中に他に何が入っているか、ですよね。
とりあえず中身のうち、比較的よく使うものを
系統別にリストアップしました。
(ダン☆おにではあまり縁が無いものもあります)
今はふーん、と眺めていただければ。

まずは定数と乱数。

Math.PI 円周率の値。
Math.random() 0以上1未満の乱数


ネイピア定数(自然対数基底)は使わないと思うので、
定数は円周率だけ掲載。
これだけは大文字書きで、かっこもなし。


次は小数関係。
aは全部変数もしくは式だと思ってください。

Math.floor(a) 小数以下を切り捨て
Math.round(a) 小数以下を四捨五入
Math.ceil(a) 小数以下を切り上げ


10倍してMath.round()を使ってから10で割ると、
小数第2位で四捨五入
といったことも出来ます。


次、大小比較。

Math.max(a,b) aとbの大きい方
Math.min(a,b) aとbの小さい方


かっこには2つしか入れられないので、
3つ同時に比較するにはmaxやminを2回使って
Math.max(Math.max(a,b),c)としてください。



次、指数関連の演算。

Math.sqrt(a) √aを計算
Math.pow(a,b) aのb乗を計算


2乗や3乗ならa*aとかa*a*aとか書いた方が手っ取り早かったり。


最後、三角関数。

Math.sin(a) aの正弦を計算
Math.cos(a) aの余弦を計算
Math.tan(a) aの正接を計算
Math.atan2(a,b) 下で解説


上の3つはASで円軌道や楕円軌道を制御するには必須です。
ちなみに、aの単位はradだと判断されるので、
「a度のコサイン」を計算したいなら、
Math.cos(a*180/Math.PI)としてください。

そして、4つめに不思議なものがありますが、これは、
「x座標がbでy座標がaな点は、原点から見てどの角度にあるか」
というのを計算してくれます。
なぜかy座標の方を先に書きます。
計算結果はradなので、*180/Math.PIして度数法に直すことが多いです。
例えば、ずっとマウスの方を向く何かを作ったりする時に使います。

Mathクラスのお話ここまで。

ま、そんな道具箱がありますよってことで。
今すぐ使うのは実はこのうちMath.random()をあわせても
2つだけだったりするんですけどね。

さて、もとの話に戻りましょう。
もとの話は何だったかというと、
サイコロの目は計算でなんとかできないか?ということでした。
こういう、何段階かの整数乱数を出すには有名な方法があります。
パターン化された手法なので、ぜひ覚えておいてください。

まず、これがさっきやった0以上1未満の乱数の発生です。
Math.random()
これに、今回は6段階の乱数が欲しいので、6をかけます。
Math.random()*6
これで、0以上6未満の乱数になりました。
で、これの小数以下を切り捨てます。
切り捨てはさっきのMathという道具箱の中にありましたね。
Math.floor(Math.random()*6)
0から5.9999・・・までの乱数だったのが、
0、1、2、3、4、5が等確率で出る整数の乱数になったのがお分かりでしょうか?
そして仕上げに、今回はほしい乱数の最低数が1なので、1を足します。
Math.floor(Math.random()*6)+1
これで、1から6までが確率1/6で出る乱数ができました。
つまり、サイコロを作るには、

_root.ransuu=Math.random();
if(_root.ransuu<1/6){
	_root.me=1;
}else if(_root.ransuu<1/3){
	_root.me=2;
}else if(_root.ransuu<1/2){
	_root.me=3;
}else if(_root.ransuu<2/3){
	_root.me=4;
}else if(_root.ransuu<5/6){
	_root.me=5;
}else{
	_root.me=6;
}
trace("_root.me="+_root.me);

なんて長々と書かなくても、

_root.me=Math.floor(Math.random()*6)+1;
trace("_root.me="+_root.me);

とだけ書けばよかったんですね。
これなら数が多くても楽チンです。

20面体ダイスなら
Math.floor(Math.random()*20)+1;
100面体ダイスなら
Math.floor(Math.random()*100)+1;
3桁以下の自然数が欲しければ
Math.floor(Math.random()*999)+1;
3桁の自然数(つまり100以上999以下)が欲しければ
Math.floor(Math.random()*900)+100;
-100から100までの整数が欲しければ
Math.floor(Math.random()*201)-100;
個数や最低数さえ間違えなければ簡単ですね。

ちなみに、サイコロじゃなくおみくじだった場合は、
もちろん計算結果で大吉とかになるわけはないので、

_root.ransuu=Math.random();
if(_root.ransuu<1/6){
	_root.omikuji="大吉";
}else if(_root.ransuu<1/3){
	_root.omikuji="中吉";
}else if(_root.ransuu<1/2){
	_root.omikuji="小吉";
}else if(_root.ransuu<2/3){
	_root.omikuji="末吉";
}else if(_root.ransuu<5/6){
	_root.omikuji="凶";
}else{
	_root.omikuji="大凶";
}
trace("_root.omikuji="+_root.omikuji);

と、書くしかありません。
・・・というと本当は嘘になるんですけどね。
別の方法を知りたい方はPlusOneをどうぞ。








Training


ボタンを押したらトランプ52種類からランダムに1枚選んでみましょう。
トランプの絵柄は表示されなくてかまいません。
「ハートの5」「スペードの11」と文字で表示されれば十分です。
else ifでひたすら52回書くのはばかばかしいので、
マークをおみくじの方法で、数字をサイコロの方法で選び、
2つをくっつけて表示しましょう。

同じカードが何度も出てしまいますが、
それを阻止するのは難しいので、
今はトランプを何組も混ぜたんだということにしておきましょう。

余裕がある人は、こんなことにも挑戦してはどうでしょうか。
・1の場合はA、11の場合はJなどと表示するようにする
・ジョーカーを含めて53枚から確率1/53ずつで出るようにする
どちらも今回までの講座内容だけでできますよ。









以上、複雑な処理の第2歩目のAS講座第07回でした。
if文を覚えてだいぶいろいろなことが出来るようになったと思います。
面白いものが出来たら掲示板等にぜひぜひご報告を。
また、そろそろ、「これを応用してこんなことできたりしないの?」
という疑問が出てくる人もいるかもしれませんが、
そういう質問も遠慮なく掲示板でしてくださいね。









PlusOne:より複雑な条件式


講座中で、0<=a<1のような書き方は出来ない、と言いました。
でも、こういう書き方をしたいときはあります。
どうしたらいいのでしょうか?

小数点以下を切り捨てて0になればいいのではないか?
と考える人もいるかもしれません。
if(Math.floor(a)==0){ }
これでも確かに今回はうまくいきますが、
1/3以上√2以下なんてなると、この方法ではかなりめんどくさいです。

ではどうするか。
正解は、「a>=0かつa<1」と分割して書けばいいのです。
「かつ」を意味する記号は、&&です。
if(a>=0&&a<1){ }
と書けば、これが0<=a<1と同じ意味を正しく表記したものになるわけですね。

ちなみに、&&はいくつでもつなげられます。
if(a>0&&b>0&&c>0){ }
で、aもbもcも正の数ならば、という表記ができるわけですね。

逆に、「または」を意味するのは||です。
キーボードの上の数字キーの0の3つ右のキーを、
Shiftを押しながら押すのを2文字。
if(a>0||b>0||c>0){ }
で、aかbかcのどれか1つでも正の数ならば、になります。
&&と||を両方使う時は、混乱しないように、
if( (a>0&&b>0) ||c>0){ }

if(a>0&& (b>0||c>0) ){ }
といったように、かっこを使っておきましょう。








PlusOne:小数の等号比較


aとbが等しいと言う条件は、普通はa==bと書きます。
何を今さら、と思うかもしれませんが、
このaとbが小数だった場合、実はこの書き方では厄介なことがおきます。
前回話したとおり、割り算というのは、割り切れない場合、適当な桁で計算を打ち切ります。
割り算以外でも、こういう適当な桁数で打ち切ることは多いのです。
例えば、0.1という数字は2進数では割り切れないので、
パソコンは2進数で適当な桁までで切った値を使っています。

どっちにしても、小数では打ち切ったことによる誤差が若干出ることがあるのです。
一方、==は、小数の値の場合は、
小数以下の点が打ち切ったとこまで全部あっているかどうかを確認します。

もう何が起こるかお分かりですね。
打ち切り誤差が合った場合、本来は一致するはずの値でも
等しくないと判断されてしまうことがあるのです。


ということで、小数同士が一致していればという条件はこう書くのが正解です。
if(Math.abs(a-b)<0.0001){ }
Math.abs()はほとんどこの形でしか見ないと思うので、
さっきの表には入れませんでしたが、絶対値を計算するものです。
つまり、aとbの大きい方から小さいほうを引いた値が0.0001未満なら、というのを
等しい条件のかわりとするわけです。

この0.0001は特に意味のある数字ではありません。
aやbが1とか10とかくらいの数字なら、
これくらいの微妙な差があるから違う数字だってこともないだろうし、
逆に打ち切り誤差が0.0001より大きくなることもないだろうという、
間の数字を適当に持ってきただけです。
当然もしaやbがそもそも0.000001くらいの数字だったり、
1くらいの値でも0.000001の差で違うと判断して欲しいなら、
右辺は0.0000000001とかにしなきゃいけません。
そこらへんは臨機応変に対応しましょう。








PlusOne:switch分岐


おみくじの時に、else ifをいっぱい並べて書きましたが、
実は別の書き方があります。
というか、数が多い場合はこっちを使うのが普通です。

その名も、switch分岐。
見たほうが早そうなので、いきなり実例を。

_root.ransuu=Math.floor(Math.random()*6);
switch(_root.ransuu){
	case 0: _root.omikuji="大吉"; break;
	case 1: _root.omikuji="中吉"; break;
	case 2: _root.omikuji="小吉"; break;
	case 3: _root.omikuji="末吉"; break;
	case 4: _root.omikuji="凶"; break;
	case 5: _root.omikuji="大凶"; break;
	default: _root.omikuji="出ない・・・";
}
trace("_root.omikuji="+_root.omikuji);

1行目と最終行は解説の必要はないでしょうが、
その間はおそらく見たことないものが並んでると思いますので、
順に解説していきましょう。

まず、switch(変数名){ }という形ですが、
これは( )の中の変数の中身が何かで、
{ }内のどのASを実行するか決めますよ
、ということです。
今回で言えば、先に振っておいた0から5までのサイコロで
何が出たかでどのASを実行するか決めますよ、というわけです。

case 0: は、今見てる変数の中身が0だったらそこから先を実行しますよ、 という印みたいなものです。
よく見るとcase 0: からcase 5: まで全部書いてありますね。
だからこのうちどれかは一致して実行されるわけです。

次に、各行の最後にbreak;と書いてありますが、
これは、そこまででswitch分岐の処理をやめるということです。
caseが開きかっこで、こっちは閉じかっこみたいな関係ですね。
ちなみに、break;を書かないと、次のcaseの先も実行します。
このASでbreak;を書き忘れると、例えばサイコロで3が出た場合、
まず末吉が代入されて、そこで終わらずに次の行も実行されて、
凶で上書きをされ、さらに次の行で大凶で上書きされ、
最後には出ない・・・が代入されて、結果的におみくじは出ません。
もちろんこういう仕様になってるのは、
break;を意図的に書かないことで便利になることもあるからなんですが、
うっかり書き忘れないようにしてくださいね。

で、最後にdefault: というやつですが、
変数の中身がどのcaseとも一致しなかった場合にはここから実行されます。
どれにも一致しなかった場合は何もしなくていいよ、という場合には
default: 自体を書かなくても大丈夫です。
今回はそもそも0から5までの整数しかありえないので絶対どれかに一致するので
実は全く無意味な行なのですが、サンプルとして入れてみました。
そしてこの行の最後にはbreak;がありませんが、
この行が終わったらとじ中かっこがあるので、
break;があろうとなかろうとここで絶対に終わるので、
最後はbreak;を書く必要はありません。

解説ここまで。長かった・・・。
今回は乱数でやってますが、当然普通の変数でもできます。

ダン☆おになら、
switch(_root.rank){
	case "S":     Sランクの処理; break;
	case "AAA": AAAランクの処理; break;
	case "AA":   AAランクの処理; break;
	case "A":     Aランクの処理; break;
	default:  Bランク以下の処理;
}

なんて分岐はいかが?




戻る   掲示板へ