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


HSPTV!掲示板


未解決 解決 停止 削除要請

2009
0516
ひゃぷよぷよのアルゴリズム8未解決


ひゃ

リンク

2009/5/16(Sat) 17:32:07|NO.25175

いま「ぷよぷよみたいなゲーム」を作っています

消える条件が「同じ色が4つ以上つながる」ではなく
「同じ色でわっかが出来上がる」ということが唯一の違いです

(例1)
■■■△ →    △ →  
■○■■ →  ○   →  
■△○■ →  △○  →  ○
■■■■ →      →  △○△
このとき■はきえます

(例2 <<重要>> )
■■   → ■■   →
■○   → ■○   →
■■■△ →    △ →  ■
■○■■ →  ○   →  ○
■△○■ →  △○  → ■○
■■■■ →      → ■△○△

このときは■の内、下4段のみを消したいと思います
(上2段はまだ閉じていないので)

この消去判定の方法で悩んで質問しました
スクリプトじゃなく、アルゴリズムだけでいいのでどなたか解説お願いします



この記事に返信する


raisen

リンク

2009/5/16(Sat) 19:06:54|NO.25181

アルゴリズムを考えるのがプログラミングの醍醐味だと思うのですが、まぁ無視して解答。

1 ■を探す(その座標を基点とする)。無ければ終わり。
2 基点から上下左右にあるか探す。あったらそこを基点にする。無ければ終わり。

for i = 0 to 3 見っけ! 次の処理へGO! next
ではだめ。見っけ!てもi=4まで。
3 2を繰り返す(候補が複数あったら全てに対し2を行う)
1の基点と見っけ!た基点が一致したら囲まれた。
4 一番左の基点の座標から順に一番右までの基点の座標まで次を行う
 1 一番左の列の一番上の基点からその列の一番下の基点までを消去(オセロと同じ。)
・・・


まで書いておけば大丈夫でしょうか?



ヒカリ

リンク

2009/5/16(Sat) 20:50:17|NO.25184

SRPG の移動範囲の応用みたいな感じでできるのではないかと。
というわけで、こんなのを考えてみました。

1.配列変数の適当な個所を1つ指定。ここを判定の開始点とする。
↓たとえば、一番左上を開始点に。これから「■」で囲っている部分を探す。
■■■■
■□■□
■■■□
判定用の配列変数の内容
↓一番左上を開始点に。
1,0,0,0
0,0,0,0
0,0,0,0

2.開始点に隣接している配列のうち、開始点と同じ図形のモノを次の判定の位置とする。
1,2,0,0
2,0,0,0
0,0,0,0

3.2を繰り返しながら、調べた回数を配列に代入。
1,2,3,4
2,0,4,0
3,4,0,0

4.ぶつかったとき…
1,2,3,4
2,0,4←この4の下は■なので、そこは5に。
3,4,5,0

1,2,3,4
2,0,4,0
3,4,5,0
 ↑つぎに、ここの4から判定しようとすると、
 右の■の位置にはすでに5が代入されているので、ここで終了。

5.今度は5の位置を開始点にして、
  2の逆の要領で、隣接した-1で等しい位置を順に負の値に変換
-1,-2,-3,4
-2, 0,-4,0
-3,-4,-5,0

6.負の値の位置を全て削除


落ちゲーとかボードゲームのアルゴリズムは考えたことないので、
もっと効率のいい方法があるかも知れませんが……。



Sucret

リンク

2009/5/17(Sun) 02:51:41|NO.25197

>>ヒカリさん
その方法だと5(最大値)の隣に一つ■があった場合
例)
■■■■
■□■□
■■■■←

右下の■も消えてしまいませんか?

-----------------------------

同じ色が2つ以上隣接している場合で判定すると
□□□□□
□■■■□
□□□□□
↑でも■がきえてしまいますし…

-----------------------------

 上下のどちらかと左右のどちらかに最低一つずつ同じ色がある場所を調べて
「角」を見つければ出来ないでしょうか?
 とはいえ私もヒカリさんと同じく考えたことは無いので、
御力になれなくて申し訳ございません…。



GENKI

リンク

2009/5/18(Mon) 21:17:39|NO.25233

みなさんこういう課題好きですね。

> スクリプトじゃなく、アルゴリズムだけでいいのでどなたか解説お願いします

「ぷよぷよ アルゴリズム」でググるとすぐ出てきます。
http://www13.plala.or.jp/kymats/study/game_other/TOKOPUYO/tokopuyo.html

すでにあるものに自分のアイデアをプラスアルファするのも楽しいものです。



abast

リンク

2009/5/18(Mon) 21:18:00|NO.25234

ネットで機種依存文字を使うとはなんという愚行



abast

リンク

2009/5/18(Mon) 21:18:50|NO.25235

>GENKI
そうは思えないんだが。好きなやつは自分で黙って考えるだろ。



Sucret

リンク

2009/5/18(Mon) 23:26:00|NO.25244

判定方法について考えてみましたが、この様なものはいかがでしょうか?

判定用に2次元の配列変数を用意します。

[1]判定したい色の上下どちらか(両方でも)に同じ色があり、
  さらに左右のどちらか(同じく両方でも)に同じ色がある部分を角とし、
  判定用の配列変数に-1を代入する(0以外が「角」となる)。
  この方法で全ての「角」を探し出す。
[2]一つの角(判定用配列変数の値が0以外)を基準とし、その角と軸が同じ四方の角の数を求める。
 ただし、角と角の間に異なる色は無いことを条件とし、一方向で数える角の数は1までとする。
 求めた角の数を判定用の配列変数に代入する。
 これを全ての角に行う。
[3]判定用の配列変数を調べ、1が代入されていればそこに0を代入。
 判定用の配列変数全体を調べた際、1が一つでもあった場合は△北瓩襦
 1が一つも無かった場合は次に進む。
 この際、判定用の配列変数全てが0になった場合はブロック(ぷよ?)の消滅はなしとなる。
[4]2以上の同軸上の角同士とその間にある全てのブロックを消す。
  ただし、手順としては一つの角からもう一つの角へ順番で同じ色を消していく。
  その際、途中に異なる色がある場合もあるのでその際は「その角」での消滅はそこまでで止める。

[4]の例
□□□□□□
□■■■□□
□■□■□□
□■■■□□
□△□□□□
□■■■■□
□■□□■□
□■■■■□
□□□□□□
角と角の間を一気に消した場合、上の△も消してしまうため、確認を取る必要がある。

説明が下手ですいません。
加え、処理にかかる時間がわからないので実用的かどうかは保障しかねます…。
HSP暦(PC暦も)2年半の未熟者ですが、少しでも助力になれれば幸いです。

>>abastさん
その様なものがあるとは知りませんでした。己の無知さを恥じるばかりです。
おかげで訂正することが出来ました。本当にありがとうございます。



taddi

リンク

2009/5/19(Tue) 23:02:02|NO.25271

判定方法について、逆の発想で実験してみました。
つまり、つながっているかどうかではなく
検索するピース(色)が外に出られるかどうかを
縦横斜めの8方向に対してチェックするというものです。
よその座標へ逃げられる場合は、その座標で再度確認し、
結局どこにも逃げられない場合、線が結ばれていると判断をする。
というのが概略です。

ちなみに線が結ばれていない場合の処理はしてありません。

また、この判定の特性上、外にある無駄なピースは判定しませんが
囲まれた中にあるピースは判定の対象となります。

本当はもっと厳密にさまざまな場合を想定して検証したいところですが、
それをしていくことはスレ主の方にお任せします。

主にパズルゲームを作ってきた者としては、
それこそ他の方が言われる通り醍醐味だと思います。
頑張ってください。

実験スクリプトの扱い方
何かキーを押してください。
変数mの中で2(○)が囲んでいるものに「レ」がつきます。
囲めていない場合は、エラーが起きます(自己責任でお願いします)


screen 0,32*7,32*10 p="■"," ","○","△","□" dim m,7,10 m(0,0)=0,0,0,0,0,0,0 m(0,1)=0,1,1,1,1,1,0 m(0,2)=0,1,1,1,1,1,0 m(0,3)=0,1,1,1,2,1,0 m(0,4)=0,1,1,2,2,1,0 m(0,5)=0,2,2,2,1,1,0 m(0,6)=0,2,4,2,2,1,0 m(0,7)=0,2,4,4,2,1,0 m(0,8)=0,2,2,2,2,1,0 m(0,9)=0,0,0,0,0,0,0 cx=-1,-1,0,1,1,1,0,-1 : cy=0,-1,-1,-1,0,1,1,1 dim c,7,10 font msgothic,32 *main stick key : if key!0{gosub *check} redraw 0 : color : boxf repeat 7 : x=cnt repeat 10 : y=cnt pos x*32,y*32 : color 255,255,255 : mes p(m(x,y)) if c(x,y)=-1{ pos x*32,y*32 : color 0,255,0 : mes "レ" } loop loop redraw 1 : await 16 goto *main *check c_col=2 repeat 5,1 : x=cnt repeat 8,1 : y=cnt if m(x,y)!1&m(x,y)!c_col{ px=x : py=y : lc=0 : dim lx,70 : dim ly,70 repeat repeat 8 if m(px+cx(cnt),py+cy(cnt))=c_col{ c(px+cx(cnt),py+cy(cnt))=-1 }else{ if c(px+cx(cnt),py+cy(cnt))=0{ c(px+cx(cnt),py+cy(cnt))=1 lx(lc)=px+cx(cnt) : ly(lc)=py+cy(cnt) : lc+ } } loop if lc!0{ lc- : px=lx(lc) : py=ly(lc) }else{ break } loop } loop loop return



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