HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2025
1024
Y_repeatrepeat中にreturn19解決


Y_repeat

リンク

2025/10/24(Fri) 20:10:02|NO.104119

プログラミングがそろそろ完成の時にバグがあり
結局repeat中にreturnしてました😭

repeat中のreturnは後から顔を出すバグなので
エラー扱いにしちゃっていいんじゃないすかね
それか警告扱いに😅



この記事に返信する


リンク

2025/10/24(Fri) 23:12:43|NO.104122

え、これだめなんですか?
特に気にしてなかったので普通にやってるかも。
GOSUBとかGOTOとか飛ぶの全部禁止だったりしますか?
後、FORの仕様も気になるところ…。



雪月夜

リンク

2025/10/25(Sat) 10:09:06|NO.104127

検証したところrepeatはどちらも駄目みたいですね
forなら大丈夫そうです
mes""+looplev
gosub *methodrepeatgosub mes""+looplev gosub *methodforgosub mes""+looplev goto *methodrepeatgoto *methodrepeatgotores mes""+looplev goto *methodforgoto *methodforgotores mes""+looplev stop *methodrepeatgosub repeat return loop return *methodforgosub for x,0,10,1 return next return *methodrepeatgoto repeat goto *methodrepeatgotores loop stop *methodforgoto for x,0,10,1 goto *methodforgotores next stop



リンク

2025/10/25(Sat) 14:09:48|NO.104133

検証お疲れ様です。
つまりあれですか、rpeatだと途中で飛ぶと、
ネストレベルがそのまま次に引き継がれる仕様って事ですか?
それは知らないと大変ですね。
どこかに明記してありましたっけ?



Y_repeat

リンク

2025/10/25(Sat) 15:26:15|NO.104134

結構有名な仕様っすね
わかっているのにやってしまってました😅

やり場のないイライラで
全くもって恥ずかしいです😅



zakki

リンク

2025/10/25(Sat) 15:45:19|NO.104135

禁止というかスタックが溜まるので、スタック溢れて落ちたり他言語知ってると直観的じゃない挙動になったりします。

HSPだとdeffuncっていう関数のエントリーポイントの行があるだけで、次の行はただの文で
コンパイラ的にreturnがループ内か静的に調べるのは微妙に面倒くさいか誤判定ありそうな気がします。

if文みたいにに、repeat 10 {} loop や defun foo {} 方式を強制にしたり、
構造化BASICみたいにdeffunc foo ... end deffunc、sub foo ... end sub方式にしたりすると、
素直ですが別物になっちゃいますね。

gotoやlooplevで変則挙動させてるプログラムやHSPROUTINEを触ってるプラグインには泣いてもらうことにすれば、
cmdfunc_gosub/code_callfuncでlooplevを保存して、cmdfunc_returnで巻き戻すのでスタック溢れないみたいな対応は
割と簡単そうな気がします。


goto *main *label1 repeat 10 mes "B " + looplev + " " + cnt if cnt == 3: return loop goto *main repeat *main pos 0, 0 mes "A1 " + looplev wait 10 gosub *label1 mes "A2 " + looplev if looplev > 0: loop



Y_repeat

リンク

2025/10/25(Sat) 17:13:54|NO.104137

何年か前だと思うんすけど
onitamaさんも対応するとおっしゃってた気がしますし
少し文法変わるなら HSP4で対応するのでしょうか



Ve

リンク

2025/10/25(Sat) 22:11:25|NO.104138

repeat〜loopは流れを頭に入れてないとエラーに陥りやすいので、gotoでループさせる手あります。

アニメや計算式とかちょっと呼び出したいループはgotoで、参照ぐらいならgosubでラベルを作って、
複雑になるほどrepeatよりはgoto等でラベルに飛ばした方がエラーが少ないと思います。



Y_repeat

リンク

2025/10/26(Sun) 01:03:19|NO.104139

返信ありがとうございます

参照してるスクリプトがc++なんで影響あるっぽいすね
repeat loopは短いブロックで使っちゃうんですがforより引数少ないので使ってしまいます
複雑なブロックはgoto 使った方が便利と



窓月らら

リンク

2025/10/26(Sun) 20:48:10|NO.104143

なのでー・・・
メインループはgotoをおすすめします。

*main
〜処理〜
goto *main

for〜nextはマクロ内でgotoなので問題ありません。



tkzn

リンク

2025/10/27(Mon) 00:36:49|NO.104147

>>zakkiさん
なかなかそのコードはトリッキーですね。🤣

HSPでは対応するペアがなく単独でrepeatやloopがあると中間コードへコンパイルするときにエラーとなるので、

repeat〜loopというペアで使われることが大前提とされているようですね。

ただ、コンパイルさえ済んでしまえば、実行時にはペアなんて知ったこっちゃなく、
repeat文とloop文はスタックを操作していきますが。。。



tkzn

リンク

2025/10/27(Mon) 00:40:51|NO.104148

私は、次のようなマクロを組んでrepeat〜loop、foreach〜loopをスタックを使わないgoto,ifのコードに書き換えて、
repeatやforeachの中でreturnとかgotoをできるようにしています。
もともとのrepeatやforeachと実用上はほぼ同じ動きをしますよ。
looplevは使えないので、looplevで挙動を変えるような特殊なプログラムには対応できないです。


#undef repeat #define repeat(%1=-1,%2=0) %t__loop_cnt%i=(%2):%t__loop_start*%i:if((%1)>=0){if(%t__loop_cnt%p>=(%1)){goto %t__loop_end*%i}} #undef foreach #define foreach(%1) %t__loop_cnt%i=0:%t__loop_start*%i:if(%t__loop_cnt%p>=length(%1)){goto %t__loop_end*%i} #undef loop #define loop %t__loop_level%o0:%t__loop_cnt%o++:goto %t__loop_start*%o:%t__loop_end*%o #undef cnt #define cnt (%t__loop_cnt%p) #undef break #define break goto %t__loop_end*%p #undef continue #define continue %t__loop_cnt%p++:goto %t__loop_start*%p #undef looplev #define looplev (0) /* スタックを消費しないためネストレベルは上がらない */ mes "repeatのテスト" repeat 3 mes cnt loop mes "" mes "repeat+breakのテスト" repeat 3 mes cnt if(cnt>=1) { mes "break!" break } loop mes "" mes "repeat+continueのテスト" repeat 3 mes cnt if(cnt=1) { mes "continue!" continue } loop mes "" mes "foreachのテスト" dim a,5 foreach a mes "#"+cnt+" : "+a.cnt loop



hkr

リンク

2025/10/27(Mon) 17:58:14|NO.104154

難しいこと考えずにフラグ立てて一旦breakして、
repeat抜けてからフラグを参考にreturnするのが良いのではないかという
1ラベル複数retuanが気持ち悪い1ラベル1returnおじさんからのご提案ですw



Y_repeat

リンク

2025/10/27(Mon) 20:01:32|NO.104157

デバッグとしましては
repeat loopをfor nextに書き換えて
エラー治りました
簡単にエラー出せそうに思ったんすけど
違うみたいっすね😅



Y_repeat

リンク

2025/10/27(Mon) 20:05:21|NO.104158

完成直前にエラー出て
大きな欠陥があったようでショック受けたんすけど
翌日にエラー箇所付近をそうしたら治ったかんじっす
皆様、返信ありがとうございました



Ve

リンク

2025/10/27(Mon) 21:01:14|NO.104160


;━━━━━━━━━━━━━━━━━━━━ ; PC、NPC、オブジェなど ;━━━━━━━━━━━━━━━━━━━━ *キャラとイベント ;-------移動処理------- if movecnt(0)=0{ if key&15 { //縦横移動 repeat 1 // 左:1, 上:2, 右:4, 下:8 if key&1:movex(0)=-1:cd(0)=0:pd=0:break if key&2:movey(0)=-1:cd(0)=1:pd=1:break if key&4:movex(0)=1:cd(0)=2:pd=2:break if key&8:movey(0)=1:cd(0)=3:pd=3:break loop }else{ if dash=1 : dash=0 } ;プレイヤーの1歩先を調べる為の変数 if pd=0:ttx=-1:tty=0 if pd=1:ttx=0:tty=-1 if pd=2:ttx=1:tty=0 if pd=3:ttx=0:tty=1 } ;全イベント移動と当たり判定 repeat evntmax ;PCは除外 if cnt>=pt{ ;ここから--------------------------------------- ;移動中ならチェックからはずす if (movecnt(cnt)=0){ ;動くNPC if (ct(cnt)=1){ ;ランダム歩行 if 0=rnd(100){ tmp=rnd(4) if tmp=0:movex(cnt)=-1:cd(cnt)=0 if tmp=1:movey(cnt)=-1:cd(cnt)=1 if tmp=2:movex(cnt)=1:cd(cnt)=2 if tmp=3:movey(cnt)=1:cd(cnt)=3 }else{ ;話かけた時 if (xkey=1)and(px+ttx=cx(cnt))and(py+tty=cy(cnt)){ logmes "イベント起動"+(cnt-pt) evntnumline=(cnt-pt) ;イベントの向き変更 if cx(cnt)=px{ ;上下の判定 if tty=-1{ cd(cnt)=3 }else{ cd(cnt)=1 } }else{ ;左右の判定 if ttx=-1{ cd(cnt)=2 }else{ cd(cnt)=0 } } ;イベント開始 evnttype=1 ;イベントページ番号 if cnt=1{ evntline=evntnum(evntnow(cnt-pt))+3 }else{ evntline=0 repeat cnt-pt evntline+=evntpage(cnt) loop logmes ""+evntline evntline=evntnum(evntline+evntnow(cnt-pt))+3 } } } } ;動かないNPC if (ct(cnt)=2){ ;話かけた時 if (xkey=1)and(px+ttx=cx(cnt))and(py+tty=cy(cnt)){ logmes "イベント起動"+(cnt-pt) evntnumline=(cnt-pt) ;イベントの向き変更 if cx(cnt)=px{ ;上下の判定 if tty=-1{ cd(cnt)=3 }else{ cd(cnt)=1 } }else{ ;左右の判定 if ttx=-1{ cd(cnt)=2 }else{ cd(cnt)=0 } } ;イベント開始 evnttype=1 ;イベントページ番号 if cnt=1{ evntline=evntnum(evntnow(cnt-pt))+3 }else{ evntline=0 repeat cnt-pt evntline+=evntpage(cnt) loop evntline=evntnum(evntline+evntnow(cnt-pt))+3 } } } };if (movecnt(cnt)=0) ;重なると発動するイベント if (ct(cnt)=3){ ;キャラとの当たり判定 if (cx(cnt)=px)and(cy(cnt)=py)and(movestop=0){ logmes "イベント起動"+(cnt-pt) evntnumline=(cnt-pt) ;起動中のイベントID保存 evnt_id=cnt ;重なりの2重起動禁止 movestop=1 ;イベント開始 evnttype=1 ;イベントページ番号 if cnt=1{ evntline=evntnum(evntnow(cnt-pt))+3 }else{ evntline=0 repeat cnt-pt evntline+=evntpage(cnt) loop evntline=evntnum(evntline+evntnow(cnt-pt))+3 } } } ;オブジェクト if (ct(cnt)=4){ ;X押した時 if (xkey=1)and(px+ttx=cx(cnt))and(py+tty=cy(cnt)){ logmes "イベント起動"+(cnt-pt)+":"+(evntnow(cnt-pt)) evntnumline=(cnt-pt) ;起動中のイベントID保存 evnt_id=cnt ;イベント開始 evnttype=1 ;イベントページ番号 if cnt=1{ evntline=evntnum(evntnow(cnt-pt))+3 }else{ evntline=0 repeat cnt-pt evntline+=evntpage(cnt) logmes ""+evntpage(cnt) loop evntline=evntnum(evntline+evntnow(cnt-pt))+3 } logmes ""+evntline } } ;向きを上で設定=プレイヤーが上向きから・調べるのみで反応するオブジェクト if (ct(cnt)=6){ ;X押した時 if (cd(cnt)=pd)and(xkey=1)and(px+ttx=cx(cnt))and(py+tty=cy(cnt)){ logmes "イベント起動"+(cnt-pt)+":"+(evntnow(cnt-pt)) evntnumline=(cnt-pt) ;起動中のイベントID保存 evnt_id=cnt ;イベント開始 evnttype=1 ;イベントページ番号 if cnt=1{ evntline=evntnum(evntnow(cnt-pt))+3 }else{ evntline=0 repeat cnt-pt evntline+=evntpage(cnt) logmes ""+evntpage(cnt) loop evntline=evntnum(evntline+evntnow(cnt-pt))+3 } logmes ""+evntline } } };ここまでNPC--------------------------------------- ;★プレイヤーの移動&NPCとオブジェクト画像、通過NPC if (ct(cnt)=1)or(ct(cnt)=2)or(ct(cnt)=5) { //キャラのマップ端の当たり判定 if cx(cnt)+movex(cnt)<=-1 :movex(cnt)=0 if cy(cnt)+movey(cnt)<=-1 :movey(cnt)=0 if cx(cnt)+movex(cnt)>((size_x-1)*CHIP)+1 : movex(cnt)=0 if cy(cnt)+movey(cnt)>((size_y-1)*CHIP)+1 : movey(cnt)=0 ;マップとの当たり判定 gsel 4 pget (cx(cnt)+movex(cnt))*CHIP,(cy(cnt)+movey(cnt))*CHIP if (debug_hit=0)and(ginfo(16)=0){ movex(cnt)=0 movey(cnt)=0 } ;自分以外の他のキャラとの当たり判定 ;tmp=自分のID tmp=cnt repeat evntmax ;後ろの仲間は通り抜けできるようにする if (tmp<PT) : if ct(chr_t(tmp))=5 : break if (tmp=cnt) : continue ;当たり判定のあるイベントタイプの場合進めない ;画像がある時の処理 ;if (cg(cnt)!=0){ ;床イベントと画像ナシ以外はぶつかる ;後ろの仲間は通り抜けできるようにする if cnt<PT { if (ct(chr_t(cnt))!=5){ if (cg(chr_t(cnt))!=0) :if ((cx(tmp)+movex(tmp))=(cx(chr_t(cnt))+movex(chr_t(cnt))))and((cy(tmp)+movey(tmp))=(cy(chr_t(cnt))+movey(chr_t(cnt)))):movex(tmp)=0:movey(tmp)=0 } }else{ if (ct(cnt)!=0)and(ct(cnt)!=5)and((ct(cnt)!=3)) { if (cg(cnt)!=0) :if ((cx(tmp)+movex(tmp))=(cx(cnt)+movex(cnt)))and((cy(tmp)+movey(tmp))=(cy(cnt)+movey(cnt))):movex(tmp)=0:movey(tmp)=0 } } loop if movecnt(cnt)=0{ if (movex(cnt)!=0)or(movey(cnt)!=0) { movecnt(cnt)=16 if cnt=0 { ;リザルト用 walk_res++ walk_res=limit(walk_res,0,2000000001) } if cnt=0 { repeat pt-1,1 movex(cnt)=tmovex(cnt) movey(cnt)=tmovey(cnt) cd(cnt)=tcd(cnt) movecnt(cnt)=16 loop } } } if movecnt(cnt)>0{ ;walk_mode ;0=Normal ;1=Dash ;2=Maniac if walk_mode<2 { if cnt<pt{ if dash=1 { // 左:1, 上:2, 右:4, 下:8 if movex(cnt)=-1:tx(cnt)-=2 if movey(cnt)=-1:ty(cnt)-=2 if movex(cnt)=1:tx(cnt)+=2 if movey(cnt)=1:ty(cnt)+=2 movecnt(cnt)-=2 }else{ // 左:1, 上:2, 右:4, 下:8 if movex(cnt)=-1:tx(cnt)-=1 if movey(cnt)=-1:ty(cnt)-=1 if movex(cnt)=1:tx(cnt)+=1 if movey(cnt)=1:ty(cnt)+=1 movecnt(cnt)-=1 } }else{ // 左:1, 上:2, 右:4, 下:8 if movex(cnt)=-1:tx(cnt)-=1 if movey(cnt)=-1:ty(cnt)-=1 if movex(cnt)=1:tx(cnt)+=1 if movey(cnt)=1:ty(cnt)+=1 movecnt(cnt)-=1 } }else{ if cnt<pt{ if dash=1 { // 左:1, 上:2, 右:4, 下:8 if movex(cnt)=-16:tx(cnt)-=2 if movey(cnt)=-16:ty(cnt)-=2 if movex(cnt)=16:tx(cnt)+=2 if movey(cnt)=16:ty(cnt)+=2 movecnt(cnt)-=2 }else{ // 左:1, 上:2, 右:4, 下:8 if movex(cnt)=-16:tx(cnt)-=1 if movey(cnt)=-16:ty(cnt)-=1 if movex(cnt)=16:tx(cnt)+=1 if movey(cnt)=16:ty(cnt)+=1 movecnt(cnt)-=1 } }else{ // 左:1, 上:2, 右:4, 下:8 if movex(cnt)=-16:tx(cnt)-=1 if movey(cnt)=-16:ty(cnt)-=1 if movex(cnt)=16:tx(cnt)+=1 if movey(cnt)=16:ty(cnt)+=1 movecnt(cnt)-=1 } } if (movecnt(cnt)<=0)and(cmove(cnt)=0){ if cnt<pt { ;仲間移動 tmovex(cnt+1)=movex(cnt) tmovey(cnt+1)=movey(cnt) tcd(cnt+1)=cd(cnt) } if cnt=0{ px+=movex(cnt) py+=movey(cnt) if movestop=1:movestop=0 ;エネミー遭遇 if mapenmmax!=0{ logmes encount if (encount<=30+(encset*10))and(debug_encount=0) { if encount>0 { if (rnd(encount)=0) : enmmax=99 }else{ enmmax=99 } } if encount>1 { repeat pt if efc_drop(cnt)=0 : continue encount-=efc_drop(cnt) loop encount-- encount=limit(encount,0,199) } } ;毒 repeat pt raster_mode=0 if (sta(cnt,0)=2)or(sta(cnt,1)=0) : continue ;毒 ラスタースクロール raster_mode=1 dcnt++ : break loop } if cnt=pt-1 : if dash=1 : dash=0 cx(cnt)+=movex(cnt) cy(cnt)+=movey(cnt) movex(cnt)=0 movey(cnt)=0 tx(cnt)=0 ty(cnt)=0 movecnt(cnt)=0 } } ;イベント用自動歩行 if (cmove(cnt)!=0){ ;logmes "自動歩行 ID( "+cnt+" ) 歩行数:"+cmove(cnt)+" 移動カウント:"+movecnt(cnt) ;"←\n↑\n→\n↓ if cd(cnt)=0:movex(cnt)=-1:tx(cnt)-=1 if cd(cnt)=1:movey(cnt)=-1:ty(cnt)-=1 if cd(cnt)=2:movex(cnt)=1:tx(cnt)+=1 if cd(cnt)=3:movey(cnt)=1:ty(cnt)+=1 ;距離カウント cmove(cnt)-- ;移動カウント movecnt(cnt)-=1 } } loop return

repeatも使いようなのかなぁ



きせん

リンク

2025/10/28(Tue) 09:49:56|NO.104162

口出ししようか迷いましたが、
そのrepeatの使い方をするのであれば、
ラベルからgotoで戻るやり方を、count等で回数を覚え
抜け出る方法の方が間違いにくいと思います。

repeatのcntも、一度cntaなどに入れないと、
どのcntかもわかりにくい気がしますので
間違いや誤動作が起こりやすい気がします。

参考にならないかもしれません。
失礼しました。



Ve

リンク

2025/10/28(Tue) 17:56:51|NO.104171

goto も万能ではないのでねぇ
ラベルばかり作るとF11で検索しづらいし
察しの良い方は分かるだろうけど、最後にreturnを入れてる



きせん

リンク

2025/10/28(Tue) 22:06:58|NO.104172

万能ではありませんが、
少なくともrepeatとloopでのエラーは起きません。
ラベルばかりつくるとは言っていません。
この記述では最後にreturnを入れる意味がありません。

そもそも、repeat evntmaxのcntを変数に格納せずに
新たにrepeatしてる時点でcntの値が意図するものと変わってそうですが、
Veさんのこの記述で自分の意図した通りに動いていますか?



きせん

リンク

2025/10/28(Tue) 22:11:21|NO.104173

私もhkrさんのNO.104154に賛同しますし、そうしてます。



記事削除

記事NO.パスワード
(質問が解決したスレッドは他の利用者に活用してもらうため、削除しないようお願いします)

NO.104119への返信

マスコット

好きなマスコットを選んでください。

名前

e-mail
HOME
  1. 初めて利用する方は、HSP3掲示板の使い方をお読みください。
  2. 不要部分の多い長いスクリプトの投稿は ご遠慮ください。
  3. 書き込みは自動改行されません。適度に改行を入れてください。
  4. スクリプトは小文字の<pre>〜</pre>で囲むと見やすく表示できます。

削除用パスワード

エラー発生時、再送信すると二重送信になることがあります。
回答が得られたら、お礼書き込み時に[解決]チェックしてください。
SPAM防止のためURLから始まる文章は投稿できません。
SPAM防止のため英文字のみの本文を投稿することはできません。

ONION software Copyright 1997-2025(c) All rights reserved.