web-dev-qa-db-ja.com

マインスイーパ解法アルゴリズム

マインスイーパゲームについては、ほとんどの人が知っていると思います。私は自分のマインスイーパゲームを(C#で)コーディングしたいと思っていて、そのゲームに適したアルゴリズムとは何かに関する情報を探していました。私はかなり長い間Webを閲覧してきましたが、良い解決策を見つけることができませんでした。誰かがそれを手伝ってくれる?

19
Saurabh Lalwani

グリッドの生成は簡単です。プレーヤーの移動を実行するときに必要ないくつかの単純なアルゴリズムがあり、どのマスを開くかを決定し、それらが負けたか勝ったかを決定します。

グリッドを生成する

最も単純なアルゴリズムは、すべての地雷をランダムに配置することです。 (重複しないように注意してください!)

問題:プレーヤーの最初のクリックは地雷かもしれません。

改善:ユーザーが最初の正方形をクリックするまでグリッドの生成を遅らせ、その正方形に地雷を置かないようにしました。

問題:プレーヤーの最初のクリックでゼロ以外の数値が表示されることがある、そして何かが開くまでランダムにクリックすることを強制されます。

改善:最初のクリックの周囲の(最大)8つの正方形に地雷を生成しないようにします。

問題:プレイヤーはある時点で推測を強いられるかもしれませんが、これを論理パズルの悲しい言い訳にしています。

改善: ソルバーを実行する ジェネレーターと一緒に、 パズル に一意のソリューションがあることを確認します。これにはある程度の賢さが必要であり、ほとんどのバリアントでは実行されません。

あいまいさを解決するもう1つの一般的ではない方法は、プレイヤーが等しく可能性の高い可能性の中から選択していることを検出し、決定した位置に「波形を折りたたむ」ことです。私はこれを実際に見たことがありませんが、それはちょっと楽しいでしょう。

ゲームをする

フラグをマークすることに加えて、プレイヤーは2種類の動きを行って、正方形を明らかにしようとすることができます。

  • 単一の推測:プレーヤーは状態が不明でフラグのない正方形をクリックします。正方形を明らかにし、プレイヤーが死亡したかどうかを確認し、そこに数字を入れます。正方形に0が含まれている場合は、周囲のすべての正方形に対してこれを再帰的に繰り返します。これは、GUIのイベントハンドラーから分離するため、再帰を容易にするため、および複数の推測で再利用されるため、専用の関数にする必要があります。

  • Multiguess:プレイヤーは、覆われておらず安全であることがわかっている正方形をクリックします。周囲のフラグの数がこの正方形の数と等しい場合は、上記と同じ手順を使用して、フラグの付いていない正方形を開きます。

ゲームに勝つ

覆われているマスの数が地雷の数と同じである場合、マス目すべてにフラグを付けていなくても、プレイヤーは勝利します。

プレーヤーが負けた場合、通常、彼らが行った不正確な推測、残りの地雷、および彼らが踏んだ地雷をマークします。

50
Josh Lee

ソルバーを作成する場合は、以下を追加するだけです- マインスイーパはNP complete(Archive Link) 。つまり、誰かが証明するまで P = NP 状況によっては、ブルートフォース検索を実行するよりも優れた方法がある可能性があります(ただし、ゲームがそうでない場合もありますNP小さなフィールドでは完全です)。

5

これが私の掃海艇ソルバーです:

  • 各数字の正方形:
    • 未開封の数==平方数の場合:それらはすべて地雷です
    • 平方数の場合-フラグ付きのカウント== 0:未開封のすべてが地雷ではない
  • サブセットルールを使用

これは実際の実装です。説明が難しいサブセットルールを使用していることに注意してください https://github.com/SHiNKiROU/Minesweeper/blob/master/src/org/shinkirou/minesweeper/MinesweeperSolver.Java# L27

もちろん、私のアルゴリズムは時々失敗する可能性があります。 Prologスタイルのバックトラックソルバーを実装する予定です。

3
Ming-Tang

これを確認してください: http://quantum-p.livejournal.com/19616.html

サルの推論では直感的に解決できないボード上の任意の位置は、より良い解決率につながる可能性があるいくつかの個々(または全体の位置)の正方形を解決できる行列です。単純なランダム推測では良い結果は得られませんでした。方程式ソルバーの線形システムを追加することにより、C++の解法アルゴリズムにこのメソッドを実装しました。マインスイーパの難しさを調査しています。アルゴリズムを使って何万ものゲームを実行し、統計を行っています。

私のアルゴリズムは(9,9,10)の簡単なレベルの掃海艇の最大85%を解決します。私はまだ他の難易度レベルで完全なテストを実行していませんが、より小さなテストでは、中レベル(16、16、40)の解答率が55-60%で、ハードレベル(30、16、99)が5と低いことが示されています-10%。私はそれを最も最適にするいくつかの新しいものを追加します。

2
Henri

アンリが述べたように、マインスイーパを解く正しい方法は、数学、特に決定論的な部分の線形代数行列数学です。私はここに全体の投稿があります:

  • その方法がどのように機能するかを説明します
  • 任意のプラットフォームでコンパイルおよび実行できる作業コードがあります
  • ゲームを作成するためのコードとソルバーも含まれています

あなたはここですべてを見ることができます: https://massaioli.wordpress.com/2013/01/12/solving-minesweeper-with-matricies/

それを読んでから、よく考えてみることをお勧めします。 Minsweeperの確率論的部分も統計を使用して解決できますが、まだそのための良い計画はありません。しかし、他の人々もそれを調べました。

2

私はマインスイーパの専門家ではありませんが、解決しようとするときに使用するアルゴリズムは次のとおりです。

明らかにされた領域の境界であるすべての正方形の上に行きます。これらの四角のそれぞれについて、隣に公開した地雷の数を数えます。 正方形に書かれている数(周囲の地雷の本当の数)を引きます。 この正方形の周りに残っている未公開の地雷の数です。 現在の四角形の周りにある非表示の四角形の数で割ります。それは地雷を含む隣接する各正方形の確率です。正方形の確率が1の場合、それを地雷としてマークします。正方形の確率が0の場合、その正方形を安全であるとマークします。次に、関連する番号を更新します。

正方形の確率が0または1でない場合はどうしますか?最適なアルゴリズムでは、複数の正方形からの制約が考慮されます。しかし、最初に書いたように、私は掃海の専門家ではないので、0または1に最も近い確率を持つ他の正方形からランダムに選択します。

2
Ofri Raviv

コメントは、ゲームを構築するのにアルゴリズムは必要ないということです。私はあなたが解くという意味でのアルゴリズムを意味していると私は信じています。

ただし、問題の解決策はアルゴリズムと見なすことができます。

ほとんどの数学の問題と同様に、解くのに十分な小さいものになるまで、アルゴリズム全体をより小さく複雑でないアルゴリズムに分解できます。これにより、最初の正しい解決策が得られます。後で、アルゴリズム全体のコンテキストで小さなアルゴリズムを最適化できます。

ゲームボードは、2次元配列と考えることができます。各操作に関連付けられたアルゴリズムがあります。最初の操作はおそらく、ランダムに生成された地雷の数とボードのサイズのパラメーターを持つx、y座標を持つ地雷の位置のセットです。あなたは、ボードと場所を取り、それに隣接する鉱山の数を決定する、正方形の公開に関連する別のアルゴリズムを持っているでしょう。最後のアルゴリズムはボードを取り、地雷のない正方形が残っているかどうかを確認します。

これで、これらの各アルゴリズムを使用して、パフォーマンスを向上させるために各アルゴリズムを最適化して、「x、y座標を使用して2次元配列が与えられた場合、現在の正方形に隣接する地雷のある正方形をカウントする最良の方法は何ですか?」.

2
Sam

ゲームのこのC#実装 を見たことはありますか?ソースコードはダウンロード可能で、オブジェクトモデルが説明されています。

1
Konamiman