グリッド上のタイルのセットが囲まれた形状を形成するかどうかを決定します


10

グリッド上のタイルのセットを前提として、以下を決定します。

  • タイルが囲まれた図を作る場合
  • ボードの側面を図の端として数えたときにタイルが囲まれた図を作る場合
  • 前の2つのステートメントのいずれかがtrueの場合、追加のタイルが囲まれた図の内側に入ると、最初のタイルが形成されます。

プレーヤーは、1つのタイルを押し下げてから、指を他のタイルにドラッグして、同じ色のタイルのチェーンを作成します。次のタイルが有効であるかどうかを確認するために行くときに確認します。例 プレーヤーが赤いタイルから始めた場合、次に有効なのは隣接する赤いタイルへの移動のみです(対角線カウントされます)。ユーザーが指を離したときに、上記の3つの項目を確認できるようにする必要があります。

ですから、私の最初の考えは、行くたびにチェーンの有効性をチェックしているので、プレーヤーが指を離したときに、最初と最後のタイルが隣接しているかどうかを確認できるということでした。(同じ色だとわかっています。)隣接している場合は、囲まれた図を作成するという予感がありました。ここに来て、大きなものが足りないかどうかを確認しました。私の直感が正しかったことのある種の論理的/数学的な証明(またはそれが正しくないことを証明する例)

しかし、そのときは、アイテム番号2について考えました。ボードの端を囲まれた図の側面として使用するチェーンも考慮する必要があります。その場合、チェーンの最初と最後のアイテムは隣接しませんが、囲まれた図がまだあります。さて、私は少し正方形に戻りました。

このグリッド座標のチェーンを使用して、囲まれた図を作成するかどうかを判断するにはどうすればよいですか?私は一度、、私は囲まれた数字を持って知って、その境界内に入る全てのタイルの追加のリストを取得するための最良の方法は何ですか?

ここに画像の説明を入力してください

ここに画像の説明を入力してください

上記では、このテストの4つの可能な結果が期待できるものの絵を描きました。

  1. チェーンは同封の図を作りません。

  2. チェーンは囲まれた図を作ります。

  3. ボードの側面を図のエッジ(または複数のエッジ)として数えると、チェーンは囲まれた図になります。

  4. チェーンは囲まれた図を作成しますが、作成された図の一部ではない余分なデータポイント(チェーンの一部としてユーザーが有効に選択したもの)があります。

ケース4は、「余分な」チェーンリンクを抽出して、囲まれた図形とその中にある部分を見つける必要があるためです(ただし、「閉じられていない」領域の周りではありません)。

だから...誰もがこれを解決する良い方法のアイデアを持っていますか、それとも私のための出発点ですか?この時点で私は一種の円を描いており、別の目を使用できます。


1
8の字や五芒星のような交差するパスはどうですか?非ゼロまたは偶奇のフィルルールを想定しますか?
Anko 14

ケース4は、ケース3とマージすることもできます。追加情報を使用して、ボードの側面を使用して囲みます
ChargingPun

ボードの中央を上から下に縦に走る垂直線がある場合、ボードのどちら側が「囲まれている」でしょうか。
Steven Stadnicki 14年

とりあえず、最小のスペースは囲まれていると思います。OPが特に指定しない限り。
トム「ブルー」ピドック

回答:


3

1.タイルのループを検出する

この問題は、グラフのサイクル(ループ)を検出するのと同じように見えますここまたはここを参照しください

  • VそのグラフのノードのセットはG=(V, E)タイルです。
  • e = (v1, v2)タイルが直接または対角の隣接ノードである場合、エッジは2つの異なるノード間に存在します

2.画面枠ケースの取り扱い

画面の境界線は、目に見えるタイルの画面の周りに1タイル幅のリムを形成する架空のタイルで構成されています。

あなたの仕様によると、画面の境界の部分は、閉じたループの暗黙の部分を形成します。閉じたループを検出するには、次のルールによる接続を尊重Gしてグラフをグラフに拡張するだけで十分G'です。

  • 2つのタイルがそれぞれ画面の境界のすぐ近くに配置されている場合、2つの異なるノード間に別のエッジが存在します

したがって、(0,0)と(1,0)のタイルは、「ボーダータイル」(-1,0)、(-1、-1)、(0、-1)とともに、閉じたループの一部になります。 、(1、-1)。

3.ループ領域の内側

私は、ユーザーのArthur Wulf Whiteが提案したのと同じような方向に進みます。

ループタイルの境界ボックスで調べる必要があるタイルのセットを制限します。

次に、塗りつぶしを使用して、閉じたループの外側または内側の境界ボックス内のすべてのタイルを選択します。それは、これらの2つのケースのうちの1つだけです。後で確認する必要があるのはどれですか。

境界ボックスを各方向に1タイルずつ拡張することも良い考えですextbb。これにより、が生成されるので、外部タイルで塗りつぶしを開始した場合に備えて、1つの接続された外部ポイントのセットができあがります。

塗りつぶし領域を取得したら、その境界ボックスも計算しますffbb。外部タイルから始めた場合、それは拡張ループバウンディングボックスと同一である必要があります。

ffbb == extbb

内側のタイルから始めた場合、ループタイルは両方の境界ボックスの間に挟まれる必要があるため、明らかに小さい境界ボックスが生成されます。

ffbb < extbb

塗りつぶしの最初の開始タイルextbbは、フリータイルである任意のタイルにすることができます。ランダムに1つを選ぶのが最善の方法かもしれません。

以前に内部が外部よりも小さいことがわかっている場合は、ループポイントの重心の周りから始めます。ループポイントは、多くの領域の内部にあります(反対の例:C形状の領域)。それ以外の場合は、の境界ですextbb。しかし、これをどのように見積もるかはわかりません。

最後の発言

通常、私はいくつかのタイルから開始し、アクセスしたタイルのリストを保持するだけの単純なウォークでサイクルを検出するのに十分であると言いますが、その画面境界条件はより複雑なグラフを生成する可能性があるため、グラフアルゴリズムを使用して安全な側にいる必要があります。

以下は、内部が接続されていない例です。一方、サイクル検出では2つのループが検出され、1つは破棄されます。

ある場合


1

これは次の方法で解決できます。

  1. その形状の境界ボックスを見つけます。
  2. 各方向にサイズを1ずつ増やします。
  3. 新しいわずかに拡大された境界ボックスのフレームを反復処理し、塗りつぶしを適用します。
  4. そのチェーン上にない塗りつぶしでマークしていないタイルがある場合、それらは囲まれます。あなたの定義では、囲まれたタイルがある場合、形状は閉じた図形であると思います。

チェーン上のすべてのタイルの上で1つ、反復を行うと見つける彼らのためにminXminYmaxXそしてmaxYそれはあなたのバウンディングボックスまたはAABBです。

2つは簡単です。

フレームの繰り返し処理は簡単です。グリッドの外側に塗りつぶさないようにしてください。ウィキペディアで塗りつぶしの方法を学ぶことができます。

4番目の場合、チェーンに隣接するタイルのみをチェックすることから開始できます。マークされていないタイルを見つけて、さらにタイルを見つけるために塗りつぶすことができます。


0

ユーザーが既に選択したタイルをユーザーが選択しようとするとすぐにチェーンが終了すると想定すると、あなたの直感は正しいです。その場合、あなたの写真では、形状は一般的に投げ縄のように見えます(4)。スワイプを続けることができる場合、彼らは多くのループを描くことができ、物事はより複雑になります。あなたがしたいことは、多角形の質問に答えることです。

まず、問題を定義する必要があります。状況が(2)のように見えると想定します。つまり、すべてのテールが取り除かれ、最後が最初に戻り、各タイルがチェーン内に正確に「先行」と「後続」を1つずつ持つようにします。 (タイルXの後継の先行モデルは常にタイルXです)。さらに、「継承者」を十分に長くフォローすると、最終的には元の場所に戻ります。Gurgadurgenの提案を使用して、ループが実際に任意の時点で元に戻るかどうかを検出できます。終了時にユーザーの入力を終了すると想定すると、それは、一連のノードの一連のノードのように見え、その後にループが続きます。ループを取り除いてラインを取り除くことができます。

次に、各行について次のことを行います。

  1. 左端から開始し、各タイルのブール値を追跡して、INかOUTかを確認します。始める。
  2. 現在のタイルがチェーンの一部である場合は、後続と先行(両方が隣接している必要がある)の両方を確認します。どちらかが真上にある場合(つまり、現在のタイルの北、北東、または北西)、現在のタイルの状態を、左側のタイルの反対側に設定します。それ以外の場合は、左側のタイルと同じに設定します。後藤4。
  3. 現在のタイルがチェーンの一部でない場合は、タイルを左側のタイトルの状態に設定します。後藤4。
  4. 右側のタイルが現在のタイルになります。後藤2。

次に、INであるすべてのタイルを取り、境界のタイル(以前にそれを削除したかどうかにかかわらず、尾を含む)を追加し、その領域を呼び出します。

ユーザーがボーダーを使用できるようにしたい場合は、これがボード上のIN / OUTを定義するのではなく、2つの部分に分割するだけであることに注意してください。たとえば、小さい領域を選択したり、隣接する2つの辺(つまり、左と下、ただし上/下または左/右ではない)を使用するようにユーザーに要求できます。

最適化は、境界を含む行のみを実行する必要があることです(側面を使用できない場合)。私はあなたのボードは十分に小さいので、すべてのタイルを繰り返し処理し、非常に単純な計算を行うことは、最も弱いモバイルシステムであっても問題にはならないと思います。(結局のところ、レンダリングする必要がありますが、これはタスクのはるかに複雑です)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.