8

問題グリッド (2D 配列) をランダムな形状の部分 (地球の構造プレート
と考えてください) に分割したいと考えています。

基準は次のとおりです。

  • ユーザー入力グリッド サイズ (これは非常に大きくなる可能性があるため、プログラムはスケーリングする必要があります)。
  • ユーザーがグリッドの分割係数 (パーツの数) を入力します。
  • Grid は長方形の 16 進グリッドで、上下にキャップがあり、左右に回り込みます。
  • パーツの分解はありません。
  • 他のパーツの中にパーツはありません。
  • 極小部品や超大型部品はありません。
  • 真円でないランダムな形状のパーツ、または伸びた蛇行形状。

私の解決策:

  • 隣接するセルにアクセス/操作できるメソッドを作成します。
  • 各パーツのサイズをランダムに決定します (すべてのパーツの合計が 2D 配列全体のサイズに等しくなります)。
  • 2D 配列全体を最後の部分の ID 番号で埋めます。
  • 最後の部分を除く各部分について:
  • 2D 配列のランダムなセルに現在のパーツ ID 番号をシードします。
  • 配列全体を反復処理し、現在のパーツ ID 番号で既にシードされているセルに隣接する各セルのアドレスを格納します。
  • 保存されているアドレスの 1 つを抽出し、そのセルに現在のプレート ID 番号を入力します (したがって、パーツが形成され始めます)。
  • 部品サイズに達するまで繰り返します。

長く伸びた「腕」や内部に大きな穴があるパーツを避けるために、2 つのストレージ アレイを作成したことに注意してください。それから私は前者の前に後者を使い果たします。

私のソリューションを実行すると、次のようになります:
グリッド サイズ: 200
幅: 20
高さ: 10
パーツ: 7

66633333111114444466
00033331111114444466
00003331111114444466
00003331111144444660
00000333111164444660
00000336111664422600
00000336615522222200
00006655555522222200
00006655555552222220
00066655555552222220

品番:0
品番:47

パーツ数:1
パーツサイズ:30

パーツ数:2
パーツサイズ:26

パーツ数:3
パーツサイズ:22

パーツ数:4
パーツサイズ:26

パーツ数:5
パーツサイズ:22

パーツ数:6
パーツサイズ:27

私の解決策の問題:

  • 最後の部分は常に断片化されています。上記の場合、6 の 3 つの別々のグループがあります。
  • パーツが袋小路で形成され、フルサイズに成長する余地がない場合、アルゴリズムは停止します (アルゴリズムは、他のパーツの上にパーツを形成することを許可しません。開始時の 2D 配列)。
  • 2D 配列を形成する前にパーツ サイズを指定せず、パーツの数を指定してその場でパーツ サイズをランダムに生成するだけで間に合わせると、小さなパーツが形成される可能性が残ります。特に 2D 配列が非常に大きい場合は特にそうです。現在のパーツ サイズの方法では、パーツ サイズを 2D 配列の合計サイズの 10% から 40% に制限しています。これを行うための非常にエレガントな方法があれば、パーツのサイズを指定しなくても大丈夫かもしれません - ユーザーが持つ唯一の制御は、2次元配列のサイズとパーツの数です。

その他のアイデア:

  • パーツを完全に整列した正方形に形成し、2D アレイを実行して、各パーツが他のパーツにランダムに侵入し、ランダムな形状に変形させます。
  • グリッドを横切る蛇行を描き、作成されたスペースを埋めます。おそらく次のような数学を使用します: http://mathworld.wolfram.com/PlaneDivisionbyLines.html

結論:
ここに問題があります: 私は初心者プログラマーで、この問題に正しい方法で取り組んでいるかどうか確信が持てません。断片化されたパーツを一緒に移動し、成形パーツが袋小路に詰まった場合に袋小路から「飛び出す」ことを可能にする「パッチアップ」メソッドをさらに作成できますが、面倒です。

この問題にどのように取り組みますか? おそらく物事を単純化するために使用できるセクシーな数学はありますか?

どうも

4

3 に答える 3

5

数か月前のゲームでも同様のことをしましたが、それは六角形のグリッドではなく長方形のグリッドでした。それでも、理論は同じであり、ほぼ同じサイズの素敵な隣接領域を考え出しました。大きいものもあれば小さいものもありますが、小さすぎたり大きすぎたりするものはありませんでした。YMMV。

  1. グリッド内のすべてのスペースへのポインターの配列を作成します。アレイをシャッフルします。
  2. それらの最初のN個のID(1、2、3など)を割り当てます。
  3. 配列がIDを持たないスペースを指さないまで、
  4. IDを持たないスペースを探して、配列を反復処理します
  5. スペースにIDを持つ隣接がグリッドにある場合は、隣接するIDの重み付けされたランダムな選択からスペースにIDを割り当てます。
  6. IDを持つネイバーがない場合は、次へスキップします。
  7. 空でないスペースがなくなると、十分に膨らんだエリアのあるマップができあがります。
于 2010-08-05T15:27:10.233 に答える
3

これが私がすることです:ボロノイアルゴリズムを使用してください。最初にいくつかのランダムな点を配置し、次にボロノイアルゴリズムにパーツを生成させます。どのように見えるかを知るには、このアプレットを参照してください。

于 2010-08-05T15:22:10.843 に答える
1

Rekin が示唆したように、Voronoi ダイアグラムといくつかのランダムな摂動は一般的にうまく機能し、あなたが持っているような離散化された空間では比較的簡単に実装できます。

ランダムな摂動を行う方法についていくつかのアイデアを提供したかっただけです。最終的な解像度でそれを行うと、非常に長い時間がかかるか、最小限に抑えられます。多重解像度の摂動を試してみてください。したがって、かなり小さなグリッド、ランダムシードから始めて、ボロノイ図を計算します。次に、境界をランダムに摂動させます。たとえば、異なる領域を持つ隣接するセルの各ペアに対して、領域をいずれかの方向に押し込みます。小さな島がないことを確認するために、後処理を実行する必要がある場合があります。単純なフラッドフィルが機能します。

次に、(各方向に) 2 倍のサイズのグリッドを作成し、領域をコピーします。おそらく最近傍を使用できます。次に、境界を再び乱し、目的の解像度に達するまで繰り返します。

于 2010-10-01T12:29:46.400 に答える