配列変数とは?
今までに数値型変数,文字列型変数という2つの変数を使ってきました。
2,3個の変数なら簡単に用意できますがが、100,200個となってくるとさすがに辛いですね?
100個の変数を用意し、すべてに1を代入する…。
アナタならどうするでしょうか。
buf1 = 1
buf2 = 1
:
buf100 = 1
…代入するだけで100行も要りますね。
え?repeat命令とcntを使えばできそう?
変数名の変更はどうやって実現するんですか?
repeat 100
bufcnt = 1 ; bufとcntの間はどのように区切ればいいのか? 「buf[cnt]」か? 「buf_cnt」か?
loop
だいたい100個も変数使うような物を作らないから関係ない、と思っている方へ。
2Dシューティングを例にあげますと、
自機の位置を示すための座標用にX座標とY座標の2つが必要ですよ。
敵の座標用にも2つ要りますし、複数敵が登場する場合は当然(敵の数×2)個用意しないとダメですね。
弾を撃つなら弾の座標用に2つ要ります。
コレも単発なら2つだけですが、5発までいけるように設定するなら10個は要ることになります。
他にもアイテムの位置、敵の弾等…考えると非常に多くの変数が必要になってくることがわかると思います。
シューティングに限ったことではなく他のモノを作る時も何かと必要になってくるでしょう。
それじゃあ皆は数百、数千個も用意してるのかと言うと恐らくそうではないはずです。
実はこの章のタイトルにある「配列変数」というものを利用しているんですね。
配列変数とは何でしょうか?
簡単に言いますと、変数100個や200個を1つにまとめた変数のことです。
どういうことでしょう?
家1つが1つの変数だと考えてください。
Aさんの家は5人家族。Bさんの家は4人家族です。
1家族の人数を変数に入れる数値とすると、
A = 5
B = 4
のように1つの変数に対して1つの値しか代入できません。
コレに対して配列変数はアパート1つとなり、複数の住居(格納場所)があるアパートが1つの配列変数です。
Aアパートは2階建てで、1階に5人家族が、2階に3人家族が住んでいます。
Bアパートは3階建てで、1階に2人家族が、2階に6人家族が、3階には1人が住んでいます。
それぞれのアパートの1階分を配列変数に入れる数値とすると、 ※説明は後程します
A.0 = 5 ; Aアパートの1階には5人
A.1 = 3 ; Aアパートの2階には3人
B.0 = 2 ; Bアパートの1階には2人
B.1 = 6 ; Bアパートの2階には6人
B.2 = 1 ; Bアパートの3階には1人
となります。
つまりAと言う配列変数には2つ、Bには3つの値を代入することができます。
書式は別として配列変数の意味はわかっていただけたでしょうか?
非常に重要なのでわかってるならともかくわからないなら適当に飛ばさないでくださいね。
後々困ってきますので理解できるまで何度も読み返してください。
この講座では理解できないのでしたら、ネット検索で「配列変数」をキーワードに調べてください。
さてそれでは配列変数の宣言を説明します。
数値型の配列はdim命令、文字列型の配列はsdim命令を使用します。
まずはdim命令から…。
書式は「dim 配列変数名,1次要素数,2次要素数,…」となっています。
p1には使いたい配列変数名を指定します。
p2以降は指定した配列変数で最大何個まで扱えるようにするのかを指定します。
p2以降というのは多次元の配列を使う時のものです。
先ほどのアパート1つが1階に1つの情報が入っていてソレが複数階分あるので1次元配列です。
宣言としては「dim A,階層分」な感じです。
例えば1階に1家族だけではなく、1階だけで3部屋(3号室)会って3家族が住んでるなら2次元配列です。
つまり「dim A,階層分,同階層の部屋数」といった感じでp3も使います。
九九なんてのも2次元ですね。
グラフで言うとX軸とY軸があるものです。
3次元と言うのは、XYZの3つあるものですね。
「横」「高さ」「奥行き」と3つの要素が必要な場合に使います。
先ほどのアパートで言うと、同じ階層・1階層の部屋数を持つアパートが複数(棟)集まったもの、
つまり、団地のイメージがまさにソレです。
宣言は「dim A,階層分,同階層の部屋数,棟番号」です。
4次元はこの団地が複数集まった感じで「dim A,階層分,同階層の部屋数,棟番号,団地番号」となります。
まぁ階数・1階層の部屋数・棟数が全く同じ団地が複数あるなんてのは少ないとは思いますけど。
HSPでは最大4次元までしかダメですがそこまで使うことはレアです。
使い方について説明していきましょう。
またまた先ほどのAアパートを例にすると、
dim A, 2 ; Aという名前で2つまで数値を扱えるようにする
と宣言します。
こうすると宣言したスクリプトの位置以降はAに2つまで数値を入れることができます。
数値の代入や中身の表示の仕方は、Aの2つ目に4を代入したいのであれば、
A.1 = 4 ;※Aと1の間は「,」コンマではなく「.」ピリオドです!
mes A.1 ; Aの2番目の内容を表示
stop
とします。
注意としては要素番号は1からではなく0から始まるということです。
「A.?」のこの何番目かを表す「?」の部分は通常は数値で指定しますが、
変数に値を入れてその変数の値で指定することも可能です。
abc = 1 ; 変数abcに1を代入
A.abc = 10 ; abcは1なのでA.1に10を10を代入
mes A.abc ; A.1の内容を表示
stop
変数で渡す利点は、数値で指定した場合、
A.0 = 5
A.1 = 5
A.2 = 5
こういう場合、当然ながら3回行わなければなりません。
10個使うなら10回、100個使うなら100回行う必要がありますが、
変数で指定した場合、繰り返し命令を使うことで記述は1回だけでよくなるのです。
abc = 0
repeat 3
A.abc = 5
abc = abc + 1
loop
3回行うくらいなら直接書くほうが少なくて、見た目もわかりやすいかもしれませんが、
数が多くなっても変数の方は行数も変わることなく、柔軟性に飛んでいます。
どの辺りが柔軟性かというと、
例として「A.0から順に0,1,2と数値を入れていたがA.10から順に0,1,2と入れて行きたい」となった時、
A.0 = 0
A.1 = 1
:
A.99 = 99
A.10から値を自分で0,1,2…と書き換えていかなければなりません。
それに対し、
abc = 10
repeat 90
A.abc = cnt;
abc = abc + 1
loop
…わかっていただけたでしょうか?
変数で値を指定することで配列変数本来の魅力を引き出せるのです。
これでこの章の初めの変数100個全てに1を入れるということができるようになりましたね。
dim buf, 100 ; bufに100個までの数値を入れることができるようにする
repeat 100
buf.cnt = 1 ; buf.0〜buf.99まですべてに1を入れていく
loop
stop
実行させても表示させる命令を入れていないので確認できませんね。
こういうときは、メニューバーの「HSP」-「Debugウィンドゥ表示」をクリックし、
項目の左にチェックが入ったことを確認した上でもう一度実行してください。
いつものウィンドウの他に「HSP Debug Window」というのが出てきたと思います。
このデバッグウィンドウは現在実行しているスクリプトの変数の内容等を確認できるものです。
上側の白色リストボックスに上から「全般、システム変数…変数buf」と並んでいると思います。
その中の「変数buf」を選択し、右側の「配列変数を表示」にチェックを入れてください。
すると、下側の灰色のボックスの中に[配列の内容]というのが表示されます。
これでbuf.0〜buf.99の100個すべてに1が入っていることが確認できました。
ではこの配列変数と前章説明したgettime命令で日付時刻を表示させるスクリプトを考えてみましょう。
dim time,8 ; 年,月,(曜),日,時,分,秒,(ミリ秒)
repeat 8
gettime time.cnt, cnt ; time.0から順にp2タイプ0〜7を代入
loop
mes "" + time.0 + "年"
mes "" + time.1 + "月"
mes "" + time.3 + "日"
mes "" + time.4 + "時"
mes "" + time.5 + "分"
mes "" + time.6 + "秒です"
stop
gettime命令で8個のタイプを取り出す作業をたったの3処理だけで実現できました。
ちなみに
A.0 = 1
A.1 = 2
A.2 = 3
と代入するものを、
A = 1, 2, 3
のように「,」(セミコロン)で区切ることによりA.0から順に値を入れていくこともできます。
省略した要素はすべて0が代入されます。
途中要素から代入したい場合は下記の様にすればOKです。
A.3 = 4, 5, 6 ; A.0〜A.2入ってない場合(0,0,0,4,5,6となる)
では文字列型のsdim版を説明しましょう。
書式は「sdim 使いたい変数名,1つの要素で扱える最大文字数,扱える要素数,…」です。
dimとは違ってなぜ初めから2次元も必要なんでしょう?
文字列の場合、数値と違って1つのテキストだけで1次元の配列変数が必要となります。
知ってる人は知ってますが、1要素で保存できるのは文字列ではなく「文字」1つ分なんですね。
なので文字列を保存する場合、文字数分だけ配列要素数を確保してやらなければなりません。
「おはよう」「こんにちは」「こんばんは」の3テキストを保存するなら合、2次元配列が必要です。
なお、日本語や全角文字と呼ばれるものは1文字で2バイト、半角文字2文字分必要です。
sdim C, 11, 3 ; 今は使いたい分+1確保すると覚えておいてね
C.0 = "おはよう"
C.1 = "こんにちは"
C.2 = "こんばんは"
mes C.1
stop
dim命令と同じで、
sdim C, 11, 3
C = "おはよう", "こんにちは", "こんばんは"
mes C.1
stop
とまとめて定義することもできます。
通常の変数の場合、半角で64文字までしか扱えないとなっていましたが、
sdim命令で確保することにより、そのサイズ分まで扱えるようになります。
sdim buf, 256 ; bufは256文字まで使えます
stop
この文字列型配列変数を使えばgettime命令の曜日の部分も短いスクリプトで行うことができますね。
sdim youbi, 3, 7
youbi = "日","月","火","水","木","金","土"
gettime wd, 2
mes "今日は" + youbi.wd + "曜日です"
stop
1つの要素で扱える最大文字数は使いたい数より少し多くしておくほうがよいと思います。
もしも確保しているサイズより内容の方が大きい場合、
別の変数の確保している部分にも書き込んだりして、変数を破壊してしまいます。
最悪の場合、強制終了してしまい、EXEが落ちてしまうこともありますので気を付けてください。
ヘルプにはalloc命令が載っています。
この命令でも上記の様に、指定した変数のサイズを変更できるものですが、
古いバージョンのHSPで使われていたものであり、過去の互換性のために残されている命令ですので、
今後いつ消えてもおかしくない命令としてあまり使用しないことをお勧めします。
また、alloc命令は64バイト以上しか確保できません。
alloc buf, 128 ; bufは128文字まで使えます
stop