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


HSPTV!掲示板


未解決 解決 停止 削除要請

2007
0213
YSRHSPで作った連珠プログラムの矛盾11解決


YSR

リンク

2007/2/13(Tue) 16:59:34|NO.5663

最近、連珠のプログラムを作っていますが、
なぜか五連を認識しなかったり、四三を三々と誤判定します。
何ででしょうか。コードはこちら↓

;連珠5 #packopt name "連珠5.exe" #include "mod_menu.as" ;-------- マクロ宣言 -------- #enum global NULL=0 #enum sousa_kifu #enum sousa_ahead #enum sousa_next #enum sousa_battle ;----- ボタンを押したときに自動的に飛ぶ ----- oncmd gosub *menuclick,WM_COMMAND onkey gosub *keypush size=20 kflg=0 ;---------- メニュー ---------- ;---------- 操作(&S) ---------- newmenu smenu,1 addmenu smenu,"棋譜ロード(&L)",sousa_kifu addmenu smenu,"前に戻る(&A)",sousa_ahead addmenu smenu,"次に進む(&N)",sousa_next addmenu smenu,"対戦(&B)",sousa_battle newmenu menu,0 addmenu menu,"操作(&S)",smenu,0x10 applymenu menu ;------------------------------ screen 0,size*17,size*21 font "MS ゴシック",size title "連珠5" stop *menuclick switch (wparam & 0xFFFF) case sousa_kifu gosub *record kflg=1 swbreak case sousa_ahead gosub *mae swbreak case sousa_next gosub *ato swbreak case sousa_battle gosub *taisen kflg=0 swbreak swend return *keypush ;L…ロード A…前 N…後 V…対戦 switch iparam case 76 gosub *record kflg=1 swbreak case 65 gosub *mae swbreak case 78 gosub *ato swbreak case 66 gosub *taisen kflg=0 swbreak swend return ;----------------------------- *record dialog "txt",16,"棋譜ファイル" if stat=0 :return dim ban,15,15 ;0→無,1→黒,2→白 sdim kifu,7*15*15+100 ;棋譜データ。一列五行、ALL notesel kifu :noteload refstr max=notemax title "連珠5 - 棋譜("+strf("%3d",point)+"手目)" gosub *byoga ;棋譜解析・閲覧 gosub *kaiseki return *kaiseki sdim datax,20,15*15 sdim datay,20,15*15 for gyo,0,max noteget data,gyo datax(gyo)=int(strmid(data,0,2))-1 datay(gyo)=int(strmid(data,3,2))-1 next return *mae if (kflg=0)|(point=0) :return point- ban(datax(point),datay(point))=0 title "連珠5 - 棋譜("+strf("%3d",point)+"手目)" gosub *byoga2 return *ato if (kflg=0)|(point=max-1) :return point+ title "連珠5 - 棋譜("+strf("%3d",point)+"手目)" gosub *byoga2 return *byoga2 for k,0,point teban2=k\2+1 ban(datax(k),datay(k))=teban2 next gosub *byoga return ;----------------------------- *taisen onkey 0 pat=0 mes " 黒 白 key" mes " 人 vs 人 → A" mes " 人 vs CPU → B" mes "CPU vs 人 → C" mes "CPU vs CPU → D" mes "今、Aのみ" repeat getkey keycheck,65 :if keycheck=1 :pat=1 :break ;getkey keycheck,66 :if keycheck=1 :pat=2 :break ;getkey keycheck,67 :if keycheck=1 :pat=3 :break ;getkey keycheck,68 :if keycheck=1 :pat=4 :break await 5 loop ;配列を初期化 dim ban,15,15 ;0→無,1→黒,2→白 sdim kifu,7*15*15+100 ;棋譜データ。一列五行、ALL title "連珠5 - 対戦" gosub *byoga vsflg=0 :winflg=0 ;打つ for count,0,225 teban=count\2+1 if teban=1 :t2="黒" :else :t2="白" mes t2+"の手番です。" switch pat case 1 gosub *keyloop swbreak case 2 if teban=1 :gosub *keyloop :else :gosub *complay swbreak case 3 if teban=2 :gosub *keyloop :else :gosub *complay swbreak case 4 gosub *complay swbreak swend gosub *kiroku mx- :my- ban(mx,my)=teban gosub *byoga gosub *hantei if (iflg1=1)|(iflg2=1)|(iflg3=1) { vsflg=2 _break } else { if gflg=1 { vsflg=1 _break } } next if vsflg=1 { mes t2+"の勝ちです!" :kifu+=str(t2)+"の勝ちです!" } else { if vsflg=2 { if iflg1=1 :mes "黒の三々禁負けです。" :kifu+="黒の三々禁負けです。" if iflg2=1 :mes "黒の四々禁負けです。" :kifu+="黒の四々禁負けです。" if iflg3=1 :mes "黒の長連禁負けです。" :kifu+="黒の長連禁負けです。" } else :mes "引き分けです。" :kifu+="引き分けです。" } dialog "棋譜を保存しますか?(kifu.txt)",2,"連珠5" if stat=6 :notesel kifu :notesave "kifu.txt" cls :onkey 1 dialog "終了" return ;----------------------------- *keyloop repeat stick ky,16+256 if ky&16 :dialog kifu if ky&256 { mx=int(1.0*mousex/size) :my=int(1.0*mousey/size) if (mx>=1)&(mx<=15)&(my>=1)&(my<=15) { if ban(mx-1,my-1)=0 :break } } await 5 loop return *complay wait 10 randomize bak=teban ;自分の手番をバックアップ ura=-teban+3 ;敵の手番を変数に格納 ;自分の五連を探す for y,0,15 for x,0,15 if ban(x,y)=0 { teban=bak :mx=x :my=y gosub *hantei if gflg=1 { mx=x+1 :my=y+1 :teban=bak return } } next next ;敵の活四を防ぐ if k4flg=1 { } ;ランダムに手を生成 sdim listx,225 :sdim listy,225 kazu=0 for y,0,15 for x,0,15 if ban(x,y)=0 { teban=bak :mx=x :my=y gosub *hantei if (iflg1=0)&(iflg2=0)&(iflg3=0) { listx(kazu)=x :listy(kazu)=y kazu+ } } next next listr=rnd(kazu) mx=listx(listr)+1 :my=listy(listr)+1 return *byoga ;盤を描画 redraw 0 cls mes " WWWWWWWWWWWWWWW " sdim hyozi,20 for y,0,15 hyozi="W" for x,0,15 if ban(x,y)=0 :hyozi+="┼" if ban(x,y)=1 :hyozi+="●" if ban(x,y)=2 :hyozi+="○" next hyozi+="W" mes hyozi next mes " WWWWWWWWWWWWWWW " redraw 1 return *kiroku kifu+=strf("%2d",mx)+","+strf("%2d",my)+"\n" return ;[渡し値] ;[返り値] ;gflg {0…五連無し,1…五連有り} ;k4flg,k3flg ;iflg1(0…三々禁なし,1…三々禁あり) ;iflg2(0…四々禁なし,1…四々禁あり) ;iflg3(0…長連禁なし,1…長連禁あり) *hantei gflg=0 :iflg1=0 :iflg2=0 :iflg3=0 ;五連が出来ているか調べる gosub *hantei2 ;五連を調べる(グレードアップ版) dim yaku2,4 yaku2(0)=yaku(0)+yaku(4)-1 ;上下方向 yaku2(1)=yaku(1)+yaku(5)-1 ;右斜め方向 yaku2(2)=yaku(2)+yaku(6)-1 ;左右方向 yaku2(3)=yaku(3)+yaku(7)-1 ;左斜め方向 dim katu2,4 katu2(0)=katu(0)+katu(4) katu2(1)=katu(1)+katu(5) katu2(2)=katu(2)+katu(6) katu2(3)=katu(3)+katu(7) dim tobi,4 ;五連判定 for k,0,4 if yaku2(k)=5 { ;通常五連 gflg=1 _break } else { if yaku2(k)>5 { if teban=1 { ;長連・黒 iflg3=1 _break } else { ;長連・白 gflg=1 _break } } } next ;三々・四々判定 ;カウント sansan=0 sisi=0 for k,0,4 if (yaku2(k)=3)&(katu2(k)=0) :sansan+ if (yaku2(k)=4)&(katu2(k)!2) :sisi+ next if (sansan>=2)&(teban=1) { iflg1=1 }else { if sansan=1 { k3flg=1 } } if (sisi>=2)&(teban=1) { iflg2=1 }else { if sisi=1 { k4flg=1 } } return ;[渡し値] ;teban {1…黒,2…白} ;mx,my ;[返り値] ;yaku(0〜7) 数 ;katu(0〜7) 敵の石があるか *hantei2 dim yaku,8 dim katu,8 ura=-teban+3 ;上 if my>=4 { hflg=0 for k,0,5 switch ban(mx,my-k) case teban hflg+ swbreak case ura katu(0)=1 _break swbreak swend next yaku(0)=hflg } ;右上 if (mx<=10)&(my>=4) { hflg=0 for k,0,5 switch ban(mx+k,my-k) case teban hflg+ swbreak case ura katu(1)=1 _break swbreak swend next yaku(1)=hflg } ;右 if mx<=10 { hflg=0 for k,0,5 switch ban(mx+k,my) case teban hflg+ swbreak case ura katu(2)=1 _break swbreak swend next yaku(2)=hflg } ;右下 if (mx<=10)&(my<=10) { hflg=0 for k,0,5 switch ban(mx+k,my+k) case teban hflg+ swbreak case ura katu(3)=1 _break swbreak swend next yaku(3)=hflg } ;下 if my<=10 { hflg=0 for k,0,5 switch ban(mx,my+k) case teban hflg+ swbreak case ura katu(4)=1 _break swbreak swend next yaku(4)=hflg } ;左下 if (mx>=4)&(my<=10) { hflg=0 for k,0,5 switch ban(mx-k,my+k) case teban hflg+ swbreak case ura katu(5)=1 _break swbreak swend next yaku(5)=hflg } ;左 if mx>=4 { hflg=0 for k,0,5 switch ban(mx-k,my) case teban hflg+ swbreak case ura katu(6)=1 _break swbreak swend next yaku(6)=hflg } ;左上 if (mx>=4)&(my>=4) { hflg=0 for k,0,5 switch ban(mx-k,my-k) case teban hflg+ swbreak case ura katu(7)=1 _break swbreak swend next yaku(7)=hflg } return
↑長い…。メニュー表示&棋譜閲覧機能&COM対戦機能(途中)をつけたからか・・・。



この記事に返信する


kz3

リンク

2007/2/13(Tue) 17:57:14|NO.5665

>↑長い…。メニュー表示&棋譜閲覧機能&COM対戦機能(途中)をつけたからか・・・。

だったらつけないで下さい。

投稿時に削除用パスワードを設定するフォームの左側にある、1,2,3の項目の1をよく読んでください。
必要なら長くてもいい、というわけではないと思います。

この場合、メニューや棋譜ロードなどのコードは問題の処理とは関係ないため、不必要でしょう。

不要なコードを入れるということは読み手に余計なコードを読ませるということになります。
自分がデバッグする身であれば、バグと関係のない部分まで読むハメになり、結局読むコードが多くてデバッグできないということに繋がるのです。

不具合の直し方が分からないのは仕方ないとして、不具合がどこで起きているのかを調べるのは、書いているプログラマの仕事です。

どこで不具合が起きているのか分からない、ということであれば、その場所を探す手がかりを教えます。
こちら(http://quasiquote.org/hspwiki/%a5%c7%a5%d0%a5%c3%a5%b0%a4%ce%bb%c5%ca%fd)を読んで、意図しない動作を引き起こしている場所を探してから、再度質問してみてください。



z

リンク

2007/2/13(Tue) 20:30:47|NO.5668

何様のつもりなんだ。いい加減仕切るのは止めろ。
長いのが嫌ならそういうのは回答しないようにしたらいい。



93

リンク

2007/2/13(Tue) 20:40:57|NO.5669

(´゚Д゚) ・・・

( ゚Д゚ )



GENKI

リンク

2007/2/14(Wed) 01:21:36|NO.5672

> いい加減仕切るのは止めろ。

まあまあ。(^-^;
最近?質問なれ掲示板なれしてない人が増えてるからデバッグ誘導の回答の質も回数も向上しますよ。
黙ってても誰かがやるし、誰もやらないようなら廃れていっちゃうんじゃないかな。
言わないでわかってもらえるならそれがいいんだけど、言わなきゃ気が付かない事だってあるんですよ。


> ↑長い…。メニュー表示&棋譜閲覧機能&COM対戦機能(途中)をつけたからか・・・。

というわけで、もう少し自分でデバッグ(スクリプト縮小)してからまた来てください。
まあ、デバッグのいい練習の機会だとでも思って…。

(とか言ってる間に誰か回答しそうな気が…。)



> なぜか五連を認識しなかったり、四三を三々と誤判定します。

それ以前にクリックした座標と碁石の座標がずれてるのが気になった。



rtb

リンク

2007/2/14(Wed) 11:07:59|NO.5680

(´゚Д゚) ・・・

つ)゚Д゚ )

メ´_ゝ`)どいつもこいつも馬鹿ばっかだぜ。困ったもんだ。



KIMU

リンク

2007/2/14(Wed) 11:41:05|NO.5681


// mx=int(1.0*mousex/size) :my=int(1.0*mousey/size) // ↓にする(標準全角フォントのサイズがx=16,y=18だから) mx=int(1.0*mousex/16) :my=int(1.0*mousey/18) //*hantei2を全部入れ替え *hantei2 dim yaku,8 dim katu,8 ura=-teban+3 l=limit(mx+1,0,5) r=limit(15-mx,0,5) u=limit(my+1,0,5) d=limit(15-my,0,5) if r<u {ru=r}else{ru=u} if r<d {rd=r}else{rd=d} if l<d {ld=l}else{ld=d} if l<u {lu=l}else{lu=u} x=0,ru,r,rd,0,ld,l,lu y=u,ru,0,rd,d,ld,0,lu kx= 0, 1,1,1,0,-1,-1,-1;これは、最初に設定 ky=-1,-1,0,1,1, 1, 0,-1;しとけばいんだけど・・・ repeat 8 nflg=0 hflg=0 cntf=cnt if x(cntf) {i=x(cntf)}else{i=y(cntf)} _kx=kx(cntf) _ky=ky(cntf) repeat i switch ban(mx+cnt*_kx,my+cnt*_ky) case 0 if nflg{break} nflg++ swbreak case teban hflg+ swbreak case ura katu(cntf)=1 ;碁盤の淵にも同じような処理が必要じゃない? break swbreak swend loop yaku(cntf)=hflg loop if teban=1{mes "●"}else{mes "○"} mes " 上("+yaku(0)+") 右("+yaku(2)+") 下("+yaku(4)+") 左("+yaku(6)+")" mes "右上("+yaku(1)+") 右下("+yaku(3)+") 左下("+yaku(5)+") 左上("+yaku(7)+")" mes "------------------------------------------" return


NO.5663のは、二升以上開いていても繋がってるようにカウントされていた


case 0 if nflg{break} nflg++ swbreak
これを追加して空きが二個以上あったらその方向のカウントを終わるようにした。

後は、外側から5個以上内側に無いと外側方向の判定が飛ばされてたのを
4以下でも判定するようにした。

>なぜか五連を認識しなかったり、四三を三々と誤判定します。
どの状態の時に、旨く行かないのかを探すのは、作ってる人の仕事だよ。



YSR

リンク

2007/2/14(Wed) 12:55:57|NO.5682

説明を加えます。
クリックした座標と碁石の座標がずれているのは、
棋譜を保存するときに分かりやすくするためです。
あと、KIMUさん、新たなコードを書いてくださり、ありがとうございます。
なお、「size」としているのは、前のコード(ここに乗せたコードより前)
で、盤のサイズを簡単に変更できるようにするためのコードの名残です。



ふほ

リンク

2007/2/14(Wed) 12:57:54|NO.5683

別に仕切られても困らないけど、怖いのは勘弁して下さい(泣(笑



KIMU

リンク

2007/2/14(Wed) 14:06:10|NO.5686

>あと、KIMUさん、新たなコードを書いてくださり、ありがとうございます。
まだ不完全だった・・・
完全に繋がってる石を数える処理をしてない
これをやらないと
●●┼1●●
この状態で1に黒が置かれると5個連続してるようにカウントされる



KIMU

リンク

2007/2/14(Wed) 21:14:47|NO.5697

>●●┼1●●
にも対応してみた。


//*kiroku ↓を追加 dim rens2,4 ;追加 rens2(0)=rens(0)+rens(4)-1 ;追加 rens2(1)=rens(1)+rens(5)-1 ;追加 rens2(2)=rens(2)+rens(6)-1 ;追加 rens2(3)=rens(3)+rens(7)-1 ;追加 > ;五連判定 > for k,0,4 > if yaku2(k)=5 { ;通常五連 > gflg=1 > _break > } > else { > if yaku2(k)>5 { ↓に変更 ;五連判定 for k,0,4 if rens2(k)=5 { ;変更 gflg=1 _break } else { if rens2(k)>5 { ;変更



//*hantei2 > repeat i > switch ban(mx+cnt*_kx,my+cnt*_ky) > case 0 > if nflg{break} > nflg++ > swbreak > case teban > hflg+ > swbreak > case ura > katu(cntf)=1 ;碁盤の淵にも同じような処理が必要じゃない? > break > swbreak > swend > loop ↓に入れ替え repeat i switch ban(mx+cnt*_kx,my+cnt*_ky) case 0 if nflg{break} nflg=hflg ;変更 swbreak case teban hflg+ swbreak case ura katu(cntf)=1 break swbreak swend loop if nflg=0 {rens(cntf)=hflg}else{rens(cntf)=nflg} ;追加



のーなめ

リンク

2007/2/22(Thu) 18:33:46|NO.5869

kz3の意見には同意ですが、書き方というものがあると思います。
上から見ている様に見えてしまいます。


YSRさんもkz3に対してなんらかの返信をするべきではないでしょうか?




# 最近、質問に答えて貰えるのが当たり前だと思う人多すぎだと思うのは俺だけ?



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