見出し画像

【IchigoJam】画面をランダムな順番でイチゴで埋め尽くす【アドベントカレンダー供養】

先日、アドベントカレンダーが開催された。
そこへの投稿を目指してプログラムを書いてみたが、あまりうまくいかなかったとしてボツにしたネタがある。
今回は、このネタを紹介して供養する。

企画

IchigoJam BASIC で、画面を (標準搭載されている) イチゴの絵文字で埋め尽くす。

画面をイチゴで埋め尽くす12の方法 / IchigoJamではじめるArmマシン語その11
では順番にイチゴを書き込んでいくが、今回はランダムな順番で書き込んでいく。

※IchigoJamはjig.jpの登録商標です。

シンプルな方法

まず、画面のサイズを取得する。
画面上の点をランダムに選び、そこにイチゴが無ければイチゴを置いて残りの数をデクリメントする。
残りの数がゼロになったら終了する。

10 ' イチゴ デ ウメル (シンプル)
20 IF VER()>=13224 W=POS(3):H=POS(4) ELSE W=32:H=24
30 CLT:CLS:N=W*H:L=N
40 S=RND(N):IFPEEK(#900+S)=0POKE#900+S,#FF:L=L-1
50 IFL>0GOTO40
60 T=TICK():LOCATE0,-1:?"COMPLETE! TIME=";T
70 GOTO70

IchigoKamuy (IchigoJam BASIC 1.4.1) で実行を行った結果、画面が埋まりきるまでの時間 (TICK() 単位) の平均は

(1384+1568+1277+1230+1002)/5 = 1292.2

となった。

高速化を狙った方法

シンプルな方法では、特に画面が埋まっていくほど、既にイチゴがある点が選ばれ、無駄になる時間が多くなり、埋まりにくくなっていくと考えられる。
そこで、画面上の点を事前にリストにし、その中から選んでいくことで、既にイチゴがある点は選ばないようにすることで、高速化できるのではないかと考えた。

しかし、IchigoJam の画面は最大で 32×24 = 768 点あり、それぞれの点を識別するのには少なくとも 10 ビット必要である。
そのため、IchigoJam のキャラクターパターン領域と配列・変数領域を合わせた 512 バイト (4,096 ビット) では、画面上の点全ての情報を格納するのには足りない。
そこで、画面上のイチゴが少ない序盤は全体からランダムに選び、残りの空きマスがメモリ上に収まる程度の数になったらそれらの位置をメモリに格納してその中から選ぶようにすることにした。

とはいえ、残りの空きマスが少なくなったタイミングで画面全体を走査して空きマスの位置をメモリに格納しようとすると、処理速度の遅い IchigoJam では処理中画面上のイチゴが増えなくなるのが目立ってしまう。
これを防ぐため、イチゴを置いていくのと並行で、少しずつ空きマスの位置の調査をしていくことにした。
この方法では、空きマスかどうかのチェックをした後、ランダム選択によりそこにイチゴが置かれると、リストにはあってもそこが空きマスではなくなってしまう。
これについては妥協し、リストから選んだ場合でも空きマスかどうかのチェックを行うようにした。
それでも、リストを使うと同じマスを1回しか選ばずにすむため、何も考えずランダムに選ぶよりは無駄が省けると考えられる。

10 ' イチゴ デ ウメル
20 IF VER()>=13224 W=POS(3):H=POS(4) ELSE W=32:H=24
30 CLT:CLS:N=W*H:L=N:C=0:F=0:CLP:FORI=0TO7:POKE#700+I,PEEK(#7F8+I):NEXT
40 IFC=NP=#708+RND(F)*2:S=PEEK(P)+PEEK(P+1)<<8:F=F-1:G=#708+F*2:POKEP,PEEK(G),PEEK(G+1)ELSES=RND(N)
50 IFPEEK(#900+S)=0POKE#900+S,#E0:L=L-1
60 IFC=NORL>225GOTO90
70 FORI=0TO9:IFC<ND=C:C=C+1:IFPEEK(#900+D)=0POKE#708+F*2,D,D>>8:F=F+1
80 NEXT
90 IFL>0GOTO40
100 T=TICK():LOCATE0,-1:?"COMPLETE! TIME=";T
110 GOTO110

キャラクターパターンおよび配列の領域を、処理対象マスのリストとして用いる。
その際、イチゴのキャラクターパターンがキャラクターパターン領域の最後にあるため、領域の最初にコピーして残りの領域を使いやすくする。

主に以下の変数を用いて処理を行う。

  • N:画面全体のマス数

  • L:現在画面に残っている空きマス数

  • C:次に空きマスかどうかの調査を行うマスの位置

  • F:現在処理対象マスのリストにあるマスの数

40行目で、次にイチゴを置こうとするマスを選択する。画面の最後まで調査が完了していればリストから選択し、そうでなければ画面全体からランダムに選択する。
50行目で、選択したマスにイチゴを置こうとする。
60行目で、空きマスかどうかの調査を行うべき (まだ調査が完了していない、かつ空きマスが十分減っている) かの判定を行う。
70~80行目で、空きマスかどうかの調査を行う。

IchigoKamuy (IchigoJam BASIC 1.4.1) で実行を行った結果、画面が埋まりきるまでの時間 (TICK() 単位) の平均は

(1293+1265+1298+1315+1251)/5 = 1284.4

となった。
「シンプルな方法」と比べ、少しだけ短くなっているが、ほとんど変わっていない。

結論

今回試した工夫では、画面をイチゴで埋めきるまでの処理時間を削減する効果はあまりみられなかった。
しかし、結果をよく見ると、処理時間のばらつきは減っていることがわかる。(標準偏差が、「シンプルな方法」では約 186、「高速化を狙った方法」では約 23)
処理時間の平均はあまり変わらず、ばらつきが減っているということは、改善はできているといえるだろう。
それをよく確かめず、「あまりうまくいかなかった」とみなしたのは、早計だったと考えられる。
さらに、うまくいかなかったとしても、「うまくいかなかった」と報告すればよく、ボツにするのも早計だったと考えられる。

いいなと思ったら応援しよう!