hinekure.net が http://hspdev-wiki.net/ から自動クローリングした結果を表示しています。画像やリソースなどのリンクが切れています。予めご了承ください。
小ワザ/特殊/repeat〜loop構文の拡張 - HSP開発wiki
トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS

小ワザ

 repeat〜loop構文は定型的に変数を要求する場合が多いので、要求されそうな変数をマクロにしてみた。

repeat〜loop構文を拡張してみた一例

拡張用スクリプト

Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
    ;――――――――――――――――――――――――――――――――――――――――
    ;		repeat、break、loopの処理をマクロで少しいじって
    ;		refloop、nowcnt、plurbreakというマクロとim_refloopモジュールを定義
    ;――――――――――――――――――――――――――――――――――――――――
    #cmpopt ppout 1
    #module im_refloop
    #deffunc set_refloop int ii
    refloop = ii
    return
    #defcfunc get_refloop
    return refloop
    #global
    #define global refloop get_refloop()
    #undef repeat
    #undef break
    #undef loop
    #define global nowcnt nowcnt@im_refllop
    #define global repeat(%1=-1,%2=0,%3=nowcnt) \
    : %trepeattotal %i @im_refloop = %1 \
    : breaknest@im_refloop = 0 \
    : repeat@hsp %trepeattotal %p0 @im_refloop, %2 \
    : %3 = cnt \
    : %trepeatcnt %i @im_refloop = cnt
    #define global break(%1=1) \
    : set_refloop %1 \
    : break@hsp
    #define global loop(%1=0) \
    : if breaknest@im_refloop > 0 { breaknest@im_refloop- : break refloop } \
    : set_refloop %1 \
    : loop@hsp \
    : %trepeattotal %o0 \
    : %trepeatcnt %o0
    #define global cnt0 %trepeatcnt %p0 @im_refloop
    #define global cnt1 %trepeatcnt %p1 @im_refloop
    #define global cnt2 %trepeatcnt %p2 @im_refloop
    #define global cnt3 %trepeatcnt %p3 @im_refloop
    #define global plurbreak(%1=1,%2=1) \
    : breaknest@im_refloop = %1-1 \
    : break %2

実用例1

Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
    ;――――――――――――――――――――――――――――――――――――――――
    ;1.二重にrepeat命令を使うので、repeat命令の次行にcnt相当の変数定義
    ;――――――――――――――――――――――――――――――――――――――――
    ;		repeat命令に変数を要求する第3引数を無理矢理定義
    ;		第3引数に定義した変数がループ開始時点でcntと同値になるように設定
    ;		この第3引数のデフォルト変数はnowcnt
    ;		cntと同期させてあるわけではないので、第3引数変数に代入したらcntとずれます
    ;――――――――――――――――――――――――――――――――――――――――
    ;/*
    gsel 0
    repeat 8, , x
        repeat 6, , y
            color x*30+15, y*40+15, 192
            boxf x*40, y*20, x*40+39, y*20+19
            pos x*40, y*20
            color
            mes "("+x+","+y+")"
        loop
    loop
    redraw 1
    ;*/

実用例2

Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 
 
 
 
 
 
 
 
 
 
 
 
-
|
-
|
!
 
    ;――――――――――――――――――――――――――――――――――――――――
    ;2.break命令で脱出した場合と、通常の場合を区別する為にフラグ変数定義
    ;――――――――――――――――――――――――――――――――――――――――
    ;		break命令とloop命令が第1引数を取って返り値を返せるように変更
    ;		返り値はrefloopマクロで取得可能
    ;		引数無定義でもデフォルト値が指定されているので今までの書き方でも問題無し
    ;		デフォルトではbreakは1を、loopなら0を返す、つまりbreak時には
    ;		if refloop : break時の処理    と言う感じで書ける
    ;――――――――――――――――――――――――――――――――――――――――
    ;/*
    repeat rnd(5)+5
        if cnt>5 : break 1
    loop 0
    if refloop = 1 {
        dialog "break命令で抜け出しました"
    } else {
        dialog "普通に抜け出しました"
    }
    ;*/

実用例3

Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
-
|
|
!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
    ;――――――――――――――――――――――――――――――――――――――――
    ;3.上2つのせいでrepeat〜loop構文が絡むユーザー定義命令はローカル変数が多い
    ;――――――――――――――――――――――――――――――――――――――――
    ;		マクロでrepeat命令のcntとは別個にcnt値をスタックする形に変更
    ;		cnt1で現状より一つ浅いスタックのcnt値を取得
    ;		cnt2なら二つ浅いスタック、cnt3なら三つ浅いスタックを取得する
    ;		repeat〜loop構文の内部にはcntのスタックを溜める配列変数があるはずなので、
    ;		そこに直にアクセスできれば、わざわざrepeatとloopをマクロで改造する必要無し
    ;		refloopと合わせて5つあったローカル変数を1つに圧縮できた
    ;――――――――――――――――――――――――――――――――――――――――
    ;/*
    #module
    #defcfunc area_checker array dimen, local k
    repeat length(dimen)
        repeat length2(dimen)
            repeat length3(dimen)
                repeat length4(dimen)
                    if dimen(cnt3,cnt2,cnt1,cnt0) = "ひゃっはー" {
                        k = cnt3, cnt2, cnt1, cnt0
                        break
                    }
                loop
                if refloop : break
            loop
            if refloop : break
        loop
        if refloop : break
    loop
    if refloop : return "ひゃっはーは("+k(0)+","+k(1)+","+k(2)+","+k(3)+")座標に存在します"
    return "ひゃっはーは存在しません"
    #global
    #define l 10
    sdim dimension, 12, l, l, l, l
    dimension(rnd(l),rnd(l),rnd(l),rnd(l)) = "ひゃっはー"
    mes area_checker(dimension)
    ;*/

実用例3別解

Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
-
|
|
!
 
 
 
 
 
 
 
 
 
 
 
 
    ;――――――――――――――――――――――――――――――――――――――――
    ;3.別解
    ;――――――――――――――――――――――――――――――――――――――――
    ;		plurbreakマクロを用いる事でloopネストを複数段階抜け出せるように変更
    ;		第1引数は抜け出すloopネストの数、デフォルト値は1なので普通はbreakと同等
    ;		第2引数はrefloopに渡す返り値、デフォルト値はbreakと同じく1
    ;		マクロ展開してみれば分かる通り、loopにrefloopのif構文を融合させてあるので
    ;		実質の処理はフラグ変数を用いる場合や前述の書き方と同じ
    ;		もう少しいじってplurbreak+return、plurbreak+gotoのような命令もできなくは
    ;		ないものの、その分全てのloopにif処理が掛かるので今回は作らず
    ;		フラグ変数を使う方法より5行少なく書ける
    ;――――――――――――――――――――――――――――――――――――――――
    ;/*
    #module
    #defcfunc area_checker2 array dimen, local k
    repeat length4(dimen)
        repeat length3(dimen)
            repeat length2(dimen)
                repeat length(dimen)
                    if dimen(cnt0, cnt1, cnt2, cnt3) = "ひゃっはー" {
                        k = cnt0, cnt1, cnt2, cnt
                        plurbreak 4
                    }
                loop
            loop
        loop
    loop
    if refloop : return "ひゃっはーは("+k(0)+","+k(1)+","+k(2)+","+k(3)+")座標に存在します"
    return "ひゃっはーは存在しません"
    #global
    #define ll 10
    sdim dimension, 12, ll, ll, ll, ll
    dimension(rnd(ll),rnd(ll),rnd(ll),rnd(ll)) = "ひゃっはー"
    mes area_checker2(dimension)
    ;*/

拡張後の各命令、マクロの解説

既存の命令の拡張

repeat p1,p2,p3
p1=1〜(-1) : ループ回数
p2=0〜(0) : システム変数cntのスタート値
p3=(nowcnt) : cntに対応させる変数

 repeat命令には新たに第3引数を定義しました。第3引数に当てられた変数は、そのrepeat〜loop構文中のcntと同じ値を返します。
 これによって、二重にrepeat命令を使い、各repeat〜loop構文中のcntを参照したい際に、代入用の変数を定義する手間が省けます。
 第3引数を省略した場合、nowcntがcntと同じ値を返します。
 この第3引数は、あくまでrepeat命令直後のcnt用変数定義を省略する為の物です。厳密にcntと第3引数が同期しているわけではないので、第3引数に値を代入したりすれば、cntと値がずれてしまいます。

break p1
p1=(1) : break時にrefloopに渡す返り値

 breakには新規に引数を定義しました。この第1引数に書かれた値を、ループから抜ける際に、新規定義マクロrefloopへと渡します。
 break命令で抜ける事無く、規定の回数分の処理を終えてrepeat〜loop構文から抜けた場合、基本的に0が返ります。(loopの第1引数によりますが)ですので、refloopの値によって、break命令を通ったか通っていないかを判別できます。
 その他には第1引数にcntを与える事により、抜け出す原因となったcnt値を返す事ができます。これは、配列変数全体からある条件を満たす配列番号を呼び出す際に利用できます。

loop p1
p1=(0) : 普通にループを終えた時にrefloopに渡す返り値

 break命令の新規第1引数と同じく、refloopに第1引数を渡します。loop命令では、break命令を使用する事無くループを終了した際にその引数を返します。
 デフォルト値は0です。

新規定義マクロ

refloop

 break命令やloop命令で返される値の保管先です。
 refloopには整数値しか与えられません。また、システム変数に近いマクロなのでbreak命令やloop命令以外で直に値を代入する事はできません。

nowcnt

 repeat命令で第3引数を定義しない際に勝手にcntの値のコピー先となる変数です。利用価値はありません。

plurbreak

plurbreak p1,p2
p1=1〜(1) : 抜け出すループネストの数
p2=(1) : plurbreak時にrefloopに渡す返り値

 break命令の拡張版です。第1引数の値分ループネストを抜け出します。
 第1引数のデフォルト値は1ですので、省略した場合break命令と同じ挙動になります。
 第2引数はbreak命令の第1引数と同じくrefloopに渡す値を定義します。

cnt0〜cnt3

cnt0、cnt1、cnt2、cnt3

 cnt0はcntと同値です。
 cnt1は現状より1つ浅いループのcnt値を返します。cnt2なら2つ浅いcnt値、cnt3なら3つ浅いcnt値を返します。
 このマクロを利用する事で浅いループのcnt値をわざわざ別変数に保管せずとも取得する事ができるようになります。


URL B I U SIZE Black Maroon Green Olive Navy Purple Teal Gray Silver Red Lime Yellow Blue Fuchsia Aqua White

トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS
Last-modified: 2011-04-21 (木) 22:00:05 (961d)