プチコン3号&BIGまとめWiki

プチコン3号&BIG 非公式初心者講座 : 第15章 サンプルプログラム7 (その3)

パンくずリスト

プログラマーからひとこと

サンプルプログラム7を見ていくのも、とうとう3回目です。
全4回でまだ1回分ありますが、今回がクライマックスです。
なぜならページの長さがいちばん長いからです。
ボス戦前のダンジョンとかこんな感じですよね。

今回は1章ごとにけっこうドンドン進みます。
そのスピードにおいていかれることもあるかもしれませんが、そんな時ははじめに戻って、きっちりわかったあたりで次に進むくらいがいいかもしれません。
なんだか勉強っぽくてイヤかもしれませんが、なにしろラストダンジョンです。
ワンパク君たちが迷うところではいっしょに迷いつつ、いっしょに戦っていきましょう。
ところで、「ワンパク君」とかあたりまえのように呼んでますが、あれ、本名なの?

敵を出してみよう

インテリくん

ここまででプレイヤー側の動きはだいたいできあがったね。いよいよ敵の動きのプログラムに入ってみようか!

神崎

今までよりも大変そうなヨカン……。

インテリくん

ははは。たしかにタクサンの敵がジグザグに動き回るから、これまでよりもフクザツではあるね。
最初はカンタンに、スタートしたときのならび方から始めようか。

ワンパクくん

しかしプレイヤーキャラ1つ動かすだけでも、ケッコウ考えるコトが多いもんだぜ……。

ワンパクくん

カンタンって言っても、こういうワケじゃねェよな?

  1. LOCATE 0,3
  2. PRINT ”Е Е Е Е Е Е Е Е Е Е”
  3. LOCATE 0,5
  4. PRINT ”Е Е Е Е Е Е Е Е Е Е”

サスガにココまでカンタンじゃねェとは、オレにもワカるぜ。

神崎

たしかに、そうかも。サンプルをRUNしてみると、敵Еは1匹ずつ順に動いてるんだよね。ショットでやられたらその敵だけが消えるわけだし……。

インテリくん

つまり1匹ずつ、あわせて20匹ぶんの変数がいるわけだね。……こう言えば、今までにおぼえたコトが役に立つんじゃないかな?

ワンパクくん

そうか! 20個の変数をヨウイするんだな!

インテリくん

い、いや……

神崎

……じゃなくって、配列変数を使うんだよね。

インテリくん

そうそう、ソコだよ!

  1. DIM EX[20]:DIM EY[20]:DIM ED[20]

ゲームで使うのはこんなところかな。敵は英語で「Enemy(エネミー)」だから、変数の頭文字には「E」をつけることにするよ。

神崎

EXEYはやっぱり、ヨコ(X)とタテ(Y)かな?

インテリくん

そうそう。ヨコがXでタテがYという変数の名付け方は、はっきりルールがあるワケじゃないけど、プログラマーの人はたいていこう書くね。おぼえておいていいんじゃないかな。

変数EDの「D」は「Dynamics (ダイナミクス)」のDなんだけど、……まあ、「動き方」くらいに考えておけばいいかな。

ワンパクくん

やけにハッキリしない言い方じゃねェか。ナニか言いたくないイミでもあんのか!?

インテリくん

「力学」とか「変動」とか……

ワンパクくん

おベンキョウの話だったか、キタイはずれだゼ!

神崎

ま、まあ分かりにくいのは本当かな。とにかく変数EDは敵がどう動くかのフラグにするってことだね?

インテリくん

そういうコト。とりあえず最初はにしておいていいかな。

ハカセ

ネンのタメに、ここで配列変数をどう使うのかまとめておこうかのう。
たとえば1匹めの敵は配列の番号を[0]に統一するのじゃ。こやつのいる場所を調べたければ、横方向なら配列変数EX[0]、縦方向ならEY[0]じゃな。同じように2匹めの敵なら、EX[1]EY[1]で場所が決まっているワケじゃ。
それとタダの書き方のモンダイじゃが、

  1. DIM EX[20]:DIM EY[20]:DIM ED[20]

というふうにコロン()で分けなくても、

  1. DIM EX[20],EY[20],ED[20]

と、ひとつのDIM命令でスッキリ書くこともできるぞい。

ワンパクくん

じゃあ、その3つの配列変数を使いながら敵をナラべてみるゼ!

  1. FOR I=0 TO 9
  2.  EX[I]=I*2
  3.  EY[I]=3
  4.  ED[I]=0
  5.  LOCATE EX[I],EY[I]
  6.  PRINT ”Е”;
  7. NEXT
  8. FOR I=10 TO 19
  9.  EX[I]=I*2−20
  10.  EY[I]=5
  11.  ED[I]=0
  12.  LOCATE EX[I],EY[I]
  13.  PRINT ”Е”;
  14. NEXT

……け、けっこうメンドくせェな、コレ!

ハカセ

イヤイヤ、なかなかジョウデキじゃぞい。トクに20行目なんかはクロウのアトがみえるのう。

神崎

敵が2列にならんでいるから、FOR文を2回に分けて作らないといけなかったんだね。

たしかに「FOR I=0 TO 19」ひとつで終わらせる方法ってないもんなあ。IF文で変数が10を超えたら……いやいや、それもプログラムが長くなっちゃう……

ワンパクくん

このタメだけに似たような行を2つ書くのがなんたってメンドクセェぜ!

インテリくん

実は、すごく短くする方法があるんだけど……

ワンパクくん

な、ナニ!? キキズテならねえな!

短かくしてみよう

インテリくん

さっきのワンパク君のプログラムでも必要なコトはできてるから、わざわざ短くしなくてもいいんだけど……

ワンパクくん

イヤイヤ、さっきのプログラムを打つのはかなりメンドウだったんだぜ。短くなるならカンゲイじゃねェか?

ハカセ

ならば、こう書くと短くなるのう。

  1. FOR I=0 TO 19
  2.  EX[I]=FLOOR(I MOD 10)*2
  3.  EY[I]=FLOOR(I/10)*2+3
  4.  ED[I]=0
  5.  LOCATE EX[I],EY[I]
  6.  PRINT ”Е”
  7. NEXT
ワンパクくん

ハ……ハァ!?

神崎

たしかに短いけど……よくわからない……

ワンパクくん

そうか、まだ習ってねェFLOORがカギだな! これにスゲェ意味が……

インテリくん

FLOORは「切り捨てて整数にする」命令だよ。たとえばA=FLOOR(1.75)と書けば変数には1.75から「.75」を切り捨ててが入るね。

ワンパクくん

ふ、フツウだぜ!

ハカセ

「FLOOR(フロア)」すなわち「たいらにする」というイミじゃから、整数にするというイミに変わったのじゃな。
12行目の計算をカンタンに言いなおすと、「変数を10で割ったあまりから小数点以下を切りすてて2倍する」となるのう。

ワンパクくん

ぜんぜんカンタンじゃねー!

神崎

うーん、なるほど……たしかにEX[0]=0EX[1]=2EX[2]=4と2ずつ増えていって、EX[10]になったとたんEX[10]=0に戻っているね。やりたかったコト通りではあるんだけど……なんだかフシギだなあ。

ハカセ

13行目も、「を10で割って小数点以下を切りすてたら、2倍して3を足す」だけじゃがこれで敵の1〜10匹めまではタテ位置行目に、11〜20匹めまではタテ位置行目にそろうというワケじゃ。

ワンパクくん

ウ……ウウ……。ケイサンしてみたらタシカにその通りだったが……セイカツの中でまったく出てこねェ式にもホドがあるぜ!

インテリくん

あんまりパッと出てくる計算じゃないかもね。
でも「FLOOR(I/N)ならが『の倍数』になるたび1増える」。
FLOOR(I MOD N)ならが『の倍数』になるたびゼロまでおり返しながら1増えていく」。
原理まで考えなくても、こう丸アンキしておくとプログラムで使えるバメンはけっこう多いよ。

ハカセ

たとえば時計を考えてみい。1時間は60分で、0分〜59分をくり返すものじゃが、この「分」はFLOOR(I MOD 60)で書きあらわせるのう。「時間」はFLOOR(I/60)と書けばいいワケじゃ。
かなりカタいたとえになってしまったが、サンプルプログラムのように、敵をセイレツさせるようなコトにも応用できるんじゃぞい。

神崎

プログラマーの生活のチエってところかな。

インテリくん

そういうコト。そうそう、ここでは「FLOOR(I MOD N)」なんて書いたけど、本当は「割り算のあまり」に小数が出てくるハズはないから、「I MOD N」と書くだけでいいんだよ。

ハカセ(泣)

ワシは……ワシは、見た目をそろえておきたかったのじゃああああ

敵を動かそう

ワンパクくん

敵をならべた後は、イヨイヨ動かすワケだが……

神崎

今までとちがって1方向や2方向じゃないのが、ナヤむところだね。

インテリくん

迷ったら、まずセイリしてみよう!

0右に動くX=49になるまでX+1
1下におりる1回だけY+1
2左に動くX=0になるまでX-1
3下におりる1回だけY+1

キホン的には、このくり返しだよね。

ワンパクくん

そう言われれば、そう……なのか?

神崎

ショットで撃たれたり、下までおりて上にもどるのが抜けてるけど……

インテリくん

そこはもっとアトから考えよう! まずこの表にある動きをクリアーしないとそこまでたどりつかないしね。

ワンパクくん

そのワリキリ、キライじゃねえな! じゃあとにかくサブルーチン「ALIEN(エイリアン)」をメインルーチンから呼び出すことにするぜ!

  1. GOSUB @ALIEN

で、アトは……1匹ずつ動かすコトだけ考えるゼ!

  1. ’−−− しんりゃくしゃ
  2. @ALIEN
  3. FOR I=0 TO 19
  4.  LOCATE EX[I],EY[I]:PRINT” ”
  5.  GOSUB @EMOVE
  6. NEXT
  7. RETURN

動かすトキのキホンだから、” ”で消すだけは消しといたゼ。 こっからサキはナガくなりそうなんで@EMOVEGOSUBさせといたが、モンダイはどの方向に動かすか……だな。

インテリくん

なかなかワルくないよ。飛んだ先でまた別のラベルに飛ぶけど、こうすると分かりやすいんじゃないかな。

  1. @EMOVE
  2. ON ED[I] GOTO @RI,@DW,@LF,@DW
ED[I]=0右に動くX=49になるまでX+1
ED[I]=1下におりる1回だけY+1
ED[I]=2左に動くX=0になるまでX-1
ED[I]=3下におりる1回だけY+1

この表のとおりだね。フラグに使ってる変数ED[I]の数しだいで、ラベル@RI@DW@LF@DWのどれかに飛ぶってやり方さ。

神崎

ああそうか、ラベルはそれぞれ「右(RIght)」「下(DoWn)」「左(LeFt)」になってるんだ。

ワンパクくん

とりあえず、右に動かすコトだけ考えるゼ!

  1. @RI
  2. EX[I]=EX[I]+1
  3. LOCATE EX[I],EY[I]
  4. PRINT ”Е”
  5. RETURN

コレで……まあ、右にだけはウゴくだろうな。

神崎

ずいぶんドンドン行くなあ。
でも、のこりの方向も同じように動かせそうだね。

  1. @DW
  2. EY[I]=EY[I]+1
  3. LOCATE EX[I],EY[I]
  4. PRINT ”Е”
  5. RETURN
インテリくん

やってるコトがカブる行が多いから、ゼンブをまとめるとこうなるかな。

  1. @RI
  2. EX[I]=EX[I]+1
  3. GOTO @EPUT
  4. @DW
  5. EY[I]=EY[I]+1
  6. GOTO @EPUT
  7. @LF
  8. EX[I]=EX[I]−1
  9. GOTO @EPUT
  10. @EPUT
  11. LOCATE EX[I],EY[I]
  12. PRINT ”Е”
  13. RETURN

ラベル名の「PUT(プット)」は日本語では「置く」というイミになるかな。敵キャラを画面に置くルーチンってことだね。

ワンパクくん

ココまではよし。……というか、まだ右に行くコトしかデキてねェな。フラグがED[I]=0のまんまだからな。

神崎

いまRUNしても、右ハジまで来たら表示がおかしくなるよ。

ワンパクくん

マカセとけ! たとえば@RIなら、右ハジに来たときだけフラグを変えてやりゃいいんだな?

  1. @RI
  2. EX[I]=EX[I]+1
  3. IF EX[I]<49 THEN @EPUT
  4. ED[I]=1
  5. GOTO @EPUT

てコトは、@LFでも同じようにできるハズだゼ!

  1. @LF
  2. EX[I]=EX[I]−1
  3. IF EX[I]>0 THEN @EPUT
  4. ED[I]=3
  5. GOTO @EPUT
インテリくん

ふむふむ。

ED[I]=0右に動くX=49になるまでX+1@RI
ED[I]=1下におりる1回だけY+1@DW
ED[I]=2左に動くX=0になるまでX-1@LF
ED[I]=3下におりる1回だけY+1@DW

フラグED[I]になると、次はラベル@DWに行くことになるね。

神崎

@DWでは下におりるのは1回だけだから、すぐフラグを変えることになるね。

  1. @DW
  2. EY[I]=EY[I]+1
  3. IF ED[I]==1 THEN ED[I]=2
  4. IF ED[I]==3 THEN ED[I]=0
  5. GOTO @EPUT

こうやってIF文を使うことになるのかな?

ワンパクくん

ン? ……ああそうか、さっきまで右に動いていたとき(ED[I]==1)と、さっきまで左に動いていたとき(ED[I]==3)で、次に立てるフラグがカワッてくんのか。

インテリくん

せっかくだから、今まででおぼえたコトを使って、もっとシンプルにしてみようか。

  1. @DW
  2. EY[I]=EY[I]+1
  3. ED[I]=(ED[I]+1) AND 3
  4. GOTO @EPUT
ワンパクくん

……ナニ?

神崎

あ、ビット演算かあ……。

ワンパクくん

ケッ! オリコウさんドモはいつもこうだ! ウーム、のトキは2進数で10で、は2進数で11だから……ブツブツ……

神崎

えーと、ようするに86行ではED[I]のナカミが1だけふえるけど、になったときだけはにもどされるってコトだよね?

インテリくん

ワリとカンタンなんだけどなあ。

ワンパクくん

デキるヤツの考えのオシツケはマッピラだぜ!

インテリくん

ヒドい言われようだよ。まあ、ビット演算の話はもっと後からくわしくおぼえることにしようか。
そうそう、画面の下まで行ったらまた上から出てくる動きも足しておこうね。

  1. IF EY[I]>20 THEN EY[I]=3
ワンパクくん

ナルホドな。コレでとりあえず、敵の動きはひととおりデキたか……。
ずいぶんトントンビョウシじゃねェか。RUNしてみるか!

神崎

……なんか、ちがう……

ワンパクくん

ウオォー! ナンだこの動き、ナンかチガうぞコレ、っつかキモチワリー! なんかキモチワリー!

ハカセ

ふぉっふぉっふぉ。ようやく気づいたようじゃのう。めざしていた正しい動きはこっちじゃよ。

ワンパクくん

そうだコレだ。敵は下におりるトキは、1匹ずつじゃなくマトメて下におりるんだ。チクショウ、どこでマチガエたんだ!?

インテリくん

ここまでにミスがあったワケじゃないよ。まだそういう動きをプログラムしてないっていうだけさ。

足りないところをつけ足してみよう

インテリくん

ちょっとアタマをヒネるところだよ。いいかい?
今までは「1匹ずつ、右ハジ・左ハジに来たら下に行く」ことにしていたね。

神崎

うん、そのハズ。……そうだよね?

ワンパクくん

ムシロ、そのドコがワルいのかがワカらねーぜ!

インテリくん

ところが、ボクらがやろうとしてたのは「どれか1匹が右ハジ・左ハジに来たら、次のターンでは敵全部がその場から下に行く」動きなんだよ。

神崎

……!

ワンパクくん

つまりアレか、今までやってたのは行列を作って歩く「ムカデ歩き」の動きで、本当にやりたいのは行進の「右向け、右!」でゼンインがいつでも同じ方向をむく動きってコトか?

ハカセ

わりとヨウチじゃが、悪くないたとえじゃぞい。ココまでわかれば、アトはできるんではないかの?

ワンパクくん

待て待て待て、やるべきコトはだいたいワカったが、けっこうコンランするぜ!

インテリくん

急にハッソウを変えるところだからね。順にかたづけていこうか。

神崎

まず、方向を変えるきっかけは「どれか1匹が右ハジ・左ハジに来たら」だよね。ここから考えてみようよ。

ワンパクくん

それは、ツマリ……@RI@LFの中の、IF文にひっかからなかったトキじゃねェか!

  1. @RI
  2. EX[I]=EX[I]+1
  3. IF EX[I]<49 THEN @EPUT
  4. ED[I]=1
  5. GOTO @EPUT

この81行目のあたりだな!

インテリくん

そうだね。ここでED[I]のフラグを変えてるけど、これだと[I]に入った1匹ずつ、右ハジにつくまでフラグが変わらないね。

ワンパクくん

ソレじゃマズいんだよな……そのカワリに、ゼンインのフラグを変える方法……?

神崎

もう1つ、大きなフラグを作ったらいいんじゃないかな!

  1. EDW=TRUE

81行目を新しい変数EDWのフラグを立てるように書きかえたよ。
このフラグが立ってる時は、どこにいる敵でもフラグED[I]を下におりるように変えたらどうかな?

ワンパクくん

フラグED[I]を変えるフラグがEDWか……ドンドンややこしくなってくるぜェ……。

インテリくん

ここがサイゴのカベだよ、がんばろう!

神崎

画面のハジに来たことはEDWで分かるようになったから、「次のターンで敵ぜんぶがその場から下に行く」動きをプログラムすればいいんだよね。
さっきのビット演算ED[I]=(ED[I]+1) AND 3を使えばそれでいいかな。

ワンパクくん

ムムム……。次のターンってことは、だいぶ前にモドるがこのあたりか。

  1. ’−−− しんりゃくしゃ
  2. @ALIEN
  3. FOR I=0 TO 19
  4.  LOCATE EX[I],EY[I]:PRINT” ”
  5.  GOSUB @EMOVE
  6. NEXT
  7. RETURN

ココのFOR〜NEXTで敵を動かしてたハズだぜ!

神崎

いちど敵のターンが終わってからED[I]のフラグを変えるわけだから……アレ? フラグを変えていい場所がないよ!?

ワンパクくん

ナニ言ってんだ……オ、オォ!?
なんてこった、タシカにそうだぜ! 70行目のアトでフラグを変えてもシッパイだし、72行目のアトじゃFOR〜NEXTループが終わってるからED[I]って書いてもナンにもならねェぞ!

インテリくん

ソコがモンダイだね。フラグEDWが立つのは敵のターンのトチュウだから、まず敵のターンが終わるまで待たなきゃいけない。でも敵のターンが終わったFOR〜NEXTの外だとED[I]を変えるコトができない。

ワンパクくん

ハマリじゃねェか! どうしようもねえ!

神崎

うーん、FOR〜NEXTが終わったあとに、もう1回こういうFOR〜NEXTを置くのはどう?

  1. FOR I=0 TO 19
  2.  IF EDW THEN ED[I]=(ED[I]+1) AND 3
  3. NEXT
  4. EDW=FALSE

ED[I]を変えるためだけのFOR〜NEXTなんだけど……

ワンパクくん

やるじゃねェか。コレでバッチリに見えるぜ?

ハカセ

なかなかワルくないぞい。しかし、似たようなFOR〜NEXTを2回ツカうのはカイゼンのヨチありじゃ。

神崎

?

ハカセ

このテイドの長さなら気にならんじゃろうが、FOR〜NEXT文は増えれば増えるほど動作に時間がかかってしまうモノなのじゃ。ミライあるショクンには、これでマンゾクせずにFOR〜NEXTの少ないプログラムをメザしてもらいたいのう。

神崎

ムズカしいんだなあ。

ワンパクくん

そうなるとマスマスどうすりゃイイのかワカらねえじゃねーか!

インテリくん

ここは……もう1つフラグを使うことにしようか。

ED[I]敵1匹ずつ[I]の動きを決めるフラグ
EDW次のターンで敵ぜんぶが下におりるフラグ
MD今のターンで敵1匹ずつ[I]下におりるフラグ

この表のとおり、モンダイの動きをコントロールするための変数MDを使ってみるよ。

ワンパクくん

フラグMDが1匹ずつ動かすのはイイのか……? ああ、1匹ずつと言っても、FOR〜NEXTのターンまるごとMDフラグで動かしてるから、ケッキョク敵ゼンブまとめて動いてるのか……
マジでヤヤコシイな、ついてこれてるのか自分でもワカらねーぜ!

インテリくん

プログラムとしては、こういうことになるね。よく見直してみよう。

  1. ’−−− しんりゃくしゃ
  2. @ALIEN
  3. MD=FALSE
  4. IF EDW THEN MD=EDW:EDW=FALSE
  5. ’−−−
  6. FOR I=0 TO 19
  7.  LOCATE EX[I],EY[I]:PRINT” ”
  8.  IF MD==FALSE THEN @EMV
  9.  ’−−− 
  10.  ED[I]=(ED[I]+1) AND 3
  11.  ’−−−
  12.  @EMV
  13.  GOSUB @EMOVE
  14. NEXT
  15. RETURN

EDWフラグのことはFOR〜NEXTの外でかたづけて、ジッサイにED[I]を変えるのはMDフラグにマカせてあるのさ。

神崎

70行目でEDWフラグのナカミをMDフラグに引きつがせて、EDWフラグじたいは初期化してるんだね。

インテリくん

ココまでのプログラムを全部書くと、こんな感じかな。

+  プログラムリスト
ワンパクくん

ナンドでも言うが、ヤヤコシイぜ!

ハカセ

ひとつずつモンダイをカイケツしていくうちに、いつしかこうなってしまったワケじゃが、だれにでも見やすいプログラムかといえばギモンかもしれん。
全てがアタマに入ったところで、あらためて見やすいプログラムに書きなおすのもダイゴミじゃぞ。今すぐやるべきコトではないかもしれんが……

インテリくん

この講座がゼンブ終わったあとで、みんなやってみてね!

ワンパクくん

マル投げのフンイキがプンプンにおうぜ!

今回のまとめ

配列宣言をいちどにすませる
  1. DIM A[10],B[10],C[10]
DIMの後に,で区切って配列宣言を並べることができます。
FLOOR命令
  1. (変数)=FLOOR(数)
数から小数点以下を切り捨てて整数にします。
  1. FOR I=0 TO 100
  2.  A[I]=FLOOR(I/5)
  3. NEXT
こう書くと、変数A[I]に入る数は、変数が「5の倍数」になるたび1増えます。 A[0]から順に、0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,……と入っていくわけです。
  1. FOR I=0 TO 100
  2.  A[I]=I MOD 5
  3. NEXT
こう書けば、変数A[I]に入る数は1ずつ増えていき、それが「5の倍数」になるたびに戻ります。 A[0]から順に、0,1,2,3,4,0,1,2,3,4,0,1,2,3,4,……と入っていくわけです。

メニュー 【3号】

ヘルプ

リンク

最近の更新

最近の人気ページ

オンライン情報

  • 現在同時に 1 人がこのサイトを見ています
  • このページはこれまでに 2726 回、本日は 1 回、昨日は 0 回閲覧されました

ページの先頭に戻る

表示モード : [ スマホ・3DS対応表示 | クラシック表示 ]
PukiWiki 1.4.7 Copyright © 2001-2006 PukiWiki Developers Team. License is GPL. Based on "PukiWiki" 1.3 by yu-ji
ページの処理時間 : 0.536 秒 | このページの最終更新 : 2022/09/20 (火) 12:48:50 (565d) | ログイン
Copyright(C) 2011-2014 プチコンまとめWiki ◆1sxkymI8ji30