2012-04-20 5 views
2

私は次元(8 x 8)のC#で鉱山スイーパーゲームを開発しています。難易度はグリッド上の鉱山の数を増減します。Mine SweeperのC#で繰り返されない乱数Game

私はランダムなセル番号を生成するために、ランダムなクラスを使用します(私は直面している問題は、ランダムなオブジェクトは同じ番号を繰り返し続けます。私はこの問題をローカルリストがどこに生成された一意の乱数を格納しているかを示します。次にNext()を呼び出すと、ローカルリストと照合して、すでに存在しているかどうかを確認します。一意であり、リストに存在しない新しい番号を取得します。しかし、これは、新しいリストを生成するのに苦労することがあるので、それ自体は良い解決策に見えません。あなたのグリッドが8×8であり、あなたは未使用のものを打つまで、ランダムに乱数を引っ張っするのではなく、未使用のセルを選択したい場合は、この上の

任意の提案は

+4

コードを見る必要があります。 Minesweeper配置アルゴリズムのほとんどは、番号付きの四角形を生成しません。鉱山を生成し、鉱山の位置に基づいて数値を計算します。 – BoltClock

+1

あなたはおそらくあなたが生成する数字のためにランダムの新しいインスタンスを作成しています... –

+0

コードを見ることなく、物事の要点を得るのは難しいですが、私はあなたが次のことを伝えることができます: マルチ次元配列[8] [8]ゲームのグリッドレイアウトのために、あなたは現在ランダムに鉱山を配置しようとしていますか? –

答えて

1

シャッフルは固定数のセル(8,8)に基づいています。 a Fisher-Yates shuffle。これは、任意の座標が(同じ番号を何度も描くことができるRandom.Next()を繰り返し使用するのではなく)正確に1回だけ表示され、座標の出現順序がランダム化されることを保証します。

セルのすべての座標を含む配列を初期化し、配列をシャッフルして次の "ランダム"セルのインデックスを維持し、セルをインデックスのオフセットで返し、インデックスを増やします。

+0

私は64の要素のint []配列をシャッフルし、1から始まる値を持つ別の方法で試しました。64.iはランダムなクラスを使用して2つの一意の数値(インデックス)を選びました私は配列要素を数回入れ替えた後、最初のn個の要素(n =鉱山の数)をとりました。提案に感謝します。私はこれを見ていきます。 –

0

は、その後、未使用のセルの数を追跡してください。 8つは使用されており、55は使用されていません。その後、0と54の間の乱数を生成します。次に、カウントしてn番目の空のセルを見つけなければなりません。

-1
それは物事の要点を取得するために一種の難しい任意のコードを見ずに

、しかしから私はあなたが以下の持って言うことができるもの:

多次元配列[8] [8]のグリッドレイアウト用あなたは今、ランダムに鉱山を置こうとしていますか?

数字を生成するには、ランダムのインスタンスを1つ保持する必要があります。そうしないと、同じ番号が何度も何度も繰り返されます。このようなもの

private readonly Random randomNumber = new Random(); 

for(int i = 0; i < 10; i++) 
{ 
    Console.WriteLine(this.randomNumber.Next(1, 10)); 
} 

これは、それぞれ異なる10の乱数を生成します。

+0

これらは異なることが保証されていません。セット全体にわたって均一な分布を提供しようとする試み。 – Ian

+0

良い点は、OPはこのメソッドで生成された数値を配列に格納し、次に各数値がすでに存在するかどうかを調べることができます。 –

+2

@ LukeBerry:OPは、ローカルリストを使って問題を解決しているが、解決策は遅くなると言った。彼は代わりの解決策を求めた。 – Skalli

0

おそらく、より線形な方法で問題を考える方が簡単でしょう。代わりに2次元配列... Squares [8] [8]は、1次元配列Squares [64]と考える。

この時点で、ランダムな鉱山配置の場合は0〜63の数値が生成されます。値が10であるとすると、あとで番号をオフセットするために保存することができます。現在の範囲を0-62から減らすことができます。値16を引き出した場合は、既に値引きした値ごとに+1を加算することになります(この場合は実際には17を使用しますが、我々のセットから除外した)。

1

鉱山があるはずのスロットを選ぶのではなく、スロットをループしてそこに鉱山があるはずの確率を計算します。改善のための

bool[] mines = new bool[64]; 

int cnt = 12; 
Random rnd = new Random(); 
for (int i = 0; i < mines.Length; i++) { 
    if (rnd.Next(mines.Length - i) < cnt) { 
    mines[i] = true; 
    cnt--; 
    } 
} 

(ルーム:cntがゼロに達したときに、あなたがすべてのスロットを初期化する必要がない場合は、ループの外に出ることができ、あなただけの単一のループを必要とし、このための実装は、非常に簡単になります。)

1

最初に鉱山の数と空のフィールドを計算します。そして、各フィールドの

Random rand=new Random(); 
int mines=GetMinesFromDifficulty(...); 
int empty=TotalFields-mines; 

:あなたは同じ乱数ジェネレータを使用する場合でも

for(int y=0;y<height;y++) 
    for(int x=0;y<height;y++) 
    { 

    if(random.Next(mines+empty) < mines)) 
    { 
     field[x,y]=Mine; 
     mines--; 
    } 
    else 
    { 
     field[x,y]=Empty; 
     empty--; 
    } 
    } 
2

は、繰り返し値が可能です。

これを回避する方法の1つは、可能な値のリストを生成し、生成された乱数を使用してインデックスを使用してこのリストの値にアクセスし、このリストを減らすことです。

は8 X 8たとえば、あなたは、64個の可能な場所

List<int> possibleValues = new List<int>(); 
for (int i = 0; i < 64; i++) 
{ 
    possibleValues[i] = i; 
} 

List<int> result = new List<int>(); 

Random r = new Random(); 
int numberOfMines = 50; //say you want to put 50 mines there 

for (int i = 0; i < numberOfMines; i++) 
{ 
    int indice = r.Next(possibleValues.Count); 

    int value = possibleValues[indice]; 

    possibleValues.Remove(value); 
    result.Add(value); 
} 
+0

+1:私の答えと似ていますが、これはちょっとばっちりです... – Ian

関連する問題