RPGツクールと数学のブログ

RPGツクールと数学についてのブログです。

相互変換モジュール ハノイの塔を作る

過去ブログの転載です。

イベント命令の簡略化についてやってみます。ハノイの塔を作ってみましょう。ハノイの塔ってなんだって?? ごめんなさい割愛します。パズルですよ。ウィキペディアをお読み下さい。

いわゆる古典的なパズルですが、RPGツクールでさあ作ろうと思ってもどこから手を付けていいかなかなか分かりづらいものです。

そこで、どのように作ろうか、大まかな手順をまず考えます。

① 枚数を決める
② 準備する
③ ハノイの塔を画面に表示する
④ クリアしていたら、終了する
⑤ クリアしていなかったら、板を移動して、③に戻る

↑こういった感じになるでしょうね。どうしても、思い付きでイベント命令を組み始めると複雑化しやすいので、わけがわからなくなって挫折してしまう危険があるのです。ここではこうやってまず纏めておき、相互変換モジュールを使って簡潔にシステムを書くことを目指しましょう。

画像素材はここにあります↓

hanoi_sozai.zip - Google ドライブ

プログラム本体は、次のようになります。

ハノイの塔.hsp

#include "ハノイの塔.as"

質問 // 枚数をプレイヤーに入力してもらう
初期化 // 変数の初期化
cy
    表示 // 板を表示
    終了判定 // 残り回数が0になったら終了
    移動 // 板を移動させる
cyend

send

 ↑ cy ~ cyend は繰り返しの処理です。上で書いた手順そのものではありませんか。そうです、そのものです。こうやって、個々の処理をまとめていくことにより、簡潔にシステムを記述することができ、なおかつバグが発生したときにどの命令が原因なのかというのを把握しやすくなります。

個々の命令がどうなっているかというと、こうなっています。

ハノイの塔.as』

#include "rpgfunc.as"

goto *@f

#deffunc 質問
    msg "枚数は?(1~13)"
    number 2, 1
    co 1, 1, 0, 0, 0
        msg "それはダメだよ……"
        hangup
    coend
    co 1, 1, 0, 14, 1
        msg "それはダメだよ……"
        hangup
    coend
return

#deffunc 初期化
    varsel 2 : var 0, 0, 1, 0
    varsel 3 : var 0, 1, 1, 0
    varsel 3 : var 1, 0, 20, 0
    cy
        varsel 2 : var 3, 0, 2, 0
        varsel_var 3 : var 0, 0, 0, 0
        varsel 3 : var 2, 0, 1, 0
        co 1, 3, 0, 20, 0
            varsel 2 : var 2, 0, 1, 0
            cybreak
        coend
    cyend
    pic 1, "土台", , , , , , 1
return

#deffunc 表示
    varsel 4, 6 : var 0, 0, 205, 0
    varsel 3 : var 0, 1, 1, 0
    varsel 3 : var 1, 0, 20, 0
    cy
        varsel 7 : var 0, 2, 3, 0
        varsel 7 : var 3, 0, 105, 0
        varsel 7 : var 1, 0, 55, 0
        varsel 8 : var 0, 2, 3, 0
        varsel 8 : var 1, 0, 4, 0
        varsel_var 8 : var 2, 0, 10, 0
        varsel 8 : var 0, 2, 8, 0
        repeat 13, 1
            co 1, 3, 0, 20 + cnt, 0
                pic cnt + 1, "板" + cnt, 1, 7, 8
            coend
        loop
        varsel 3 : var 2, 0, 1, 0
        co 1, 3, 0, 20, 0
            cybreak
        coend
    cyend
    pause 3
return

#deffunc 終了判定
    co 1, 2, 0, 0, 0
        msgop 1, 0, 0, 1
        msg "【終了】"
        msgop 0, 2, 0, 1
        repeat 14, 1
            picdel cnt
        loop
        hangup
    coend
    varsel 2 : var 2, 0, 1, 0
return

#deffunc 移動
    varsel 7 : var 0, 1, 2, 0
    varsel 7 : var 5, 0, 2, 0
    co 1, 7, 0, 0, 0
        rem "【回数が奇数の場合】"
        varsel 21 : var 1, 0, 1, 0
        varsel 21 : var 5, 0, 3, 0
    coelse
        rem "【回数が偶数の場合】"
        varsel 3 : var 0, 0, 21, 0
        varsel 7 : var 0, 0, -1, 0
        cy
            varsel 8 : var 0, 2, 3, 0
            co 1, 7, 1, 8, 5
                co 1, 7, 0, -1, 0
                    varsel 7 : var 0, 1, 8, 0
                coelse
                    varsel_var 3 : var 0, 1, 7, 0
                    varsel_var 3 : var 1, 1, 8, 0
                    varsel_var 3 : var 2, 0, 3, 0
                    varsel_var 3 : var 3, 0, -1, 0
                    cybreak
                coend
            coend
            varsel 3 : var 1, 0, 1, 0
        cyend
    coend
return

*@

#deffuncから始まるブロックごとに処理を書いています。こうすると一つ一つは小さく纏められるので、考えやすくもなるはずです。

拡張子「.as」にするとこれはヘッダファイルと呼ばれるものになります。『ハノイの塔.as』というのは、『ハノイの塔.hsp』のヘッダファイルです。分かりやすいように、同名にして拡張子だけ変えています。「.as」の方に個々の命令をそれぞれ格納しておき、本体を「.hsp」の方だけに書けば、非常に簡潔にまとまって見やすいものになると思います。おかしなことが起こったら、デバッグの際にメッセージか何かを本体の方に入れればどの命令がおかしいのか確認できますねぇ。

「.as」を取り込む命令が、「#include」になります。「.hsp」の先頭に書いてありますね。その名の通り、ソースファイルを「含む」のです。「.as」のソースすべてを「#include "ハノイの塔.as"」の一行で済ますわけですね。

「.hsp」の方を簡潔にするために、「.as」の先頭に「#include "rpgfunc.as"」と書いてあります。もちろん、「.hsp」の方で書いても構いません。

このことからお分かり頂けますでしょうが、「rpgfunc.as」もまたヘッダファイルです。これをインクルードすることによって、「msg」とか「send」とかが使えるようになるわけです。

「goto *@f」は、次の「*@」がある行まで飛ぶ、という命令です。
「goto *@f」から「*@」の間に、個々の命令の内容を記述していきます。
命令を作るには、「#deffunc 命令名」から「return」までの間に内容を記述します。命令名には日本語が使えます。上の例でも使っていますが……命令名には引用符は付けません。

命令の内容はツクールの方で作成し、それを相互変換を用いてHSPにして「.as」に格納していく、といったことをすると良いでしょう。動作確認をするときは「.hsp」の方で実行してすべての命令をクリップボードにコピーし、ツクールに貼り付けることにします。修正する場合はHSPの方を手直しし(時々相互変換しながら)、再度動作確認をするときはツクールに前回貼り付けた分をすべて削除して、新しく貼り付ければそれで済みます。

ハノイの塔の個々の命令で何をやっているのかは割愛しています……単に、ハノイの塔をやっているだけです^^;「.hsp」を開いてF5を押してツクールに貼り付ければ、ちゃんと動作するはずです。

次の変数を使用しています。

変数 1番:枚数
変数 2番:残り回数
変数 3番:枚数一時
変数 4番:柱1 y座標
変数 5番:柱2 y座標
変数 6番:柱3 y座標
変数 7番:一時1
変数 8番:一時2
変数21番:位置(1枚目)
変数22番:位置(2枚目)
変数23番:位置(3枚目)
変数24番:位置(4枚目)
変数25番:位置(5枚目)
変数26番:位置(6枚目)
変数27番:位置(7枚目)
変数28番:位置(8枚目)
変数29番:位置(9枚目)
変数30番:位置(10枚目)
変数31番:位置(11枚目)
変数32番:位置(12枚目)
変数33番:位置(13枚目)

このように命令を簡略化することにより、個々の命令そのものはどのようにして動いているのか知らなくても、「.hsp」だけを見れば大体こういう風に動いているのかと分かるというメリットもあります。

だんだんオブジェクト指向な感じになってきましたねええ。