ひな形スクリプト講座5
[ひな形スクリプト講座1][ひな形スクリプト講座2][ひな形スクリプト講座3][ひな形スクリプト講座4][ひな形スクリプト講座5][ひな形スクリプト講座6][ひな形スクリプト講座7][ひな形スクリプト講座8][ひな形スクリプト講座9][ひな形スクリプト講座10][ひな形スクリプト講座11][ひな形スクリプト講座12][ひな形スクリプト講座13][ひな形スクリプト講座14][ひな形スクリプト講座15][ひな形スクリプト講座16][ひな形スクリプト講座17][ひな形スクリプト講座18][ひな形スクリプト講座19][ひな形スクリプト講座20][ひな形スクリプト講座21][ひな形スクリプト講座22][ひな形スクリプト講座23][ひな形スクリプト講座24][ひな形スクリプト講座25][ひな形スクリプト講座26][ひな形スクリプト講座27][ひな形スクリプト講座28][ひな形スクリプト講座29][ひな形スクリプト講座30][参考資料索引]

さあ、またまた前回のスクリプトを改造していきましょう。今回は乱数が出てきます。スクリプト改造しながらスクリプトプログラムのことが学べるなんて楽しいですね。

え〜、今回の改造でなにをしようとしているかというと、前回ではいつも決まった場所からスタートします。ページを表示する度に同じ動きになるんですね。
そこで今回は画面の外から入ってきて、バウンドするようにしたいと思います。どこから入るって?それをプログラムで任意の場所にしたいんです。といってもでたらめではなく、次の図のように規則を作ります。その規則内でスクリプトで表示する度に違う場所から入ってくるようにしたいんです。

1〜4までの目があるサイコロ(正三角錐)を振る。どの目も出る確率は同じ(25%)である。

@出た目が1の時はLeftを画像の横幅分マイナスにする(img1.style.pixelLeft=-img1.clientWidth)
       
この時Topは-img1.clientHeightからdocument.body.clientHeightの範囲でプログラムで決定させる

A出た目が2の時はTopを画像の縦幅分マイナスにする(img1.style.pixelTop=-img1.clientHeigt)
        この時Leftは-img1.clientWidthからdocument.body.clientWidthの範囲でプログラムで決定させる

B出た目が3の時はLeftをdocument.body.clientWidthにする(img1.style.pixelLeft=document.body.clientWidth)
       この時Topは-img1.clientHeightからdocument.body.clientHeightの範囲でプログラムで決定させる

C出た目が4の時はTopをocument.body.clientHeightにする(img1.style.pixelTop=ocument.body.clientHeight)
        この時Leftは-img1.clientWidthからdocument.body.clientWidthの範囲でプログラムで決定させる

@〜Cはまずサイコロを振ってその目に応じて左から出現か、上から出現か、右から出現か、下から出現かをおおまかに決定します。
その決定の後更に出現位置をランダムに計算させて位置決定しようということです。

さあサイコロを振らせましょう。といってもスクリプトにサイコロがあるわけではないので、1〜4までの数字のいずれかを選ぶというプログラムを作らなければなりません。そして1〜4までの出現率は同じ(確率的に同じ)である必要があります。そこで乱数の登場です。

スクリプトでは乱数を発生させる関数(数学関数のひとつです)が用意されています。しかしこれは○〜●までの整数の乱数を発生させるものではないため、工夫が必要になります。

乱数の取得・・・Math.random()・・・0以上1未満の乱数を取得する(0<=Math.random()<1)
MathのMは大文字です、注意してくださいね。

0以上というところと1未満というところをよく覚えておいてください。つまり0である可能性はありますが、1には決してなりません。1未満ですから値は0である時以外は小数となります。0や0.1025、0.999999、などですね。

さて整数の乱数を得たい場合ですが、1未満の値しか出ないわけですから、工夫が必要になります。0から9までの整数を条件にした乱数を考えます。

Math.random()*10を計算しましょう。例えばMath.random()がとりうる値が最小値である場合、これは0ですから0*10=0ですね。つまり最小値は0となります。
最大値を考えましょう。Math.random()は0.999999…が最大値です。これに10を乗ずると、9.999999…ですね。つまり最大値は10未満の10に無限に近い数値になります。

ということはMath.random()*10は0以上10未満の乱数ということになります。整数値を得たいわけですから、スクリプトに用意されている丸め込みを行う関数を使用して小数を整数にしてしまうと良いと気が付きます。

丸め込みですが、切捨て、四捨五入、切り上げがありますが、ここでは四捨五入でも切り上げでもなく、切捨てを使用するのが一般的です。理由は切り捨てでのみ同じ確率になるからですが、ここでは説明を省略します。ご自分でどうしてなのか考えてみるのもいいでしょう。

で、スクリプトでの切り捨ても数学関数として用意されております。

Math.floor(値)・・・値を小数点以下切捨てして整数値にする
注意!負数の場合は小数点以下を切り捨てた最大値の負数になる

これは例を示しておきますね。
Math.floor(7.5)・・・7になります。
Math.floor(-7.5)・・・-8になります。-7ではありません。

いうことでMath.floor(Math.random()*10)・・・最小値0で、最大値9を範囲とする整数の乱数になります。

では1から4までの整数の乱数を得るにはどうしましょう?もうおわかりですね。
Math.floor(Math.random()*4)+1・・・Math.floor(Math.random()*4)が0以上3以下の整数の乱数それに1を足せばよい

この計算式はスクリプトでは公式みたいなものです。こうするものなんだと覚えておけばいいでしょう。


ではさいころの目(乱数)が1、2、3、4それぞれ出現した場合の場合分けはどうプログラムすればいいかを考えましょう。今まで出てきたif(条件){処理}でできそう?

だめな例をまず示します。どこがだめなのか考えてみてくださいね。

if(Math.floor(Math.random()*4)+1==1){処理1}
if(
Math.floor(Math.random()*4)+1==2){処理2}
if(
Math.floor(Math.random()*4)+1==3){処理3}
if(
Math.floor(Math.random()*4)+1==4){処理4}

 

わかりましたか?まずMath.floor(Math.random()*4)+1が2となった場合、処理1は実行されませんね。次のMath.floor(Math.random()*4)+1では4になりました。すると処理2は実行されません。更にMath.floor(Math.random()*4)+1が計算され、1になりました。すると処理3は実行されません。最後のMath.floor(Math.random()*4)+1では2となりました。つまり処理4も実行されません。このように毎回乱数を取得していてはその都度値が変わりどの処理も実行されない場合が起こります。全ての処理が実行されてしまうこともあるでしょう。このような時は一回だけ乱数を取得しておいて、その値を条件式に当てはめていずれかの処理を実行させる必要があるのです。

ということで乱数を取得したらそれを一旦保存します。保存するには変数に入れればいいのはわかりますね。

var saikoro=Math.floor(Math.random()*4)+1
こうしておいて変数saikoroの内容を当てはめればいいわけですね。==は比較演算子、等しい(ならば)です。

var saikoro=Math.floor(Math.random()*4)+1
if(saikoro==1){処理1}
if(
saikoro==2){処理2}
if(
saikoro==3){処理3}
if(
saikoro==4){処理4} 


サイコロの目が1〜4のいずれかになる場合分けはできました。次は各処理の内容を考えましょう。

まずサイコロが1だった時(処理1)
Leftを画像の横幅分マイナスにする(img1.style.pixelLeft=-img1.clientWidth)
       
この時Topは-img1.clientHeightからdocument.body.clientHeightの範囲でプログラムで決定させる

下図を見てください。なにをしようとしているかわかりますね。

ここでまた難しい問題が出てきました。-img1.clientHeightからdocument.body.clientHeightの範囲でプログラムで決定させる--言い換えると、-img1.clientHeight以上document.body.clientHeight以下の整数の乱数を取得するとなります。

a以上b以下の乱数を取得する(整数)。最小値と最大値の間の乱数を取得するには、最大値と最小値の差の乱数を得てから、最小値をその値に足すとできます。

問い)最小値=-5、最大値=8間の整数の乱数を取得するスクリプトは?

8-(-5)=13ですね。で、もし乱数が0の時-5を足すと-5になります(最小値)。また13に-5を足すと、8になります(最大値)。つまりは0以上、差の値以下の乱数を得てから最小値を足せばいいのがわかります。この場合はMath.floor(Math.random()*(8-(-5)+1))=Math.floor(Math.random()*(13+1))=Math.floor(Math.random()*14)が乱数取得で、それに最小値を足します。
(答)Math.floor(Math.random()*14+1

最小値以上、最大値以下の整数の乱数を得る公式・・・Math.floor(Math.random()*(最大値-最小値+1))+最小値

ということで処理1にあてはめると、
img1.style.pixelLeft=-img1.clientWidth
img1.style.pixelTop=
Math.floor(Math.random()*(document.body.clientHeight-(-img1.clientHeight)+1))+(-img1.clientHeight)

 

同様に処理2は、
img1.style.pixelTop=-img1.clientHeight
img1.style.pixelLeft=
Math.floor(Math.random()*(document.body.clientWidth-(-img1.clientWidth)+1))+(-img1.clientWidth)

処理3は、
img1.style.pixelLeft=document.body.clientWidth
img1.style.pixelTop=Math.floor(Math.random()*(document.body.clientHeight-(-img1.clientHeight)+1))+(-img1.clientHeight)

処理4は、
img1.style.pixelTop=document.body.clientHeight
img1.style.pixelLeft=Math.floor(Math.random()*(document.body.clientWidth-(-img1.clientWidth)+1))+(-img1.clientWidth)

さあ、綺麗にまとめましょう。

<script>
var ix=5//一度に動くピクセル数
var iy=5//一度に動くピクセル数(縦)
var rtime=10//繰り返し実行時間(ミリ秒)
function lidou(){//右移動する関数
if(img1.style.pixelLeft+ix>=document.body.clientWidth-img1.clientWidth){
   if(img1.style.pixelLeft<document.body.clientWidth-img1.clientWidth){
       img1.style.pixelLeft=document.body.clientWidth-img1.clientWidth
   }else{
       ridou()
       return
   }
}else{
   img1.style.pixelLeft+=ix
}
status=img1.style.pixelLeft
setTimeout("lidou()",rtime)
}

function ridou(){//左移動する関数
if(img1.style.pixelLeft>0){
   if(img1.style.pixelLeft-ix<0){
       img1.style.pixelLeft=0
   }else{
       img1.style.pixelLeft-=ix
   }
   setTimeout("ridou()",rtime)
}else{
lidou()
return
}
}

function didou(){//下移動する関数
if(img1.style.pixelTop+iy>=document.body.clientHeight-img1.clientHeight){
   if(img1.style.pixelTop<document.body.clientHeight-img1.clientHeight){
       img1.style.pixelTop=document.body.clientHeight-img1.clientHeight
   }else{
       uidou()
       return
   }
}else{
   img1.style.pixelTop+=iy
}
setTimeout("didou()",rtime)
}

function uidou(){//上移動する関数
if(img1.style.pixelTop>0){
   if(img1.style.pixelTop-iy<0){
       img1.style.pixelTop=0
   }else{
       img1.style.pixelTop-=iy
   }
   setTimeout("uidou()",rtime)
}else{
didou()
return
}
}

var saikoro=Math.floor(Math.random()*4)+1
if(saikoro==1){
img1.style.pixelLeft=-img1.clientWidth
img1.style.pixelTop=
Math.floor(Math.random()*(document.body.clientHeight+img1.clientHeight+1))-img1.clientHeight
}
if(
saikoro==2){
img1.style.pixelTop=-img1.clientHeight
img1.style.pixelLeft=
Math.floor(Math.random()*(document.body.clientWidth+img1.clientWidth+1))-img1.clientWidth
}
if(
saikoro==3){
img1.style.pixelLeft=document.body.clientWidth
img1.style.pixelTop=Math.floor(Math.random()*(document.body.clientHeight+img1.clientHeight+1))-img1.clientHeight
}
if(
saikoro==4){
img1.style.pixelTop=document.body.clientHeight
img1.style.pixelLeft=Math.floor(Math.random()*(document.body.clientWidth+img1.clientWidth+1))-img1.clientWidth
}


lidou()//右移動関数スタート
didou()//下移動関数スタート
</script>

外からin

表示したら[F5]で何度か更新して確認してみてくださいね。ステータスバーにはさいころの目が出るようにしています。

 ところでそもそも元々のスクリプトは右端から左端へ移動、左端から右端へ移動といったものでした。それなのに画面外からINしてくる(画面内に移動してくる)のはどうしてでしょう?

移動スクリプトをもう一度見てください。

例えばサイコロが1の場合、img1.style.pixelLeftは0より小さい値になるようにしましたね(img1.style.pixelLeft=-img1.clientWidth)。右に移動する関数ではimg1.style.pixelLeft+ix>=document.body.clientWidth-img1.clientWidthではない場合、img1.style.pixelLeft+=ixでしたから、この処理が実行されることになり、左から右へとINしてきますね。
下に移動する関数のimg1.style.pixelTop+=iyが実行される条件により、Topがどのような場合でも、上から下へ、あるいは下から上に移動する関数実行へと処理が移ることができます。サイコロの目が2・3・4いずれの場合でも移動する関数がきちんと動作することもプログラムを見ていくと確認できます。

 

次回はこのスクリプトをif条件分岐ではなく、条件分岐処理(switch構文)を使用して作り直してみます。お楽しみに。


[ひな形スクリプト講座1][ひな形スクリプト講座2][ひな形スクリプト講座3][ひな形スクリプト講座4][ひな形スクリプト講座5][ひな形スクリプト講座6][ひな形スクリプト講座7][ひな形スクリプト講座8][ひな形スクリプト講座9][ひな形スクリプト講座10][ひな形スクリプト講座11][ひな形スクリプト講座12][ひな形スクリプト講座13][ひな形スクリプト講座14][ひな形スクリプト講座15][ひな形スクリプト講座16][ひな形スクリプト講座17][ひな形スクリプト講座18][ひな形スクリプト講座19][ひな形スクリプト講座20][ひな形スクリプト講座21][ひな形スクリプト講座22][ひな形スクリプト講座23][ひな形スクリプト講座24][ひな形スクリプト講座25][ひな形スクリプト講座26][ひな形スクリプト講座27][ひな形スクリプト講座28][ひな形スクリプト講座29][ひな形スクリプト講座30][参考資料索引]