2

私は現在、ac# バージョンのメモリ (ゲーム) を作成しています。現在、カードをシャッフルするメソッドを作成する必要があります。私はこのようなものを持っています(しかし、まだ機能していません):

    public void shuffle()
    {
        for (int i = 0; i < 100000; i++)
        {
            Random k = new Random();
            Random k2 = new Random();

            kaarten[k.Next(0, 11)] = kaarten[k2.Next(0,11)];
            kaarten[k2.Next(0, 11)] = kaarten[k.Next(0, 11)];
        }
    }

誰かが私を助けてくれるのではないかと思ったので、よろしくお願いします!スティーブン。

4

5 に答える 5

3

カードkaartenList表す何かの

public void Shuffle()
{
    // Insert cards at random order into the shuffled list
    var shuffled = new List<Card>();
    var rand = new Random();

    // As long as there are any cards left to insert randomly
    while (kaarten.Count != 0)
    {
        // Get the index of the random card to insert
        var i = rand.Next(kaarten.Count);

        // Insert it
        shuffled.Add(kaarten[i]);

        // Remove from non-shuffled list
        kaarten.RemoveAt(i);
    }

    // Set the list of cards to the shuffled list
    kaarten = shuffled;
}

現在のコードの問題:

ランダムをローカル変数に保存しないため、それらを交換しようとすると、実際には2つのランダムではなく4つのランダムがあります。

また、配列内の 2 つの要素を交換するには、tmp 変数を使用する必要があります。これは、Swap アルゴリズムで見られるほとんどすべての場所で見られます。

ただし、完全なシャッフルの場合、私のアプローチでは、十分なシャッフルのためにスワップをループする回数を決定する必要がなくなるため、より効率的で理解しやすくなります。

リストをシャッフルする別の方法があります。これは少しわかりにくい (そして効率が悪い) ですが、必要に応じて短くなります。

var rand = new Random();
kaarten = kaarten.Select(x => new{X=x,R=rand.Next()})
                 .OrderBy(x => x.R)
                 .Select(x => x.X)
                 .ToList();
                 //.ToArray(); if kaarten is an array and not a list
于 2013-06-15T10:06:54.860 に答える
2

コードの最初の大きな問題は、 の 2 つのインスタンスを作成していることですRandom。のくだらないシードはnew Random()、それらのインスタンスがまったく同じシーケンスを返す可能性が最も高いことを意味します。

new Random()Environment.TickCount数ミリ秒ごとにのみ変化するシードを使用します。したがって、 の 2 つのインスタンスをRandom立て続けに作成すると、時間が同じになり、同じシーケンスが出力されます。

適切な解決策は、最初に のインスタンスを 1 つだけ作成Randomし、すべてのランダム性のニーズに対して if を使用することです。マルチスレッドには注意してください。 のインスタンスはRandomスレッドセーフではありません。

また、 の上限random.Nextは排他的であるため、コードは 11 要素の配列でのみ機能することに注意してください。値をハードコーディングするのではなく、コレクションのサイズを使用することをお勧めします。

コードのもう 1 つの問題は、適切なスワップを実装していないことです。スワップするには、スワップに 2 つの問題があります。2 番目の方向に新しいインデックスを使用しており、ローカル変数に一時コピーを作成して、元の値ではなく上書きされた値を読み取らないようにする必要があります。

これらの問題を修正すると、コードは次のようになります。

Random random = new Random();//one persistent instance

public void shuffle()
{
    for (int i = 0; i < 100000; i++)
    {
        var i1=random.Next(kaarten.Count);
        var i2=random.Next(kaarten.Count);

        var temp=kaarten[i1];
        karten[i1]=kaarten[i2];
        karten[i2]=temp;
    }
}

とはいえ、100000 回反復するため、アプローチは少し非効率的です。標準的なシャッフル アルゴリズムは、Jon-Skeet がIs using Random and OrderBy a good shuffle algorithm?で説明している Fisher-Yates シャッフルです。.

于 2013-06-15T10:08:46.920 に答える
1

まず、Swap と呼ばれる便利な拡張メソッドを使用できます。

public static void Swap<T>(this IList<T> source, int one, int two)
{
    T temp = source[one];
    source[one] = source[two];
    source[two] = temp;
}

これで、コードは簡単になります。

public void Shuffle()
{
    int count = kaarten.Count;
    Random rnd = new Random();
    for (int i = 0; i < 1000; i++)
    {
        kaarten.Swap(rnd.Next(0, count), rnd.Next(0, count));
    }
}
于 2013-06-15T10:08:19.640 に答える
1

フィッシャー・イェーツ・シャッフル

ステップ 1. 山札からランダムにカードを 1 枚引く

step 2. 新しいデッキに入れる

ステップ 3. デッキが空でない場合は、1 と 2 を繰り返します

これをクラスに追加します

public List<Card> Shuffle(List<Card> deck){
    List<Card> Shuffeled = new List<Card>();
    int deckSize = deck.Count;
    int selection = 0;
    Random rand = new Random();
    for(int i = 0; i < deckSize; i++){
        selection = rand.next(deck.Count-1);
        Shuffeled.Add(deck[selection]);
        deck.RemoveAt(selection);
    }
    return Shuffeled;
}

ゲームコールからkaarten = Shuffle(kaarten);

于 2013-06-15T10:36:57.220 に答える
1

配列リストの要素をシャッフルします

public void Shuffle(System.Collections.ArrayList elements)
    {
        int temp;
        Random randomNumber=new Random();
        for (int n = elements.Count; n > 1; )
        {
            int k = randomNumber.Next(n); //returning random number less than the value of 'n'
            --n; //decrease radom number generation area by 1 
            //swap the last and selected values
            temp = Convert.ToInt16(elements[n]);
            elements[n] = elements[k];
            elemetns[k] = temp;
        }
    }
于 2013-06-15T10:14:03.957 に答える