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


HSPTV!掲示板


未解決 解決 停止 削除要請

2015
0211
魔龍☆パズルゲーム、4つ並ぶと消える判定方法8解決


魔龍☆

リンク

2015/2/11(Wed) 15:46:47|NO.67367

パズルアンド〇ラゴンズや、愛と勇気と〇しわもちのように、いくつか並んだら消える、というパズルゲームを作ろうと思ってます。
そこで、私は判定方法で苦戦しているのですが、教えていただけないでしょうか。

今まで書いてきたやり方では以下の通りです。
for nextのループでX,Y座標(列)を指定し、その列の組み合わせを全通り調べて、消えるようならばそこの座標の変数を5にします。
*yoko
if cal(0,y)=cal(1,y) and cal(0,y)=cal(2,y) and cal(0,y)=cal(3,y) :cal(0,y)=5:cal(1,y)=5:cal(2,y)=5:cal(3,y)=5:foooo=1
if cal(1,y)=cal(2,y) and cal(1,y)=cal(3,y) and cal(1,y)=cal(4,y) :cal(1,y)=5:cal(2,y)=5:cal(3,y)=5:cal(4,y)=5:foooo=1
if cal(2,y)=cal(3,y) and cal(2,y)=cal(4,y) and cal(2,y)=cal(5,y) :cal(2,y)=5:cal(3,y)=5:cal(4,y)=5:cal(5,y)=5:foooo=1
if cal(3,y)=cal(4,y) and cal(3,y)=cal(5,y) and cal(3,y)=cal(6,y) :cal(3,y)=5:cal(4,y)=5:cal(5,y)=5:cal(6,y)=5:foooo=1
if cal(4,y)=cal(5,y) and cal(4,y)=cal(6,y) and cal(4,y)=cal(7,y) :cal(4,y)=5:cal(5,y)=5:cal(6,y)=5:cal(7,y)=5:foooo=1
if cal(0,y)=cal(1,y) and cal(0,y)=cal(2,y) and cal(0,y)=cal(3,y) and cal(0,y)=cal(4,y) :cal(0,y)=5:cal(1,y)=5:cal(2,y)=5:cal(3,y)=5:cal(4,y)=5:foooo=1
if cal(1,y)=cal(2,y) and cal(1,y)=cal(3,y) and cal(1,y)=cal(4,y) and cal(1,y)=cal(5,y) :cal(1,y)=5:cal(2,y)=5:cal(3,y)=5:cal(4,y)=5:cal(5,y)=5:foooo=1
if cal(2,y)=cal(3,y) and cal(2,y)=cal(4,y) and cal(2,y)=cal(5,y) and cal(2,y)=cal(6,y) :cal(2,y)=5:cal(3,y)=5:cal(4,y)=5:cal(5,y)=5:cal(6,y)=5:foooo=1
if cal(3,y)=cal(4,y) and cal(3,y)=cal(5,y) and cal(3,y)=cal(6,y) and cal(3,y)=cal(7,y) :cal(3,y)=5:cal(4,y)=5:cal(5,y)=5:cal(6,y)=5:cal(7,y)=5:foooo=1
if cal(0,y)=cal(1,y) and cal(0,y)=cal(2,y) and cal(0,y)=cal(3,y) and cal(0,y)=cal(4,y) and cal(0,y)=cal(5,y) :cal(0,y)=5:cal(1,y)=5:cal(2,y)=5:cal(3,y)=5:cal(4,y)=5:cal(5,y)=5:foooo=1
if cal(1,y)=cal(2,y) and cal(1,y)=cal(3,y) and cal(1,y)=cal(4,y) and cal(1,y)=cal(5,y) and cal(1,y)=cal(6,y) :cal(1,y)=5:cal(2,y)=5:cal(3,y)=5:cal(4,y)=5:cal(5,y)=5:cal(6,y)=5:foooo=1
if cal(2,y)=cal(3,y) and cal(2,y)=cal(4,y) and cal(2,y)=cal(5,y) and cal(2,y)=cal(6,y) and cal(2,y)=cal(7,y) :cal(2,y)=5:cal(3,y)=5:cal(4,y)=5:cal(5,y)=5:cal(6,y)=5:cal(7,y)=5:foooo=1
if cal(0,y)=cal(1,y) and cal(0,y)=cal(2,y) and cal(0,y)=cal(3,y) and cal(0,y)=cal(4,y) and cal(0,y)=cal(5,y) and cal(0,y)=cal(6,y) :cal(0,y)=5:cal(1,y)=5:cal(2,y)=5:cal(3,y)=5:cal(4,y)=5:cal(5,y)=5:cal(6,y)=5:foooo=1
if cal(1,y)=cal(2,y) and cal(1,y)=cal(3,y) and cal(1,y)=cal(4,y) and cal(1,y)=cal(5,y) and cal(1,y)=cal(6,y) and cal(1,y)=cal(7,y) :cal(1,y)=5:cal(2,y)=5:cal(3,y)=5:cal(4,y)=5:cal(5,y)=5:cal(6,y)=5:cal(7,y)=5:foooo=1
if cal(0,y)=cal(1,y) and cal(0,y)=cal(2,y) and cal(0,y)=cal(3,y) and cal(0,y)=cal(4,y) and cal(0,y)=cal(5,y) and cal(0,y)=cal(6,y) and cal(0,y)=cal(7,y) :cal(0,y)=5:cal(1,y)=5:cal(2,y)=5:cal(3,y)=5:cal(4,y)=5:cal(5,y)=5:cal(6,y)=5:cal(7,y)=5:foooo=1
return

(縦も同様)

しかし、これでは5つ並んだ時に消えない不具合が起きたり、文が長すぎて動きが遅い気がするのです。
これの間違いをしていただくか、もっと短く書く方法を教えていただきたいです。

ここの掲示板に書かれてあることはみんな(私にとって)レベルが高いのでこんなことで投稿していいのかと思いますが、
教えていただけたら非常にありがたいです。



この記事に返信する


科学太郎

リンク

2015/2/11(Wed) 16:33:49|NO.67369

> ここの掲示板に書かれてあることはみんな(私にとって)レベルが高いのでこんなことで投稿していいのかと思いますが、
> 教えていただけたら非常にありがたいです。
まずは、上記のソースを繰り返し命令で記述しな直すことから始めてみましょう。
分かりますか?



魔龍☆

リンク

2015/2/11(Wed) 16:48:55|NO.67370

>>繰り返し命令で記述
すいません、抜けているところがあったので訂正します。
ここまで、
for y,0,8
gosub *yoko
next
で来ています。これではいけないでしょうか。



男子中学生

リンク

2015/2/11(Wed) 17:12:42|NO.67371

for~next文を「入れ子」(for~next文の中にfor~next文を入れる)
すればよいです。



font "",20 for x,0,10,1;______________________ ;| for y,0,10,1;_______________ | pos 20*x,20*y:mes "○";| | next;______________________| | ;| next;_____________________________|



(´ω`)

リンク

2015/2/11(Wed) 18:04:55|NO.67372

こういうのんのアルゴリズムを考えてる時が、一番楽しいんですよね。(´ω`)

複数の石を全部同じテーブルに入れて1つ1つ比較する方法は一番実直ですが、
石の種類ごとにテーブルをわけてみてはいかがでしょうか。

例えば、ゲーム中にA〜Eの5種類の石が出るならば、各種類ごとに5つのテーブルを作ります。
で、各テーブル内には、0(ない)、1(ある)の情報だけを入れます。
すると、並んでいるかどうか判定するのは、単純な足し算で済みますね。

これをさらに推し進めると、並びのチェックも消す作業も、ビット演算で簡単に済むことが
わかると思います。ぜひお考えください。(´ω`)



KA

リンク

2015/2/11(Wed) 20:07:52|NO.67376

ちょっと整形して見ました。

for y,0,8 gosub *yoko next *yoko A=cal(0,y) B=cal(1,y) C=cal(2,y) D=cal(3,y) E=cal(4,y) F=cal(5,y) G=cal(6,y) H=cal(7,y) if A=B & A=C & A=D : A=5 : B=5 : C=5 : D=5 : foooo=1 if B=C & B=D & B=E : B=5 : C=5 : D=5 : E=5 : foooo=1 if C=D & C=E & C=F : C=5 : D=5 : E=5 : F=5 : foooo=1 if D=E & D=F & D=G : D=5 : E=5 : F=5 : G=5 : foooo=1 if E=F & E=G & E=H : E=5 : F=5 : G=5 : H=5 : foooo=1 if A=B & A=C & A=D & A=E : A=5 : B=5 : C=5 : D=5 : E=5 : foooo=1 if B=C & B=D & B=E & B=F : B=5 : C=5 : D=5 : E=5 : F=5 : foooo=1 if C=D & C=E & C=F & C=G : C=5 : D=5 : E=5 : F=5 : G=5 : foooo=1 if D=E & D=F & D=G & D=H : D=5 : E=5 : F=5 : G=5 : H=5 : foooo=1 if A=B & A=C & A=D & A=E & A=F : A=5 : B=5 : C=5 : D=5 : E=5 : F=5 : foooo=1 if B=C & B=D & B=E & B=F & B=G : B=5 : C=5 : D=5 : E=5 : F=5 : G=5 : foooo=1 if C=D & C=E & C=F & C=G & C=H : C=5 : D=5 : E=5 : F=5 : G=5 : H=5 : foooo=1 if A=B & A=C & A=D & A=E & A=F & A=G : A=5 : B=5 : C=5 : D=5 : E=5 : F=5 : G=5 : foooo=1 if B=C & B=D & B=E & B=F & B=G & B=H : B=5 : C=5 : D=5 : E=5 : F=5 : G=5 : H=5 : foooo=1 if A=B & A=C & A=D & A=E & A=F & A=G & A=H : A=5 : B=5 : C=5 : D=5 : E=5 : F=5 : G=5 : H=5 : foooo=1 return

3つ連続していれば全て「5」に成るようですが、もし「5」以外
の数字が4つ以上連続していた場合はどうなるのか考えて見ましょう。

IF で、こういう使い方をする時は鉄則があります。



KA

リンク

2015/2/11(Wed) 20:18:30|NO.67377

付け加えると

A=B=C=D=E

の状態は

if A=B & A=C & A=D
if B=C & B=D & B=E
if A=B & A=C & A=D & A=E

が、全て成立します。



Drip

リンク

2015/2/11(Wed) 20:38:49|NO.67378

こんにちは、Dripです。

 魔龍☆さん、こんにちは。
連続して並んだボールの数をカウントする方法はかなり沢山ありますが、
よりシンプルに書きたいか、より高速な処理で書きたいか、よりメモリ消費を抑えたいか…
等によって、書き方が全く変わってきます。もしも初めて挑戦するジャンルであれば、
動作速度よりも見やすさと安定性を重視して自分なりに構想を練ってみると良いかと思います。
魔龍☆さんのコードの様子ですと、まずrepeat - loop の構文と二次元配列を理解することで、
また別の角度からロジックを考察できるようになるかと思いますよ。

 私自身パズドラは遊んだことが無いのですが、
以下に「動作速度よりも手数の少なさとシンプルさを重視したパズドラらしき処理」
をするサンプルを示します。整形しても80行未満です。現状理解が難しいかもしれませんが、
“この程度書けばこの程度の処理ができる”…くらいの参考になれば幸いです。
どうぞ頑張ってください。

//★パズドラらしき何かをするサンプル/パラメータをいじって鑑賞してみてください。 //━━━━━━━━ ゲーム設定パラメータここから ━━━━━━━━ #define pat 3 //ボールの色の種類 #define norma 4 //何個で消滅するか #define rule 4 //消滅ルール 1:横のみ 2:縦と横 4:縦と横と斜め #define fx 20 //フィールド横サイズ #define fy 10 //フィールド縦サイズ #define sz 24 //ボールのサイズ #define destTime 20 //消滅時の点滅フレーム数 #define dropFrm 5 //落下待ちフレーム(小さいほど早い) //━━━━━━━━ ゲーム設定パラメータここまで ━━━━━━━━ dim map,fx,fy //フィールドのボール状態を格納する変数。-1だと空白 dim chain,fx,fy //いくつくっついているかを格納する変数 mode=0 //0:消滅チェック 1:ボールが消滅中 2:ボールが落下中 time=0 //フレームカウンタ chx=1,0,1,1 //チェック方向X chy=0,1,1,-1 //チェック方向Y colShift=int(192.0/pat) //ボールの色の差 repeat fx*fy:map(cnt\fx,cnt/fx)=rnd(pat):loop //ボールをランダムに配置 screen 0,fx*sz,fy*sz:randomize *main //★メインループ redraw 0 //●落下ボールが無く、何もしていなければいくつくっついてるか調べる if mode=0:{ repeat fx*fy:tx=cnt\fx:ty=cnt/fx chain(tx,ty)=0 //全ての方向を同じ処理でチェックしてしまう if map(tx,ty)>-1:{ //ボールがあったら処理開始 repeat rule //1ボールごとに横・縦・斜め・逆斜めの順でチェック。 prm=tx,ty,map(tx,ty),1,chx(cnt),chy(cnt):gosub *chk prm=tx,ty,map(tx,ty),prm(3),-chx(cnt),-chy(cnt):gosub *chk if chain(tx,ty)<prm(3):chain(tx,ty)=prm(3) //くっついてるボール数更新 loop } if chain(tx,ty)>=norma:mode=1:time=0 //ノルマを満たすボールがあれば消滅モードに移行 loop } //●ボール消滅モード if mode=1:{ if time>destTime:{ //消滅時間が来たら消す。それまでは点滅待機。 repeat fx*fy if chain(cnt\fx,cnt/fx)>=norma:{ //ノルマを満たしたボール発見 map(cnt\fx,cnt/fx)=-1:chain(cnt\fx,cnt/fx)=0 //消滅 } loop mode=0 } } //●ボール消滅モードでないなら、指定フレーム毎に落下チェック if mode!1 & time\dropFrm=dropFrm-1:{ mode=0 //落下処理が行われなかった場合はくっつきチェックに移行する準備 repeat fx*fy-fx,1:tx=(fx*fy-cnt)\fx:ty=(fx*fy-cnt)/fx //下から上に検索 if map(tx,ty)<0:{ //空白を見つけたら上のボールを空白に落下移動する map(tx,ty)=map(tx,ty-1):chain(tx,ty)=chain(tx,ty-1) map(tx,ty-1)=-1:chain(tx,ty-1)=-1:mode=2 } loop repeat fx //最上段に隙間があればボールを新規リリース if map(cnt)<0:map(cnt)=rnd(pat) loop } //●画面の描画 color 255,255,255:boxf repeat fx*fy //ボールがあるか、点滅表示中であればそのボールを描画する if map(cnt\fx,cnt/fx)>-1 & (chain(cnt\fx,cnt/fx)<norma | time/4\2=0):{ hsvcolor map(cnt\fx,cnt/fx)*colShift,191,220 circle cnt\fx*sz,cnt/fx*sz,cnt\fx*sz+sz,cnt/fx*sz+sz,1 } loop redraw 1:await 30:time++ //フレーム待ち goto *main *chk //prm,prm(1)の座標からprm(2)の色が隣接していればprm(3)を増やし、 //prm,pmr(1)の座標をprm(4),prm(5)ずつ移動して再起処理するサブルーチン prm+=prm(4):prm(1)+=prm(5) if prm<0 | prm>=fx | prm(1)<0 | prm(1)>=fy:return if map(prm,prm(1))=prm(2):prm(3)++:gosub *chk //再起 return



魔龍☆

リンク

2015/2/11(Wed) 23:45:56|NO.67380

>>ka様
このやり方は、長い変数名を、AやBなどの単純なものにして、読みやすくした、というものでしょうか。

>>Drip様
なるほど・・・ruleの所を2にすると縦と横だけにできるんですね!
これをいじったりしてじっくり見て行こうと思います。

みなさま、ご丁寧にありがとうございました。ゆっくり考えて行こうと思います!!



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