本文でも少し書きましたが、RANDOMIZE命令は値を指定しないでやると、勝手にそのときの時間から数値を得ます。
「それなら何も自分でやらなくてもいいんじゃない?」
でも、自動でやってくれないBASICというのも考えられるので、そこでも使えるように方法の一つとして覚えておきましょう。
10 RAMDOMIZE VAL(RIGHT$(TIME$,2)) |
これだけです。
が、本文では出てきていない関数を使っているので、ここで説明しておきます。
文法 |
VAL(文字数列) |
動作 | 文字数列を数値に変換する。 |
補足 | ここで言う文字数列とは、"123456"や"-1.05"などの文字列で、内容が数値として読もうと思えば読めるものです。 |
さらに、
文法 |
RIGHT$(文字列,値) |
動作 | 文字列の右から数えて、値文字分だけの文字列を得る。 |
補足 | なし。 |
また、命令や関数ではないですが、値を返すものとして、
文法 |
TIME$ |
動作 | 時間をHH:MM:SSの書式で、文字列として返す。 |
補足 | 同様にDATE$というものもあり、こちらは年月日を得られる。 |
では、括弧の内側から解説していきます。
A$=RIGHT$(TIME$,2)
PRINT A$
上のコードは、今の時間の「秒」を文字列として表示します。
TIME$の右から2文字だけを変数A$に代入していますが、これはTIME$の書式のSSの部分ですね。
では続いて、
A=VAL(RIGHT$(TIME$,2))
PRINT A
とすれば、2桁の文字列である「秒」を、数値として表示できますね。
それなら、この値をRANDOMIZEで使えば、秒ごとに違った乱数列で初期化できますね。
同じようにして、分ごとでも時ごとでも、全部混ぜることもできます。
参考に、全部使った大がかりな初期化のサンプルを書いておきますね。
まずは命令紹介。時間のHHとMMの部分を得るために、
文法 |
LEFT$(文字列,値) |
動作 | 文字列の左から数えて、値文字分だけの文字列を得る。 |
補足 | なし。 |
これと、
文法 |
MID$(文字列,開始位置[,文字数]) |
動作 | 文字列の左から数えて、開始位置から文字数分だけの文字列を得る。 |
補足 | 文字数を省略すると、文字列の最後までを得ます。 |
を使えばできます。
10 RAMDOMIZE VAL(LEFT$(TIME$,2))*3600+VAL(MID$(TIME$,4,2))*60+VAL(RIGHT$(TIME$,2)) |
1行じゃ複雑に見える? それなら、
10 H=VAL(LEFT$(TIME$,2)) 20 M=VAL(MID$(TIME$,4,2)) 30 S=VAL(RIGHT$(TIME$,2)) 40 V=H*3600+M*60+S 50 RANDOMIZE V |
これでどうですか。試してみればすぐ覚えられるでしょう。頑張ってね。
▲▲▲▲▲▲ ここまでは 2001/03/01 に書いています ▲▲▲▲▲▲
まず最初に言っておきますが、BASICを勉強している段階では別に知ってなくても問題ないです。
「これを覚えようとしたら難しくなるから」って、初心者向けのBASICがせっかく隠してくれている部分なので。
これを理解するためには、コンピュータの2進数の説明から始めないといけませんね。
▲▲▲▲▲▲ ここまでは 2001/03/03 に書いています ▲▲▲▲▲▲
2進数を最初から説明していくと大変なので簡単に。
その辺は数学の教科書でも見て下さい(苦笑)
コンピュータは電気のON/OFFの2値で情報を記憶しています。つまり、1か0かです。
特に1がONで0がOFFとは決められていないです。左のだと正論理、逆だと負論理と呼ばれます。
もう少し詳しく説明しましょう。
コンピュータの中には、こういう箱が延々と連なったものが用意されています。
右から1と0を入れていくと、数値が表現できますよね。
0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 |
上の場合は、(1×8)+(0×4)+(1×2)+(1×1)=11を表しています。
それぞれの桁にかける値は、1桁増えるごとに2倍になります。10進数なら10倍ですよね。それと同じです。
では、次に2進数の足し算をしてみましょう。
0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 |
に
0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
を足すとどうなるでしょうか。
1の位は、繰り上がりが起こり、0。
2の位は、繰り上がった分と足して、また繰り上がり、0。
4の位は、繰り上がった分だけなので、1。
8の位は、そのまま1。
つまり、
0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 |
となります。
要は11+1ですから、12になっていればいいわけですが……、ちゃんとなっていますね。
では次に、マイナスの数値をどうやって表現しているのか説明します。
考え方は簡単です。一番左端の箱が0ならプラス、1ならマイナスです。
しかし、ただ単に0と1を逆にしただけではプラスマイナスの逆転はできても、数値が変わってしまってうまくいきません。
これには2の補数という、説明するととんでもなくややこしくなることが関係しているので、ここでは説明しません(汗)
希望があるようならやりますが……別の題目でやらないといけないですね。
ここでは左端によってプラスマイナスが決定されるということだけを覚えておいて下さい。
それでは一度足し算に戻ります、次の場合はどうでしょうか?
0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
に
0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
を足すと、どんどん繰り上がっていって、左端が1になってしまいました。
1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
左端は符号を意味しているはずでしたよね?
つまり、本当なら127+2=129のはずなのに、詳しい数値はともかく答えはマイナスの値になってしまいました。
これです。この説明で言いたかったのはこれなんです。
変数の値が一度でも範囲外になると、正しい数値が記録されないと本文で書きましたよね。
この例のように符号が逆転してしまったり、他の変数が使っている箱に書き込んだりしてしまうんです。
ところで、この説明では1つの変数は8個の箱を持っていることにしていますが、箱1つ、つまり2進数の1桁のことをビット(Bit)といいます。
この言葉はどこかで聞いたことがあるでしょう。
64ビット機というふれこみのゲーム機がありましたね。あれはこの単位のことです。
何が64ビットなのかは、これもまたおいておきます(苦笑)。これを理解するにはアーキテクチャの基礎からやらないといけないし。
では、単位を説明しましょうか。
8ビット=1バイト(Byte)
1024バイト=1キロバイト(KB)
1024キロバイト=1メガバイト(MB)
1024メガバイト=1ギガバイト(GB)
MBはメディア関係(フロッピーディスク、MO、CD-RW)やメモリの容量で、GBはハードディスクの容量でお馴染みですね。
さて、話を戻して、と。
さっき範囲外と書きましたが、具体的な範囲も書いておきましょうか。
この変数は8ビットの領域を使っているので、範囲は左端の符号ビットを除いた7ビット分で、−128〜127です。
マイナスの方が1だけ多いのは気にしない(苦笑)
その範囲を越える数値を入れると、下手をすれば変数に用意された8ビットだけでは収まり切らなくなって、符号ビットの左のビットを書き換えてしまいます。
もし、その領域を他の変数で使っていたとしたら、今度はその変数の中身までも壊れてしまいます。
こういう類のバグをオーバーフロー(Overflow)と言います。
また余談になりますが、次の場合を計算してみましょう。
今度は都合により正の数限定(=符号なし整数:unsigned integer)の8ビット変数です。
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
これは255ですよね。正の数のみで8ビットだと、最高で255……何か思い出しませんか?
そうです、RPGで持てるアイテムの最大数。よくこの数字を目にしましたよね。
中途半端な数字だと思っていた人が多いと思います。「どうせなら100にしろ」ってね。
でも、使わないビットを余らせないことで、データ量の節約をしているんです。
アイテムの数はセーブしたときに記録しないといけませんよね?
それなら、メモリーカードに記録するときに使う容量は、無駄がなく少ない方がいい、というわけです。
セーブにかかる時間も短縮できますし。
99個っていうのもありますが、あれはまた別のお話。
表示スペースの問題ですな。
さて、理由がわかってもらえたでしょうか。
余計なことを書いて長くなってしまいましたが、これでもいくつか話題を伏せています(笑)
まあ、程々に、ということで。
▲▲▲▲▲▲ ここまでは 2001/04/04 に書いています ▲▲▲▲▲▲