パソコン活用研究5番街(Visual Basic、Excel(VBA)、BASIC プログラミング研究)

配列、FOR ... NEXT, READ, DATA


1 大量のデータを変数に読み込む

大量のデータを扱う時に便利なのが、配列です。
DIM A(100)
と宣言することにより、A(0)からA(100)まで101個の変数が用意されます。
* ほとんどのBASICで、配列の添え字はA(1)ではなく、A(0)から始まる点に注意して下さい。

配列と、FOR ... NEXT, READ, DATA を使って、大量のデータを変数に読み込ませることができます。
例として、以下に 「いつ どこで 誰が 何を どうした」 GAME のリストをあげます。 
DIM(配列), FOR ... NEXT, READ, DATA以外は INPUT, PRINT, IF ... THEN, RND等の基本命令しか
使っていませんので分かりやすいと思います。

このように、大量(このGAMEではさほど大量ではないですが)のデータを使うプログラム
で、データを変数にセットする場合、この方法が定石となっています。

まず、20行で配列の宣言をしています。when$ (いつ?のデータ用)  where$ (どこで?
のデータ用) ・・・といった具合です。
25行のrestore は以下の readで読み込むデータ(data のある行)行の先頭行を指定
しています。この場合 when$()に読み込むデータは500行から読みはじめろ、ということに
なります。
以下 for ... next と readで次々にデータを変数に読み込んでいます。
300行からは、乱数(rnd)を使って、ランダムにデータを選択して表示しています。
400行からは、ユーザーの入れたデータ(どこで、何を)とコンピューター(いつ、誰が、どうした)
の合作の表示です。

いつ どこで 誰が 何を どうした GAME <N88互換Basic for Win用>

10 '** いつどこで誰が何をどうしたGAME ver0.0.1 **
20 '** N88互換BASIC用 Written By KASAI **
20 dim when$(11), where$(15),who$(11),what$(12),verb$(10)
25 restore 500
30 for i=0 to 11
40 read when$(i)
50 next
55 restore 510
60 for i=0 to 15
70 read where$(i)
80 next
85 restore 520
90 for i=0 to 11
100 read who$(i)
110 next
115 restore 530
120 for i=0 to 12
130 read what$(i)
140 next
145 restore 540
150 for i=0 to 10
160 read verb$(i)
170 next
180 randomize val(right$(time$,2))
190 print "いつ どこで 誰が 何を どうした GAME ver0.0.1 Written by KASAI"
200 print "1 ComputerのDEMO 2 コンピューターとあなたで合作する 3 終わり (半角で入力して下さい)"
210 a$=input$(1)
220 if a$="1" then gosub 300
230 if a$="2" then gosub 400
235 if a$="3" then end
240 goto 190
300 print when$(int(rnd*12))
310 print where$(int(rnd*16))
320 print who$(int(rnd*12))
330 print what$(int(rnd*13))
340 print verb$(int(rnd*11))
350 print:return
400 input "どこでを入力して下さい",whe$
410 input "何を、を入力して下さい",wha$
415 print when$(int(rnd*12))
420 print whe$
425 print who$(int(rnd*12))
430 print wha$
440 print verb$(int(rnd*11))
450 print:return
500 data きのう,今日,おととい,1年前,朝,昼,真夜中,夏休み,旅行に行った時,1週間前
505 data 冬,昼休み
510 data トイレで,家の前で,レストランで,公園で,階段で,駅で,デパートで,屋上で,バスの中で,机の上で
515 data 海で,山で,本屋で,花屋で,職員室で,社長室で
520 data 僕が,赤ちゃんが,弟が,お母さんが,おじさんが,おまわりさんが,猫が
525 data アメリカ人が,いぬが,友達が,先生が,金髪の美人が
530 data バナナの皮を,うんちを,アイスクリームを,シャベルを,ボールを,本を
535 data 1000円札を,団子を,コンピューターを,ぽけもんを,飴を,本を,花を
540 data 食べた,拾った,投げた,蹴飛ばした,踏み潰した,ポケットに入れた,捨てた
550 data 眺めた,飛び越えた,見つけた,踏んづけてころんだ

 

2 配列を使って大量の敵(キャラ)を動かす。


BASIC超基本2では、敵のキャラクタを1つだけ動かすプログラム例をあげましたが、
配列を使えば、簡単にたくさんのキャラを動かすことができます。
下のプログラムはFM8kame.bas(N88互換Basic for Win用 N88互換Basic の
ページからダウンロードできます)の敵キャラ移動ルーチンの抜粋です。
変数の付け方が汚くて申し訳ありませんが、このゲームはかなり多くのキャラを動かして
います。
敵キャラは2種あり、一つは牛 "C" (500行から600行)、もう一つは虎 "T"(610行から
690行まで)です。
(1)  牛
牛の頭数は変数maxに設定してあります。ワンターンではそのうち3頭づつ動かしています。
牛は単純に一つ左に移動させています。ただし、前に他の牛、虎がいる時はその位置にとどまります。
変数は
Pが牛の番号(1からmaxまで)
Aは3頭づつ動かすためのカウンタ用 A>3となったら牛移動ルーチンから抜ける
cx(), cy() は牛のx座標、y座標
char( , )  その座標に  0なら何もいない 1なら牛がいる  2なら虎がいる

(2)  虎
虎は8頭です(No.1からNo.8)
虎の移動は for ... next ループを使って、8頭の移動処理をしています。
8頭分の処理が終わってからメインルーチンにリターンさせています。
虎の移動は、他の牛、虎を避けて動くようにしてあります。基本は一つ左に移動(1)。もし、そこに牛、虎が
いたら斜め上に移動(2)。そこにも、牛、虎がいるか、道路にはみだすようなら、斜め下に移動(3)。
もし、そこにも牛、虎がいるなら、元の位置のすぐ下に移動(4)。それでもだめなら移動しない。
下の1から4の順で虎の移動先を選んでいきます。

     2
     1<T
     3  4


変数
G   虎の番号(No.1からNo.8)
tx, ty  虎のx座標、y座標
QT1, QT2 虎の元の座標一時保存用
char  牛と同じ

ということで、牛も虎も配列を使い、通し番号で個々のキャラを識別、制御しています。
スマートでなくきたないコードですが、参考にして下さい。

FM8kame.bas (ver0.6) 抜粋

500 P=P+1:A=A+1
510 IF P>max THEN P=1        '牛のNoがmaxを超えたらNo.1に戻す
520 IF A>3 THEN A=0:RETURN     '3頭動かしたらリターン
525 LOCATE cx(P),cy(P):PRINT" ":char(cx(p),cy(p))=0:r1=cx(p):t1=cy(p)   '牛を消す char(  )=0にする
530 cx(P)=cx(P)-1              '一つ左に座標を移動
540 IF cx(P)<10 THEN GOTO 545 ELSE 570  '左端(X座標 10)まできたら右端移動の処理(545行へ)
545 cx(P)=31                   '右端(X座標31)
550 LOCATE 10,cy(P):PRINT" ":char(10,cy(p))=0
560 cy(P)=INT(RND(1)*6)+6          'Y座標をランダムに決定
570 oi=char(cx(p),cy(p))
572 if oi<>0 then cx(p)=r1:cy(p)=t1      '他の牛、虎いたら元の座標に戻す
580 LOCATE cx(P),cy(P):PRINT"C":char(cx(p),cy(p))=1    '新座標で表示
590 IF cx(P)=X AND cy(P)=Y THEN GOTO 900     '自分のキャラ(かめ)との当たり判定。当たりなら900へ
600 GOTO 500
610 FOR G=1 TO 8                '虎  No.1から No.8
620 LOCATE tx(G),ty(G):PRINT" ":char(tx(g),ty(g))=0:QT1=tx(G):QW1=ty(G)  '虎消す
630 tx(G)=tx(G)-1                 '以下636行まで移動先(他の牛、虎のいない場所)の決定
631 OI=char(tx(G),ty(G))
632 IF OI<>0 THEN ty(G)=ty(G)-1 ELSE 640
633 OI=char(tx(G),ty(G))
634 IF OI<>0 OR ty(g)<=5 THEN ty(G)=ty(G)+2 ELSE 640
635 OI=char(tx(G),ty(G))
636 IF OI<>0 THEN tx(G)=tx(G)+1 ELSE 640
637 OI=char(tx(G),ty(G))
638 IF OI<>0 THEN tx(G)=QT1: ty(G)=QW1    '移動先のない時は元の座標に
640 IF tx(G)=9 THEN 650 ELSE 665        '左端まで来た時の処理
650 tx(G)=31:ty(G)=INT(RND(1)*6)+6
660 IF ty(G)<6 THEN ty(G)=6 ELSE IF ty(G)>12 THEN ty(G)=12
662 oi=char(tx(g),ty(g))
663 if oi<>0 then tx(g)=qt1:ty(g)=qw1
665 LOCATE tx(G),ty(G):PRINT"T":char(tx(g),ty(g))=2   '新座標の表示
670 IF tx(G)=X AND ty(G)=Y THEN 900           '自分のキャラ(かめ)との当たり判定
680 NEXT
690 RETURN


以下はVer0.5のコードです。移動先で他のキャラとの重複の判定が甘いので、キャラの重なることが
ありました。バグ?の例として参考までにあげておきます。どこが甘いかはご自分で判別して下さい。
なお、変数(牛、虎の座標)がver0.6と違います。


500 P = P + 1: A = A + 1
510 If P > 30 Then P = 0   '牛のNo.29を超えたらNo.0に戻す
520 If A > 3 Then A = 0: Return  '3頭動かしたらリターン
525 LOCATE R(P), T(P): Print " ": char(R(P), T(P)) = 0  '牛を消す
530 R(P) = R(P) - 1      '一つ左に座標を移動
540 If R(P) < 10 Then GoTo 545 Else GoTo 580   '左端(X座標 10)まできたら右端へ
                     '560行まで左端に来た牛を右端へ戻す処理
545 R(P) = 31                       '右端(X座標31) 
550 LOCATE 10, T(P): Print " ": char(10, T(P)) = 0
560 T(P) = Int(Rnd(1) * 6) + 6              'Y座標をランダムに決定
580 LOCATE R(P), T(P): Print "C": char(R(P), T(P)) = 1  '新座標で表示
590 If R(P) = x And T(P) = y Then GoTo 900  '自分のキャラとの当たり判定。当たりなら900へ
600 GoTo 500

610 For G = 1 To 8       '虎  No.1から No.8  
620 LOCATE QT(G), QW(G): Print " ": char(QT(G), QW(G)) = 0
630 QT(G) = QT(G) - 1
631 OI = char(QT(G), QW(G))
632 If OI = 1 Then QW(G) = QW(G) - 1 Else GoTo 640
633 OI = char(QT(G), QW(G))
634 If OI = 1 Or QW(G) <= 5 Then QW(G) = QW(G) + 2 Else GoTo 640
635 OI = char(QT(G), QW(G))
636 If OI = 1 Then QT(G) = QT(G) + 1 Else GoTo 640
640 If QT(G) = 9 Then GoTo 650 Else GoTo 660
650 QT(G) = 31: QW(G) = Int(Rnd(1) * 6) + 6
660 If QW(G) < 6 Then QW(G) = 6 Else If QW(G) > 12 Then QW(G) = 12
665 LOCATE QT(G), QW(G): Print "T": char(QT(G), QW(G)) = 2
670 If QT(G) = x And QW(G) = y Then GoTo 900
680 Next
690 Return

TOP PAGE >Basic活用研究目次