2012-05-01 6 views
0

リストのランダム要素の値にアクセスしようとしています。現時点では、コードは値ではなく要素を返すようです。現時点ではリストのランダム要素の値にアクセスするC#

int x = _randMoveDecider.Count; 

//makes sure x is never more than the array size 
if(x != 0) 
    { 
    x = x - 1 ; 
    } 

Random _r = new Random(); 

_move = _r.Next(_randMoveDecider[x]); 

return _randMoveDecider[_move]; 

_randMoveDeciderは値2、5と9を保持している場合、それは私が間違っているつもりだところ、リスト中の0、1または2ではなく、値を返すのだろうか?

[編集]私は、_randMoveDeciderの長さとそれに格納されている値は、プログラムの実行ごとに変わったはずですが、それらは常に整数です。

+0

??? –

+0

値は変わりますが、常に整数です。 –

答えて

2

まず、ランダムを一度初期化する必要があります。フィールドにする:

private Random _rand = new Random(); 

次に適切な範囲から乱数を取得します。 numbersform < 0、n)を返します。次の()の範囲

return _randMoveDecider[_rand.Next(_randMoveDecider.Count)]; 
+0

@yamen No. docから "指定された最大値より小さい非負の乱数を返します。" –

+0

はい、私はそれが最大排他的で、削除されたコメントであることに気づいた。 – yamen

3

どうちょうどこのことについて - (!xは= 0)が役に立たない場合は?

// make this a field or something global 
public IEnumerbale<int> randomiser = Randomise(_randList); 

// then later 
return randomiser.First(); 
+0

-1。私はいつも乱数を作成すると、時間が変わるまで伝統的に同じ値が返されます。 –

+0

@AlexeiLevenkov私は2番目のコードセットで固定されていました。これは-1ではありません。 – yamen

+0

2つのリストのランダム化を作成し、その結果の「ランダム化された」シーケンスを比較すると、ほぼ同じようにランダム化されていることがわかります。その結果、擬似ランダムシーケンスが高い確率で同一であるため、各シードについて同じシード(ほぼ同じ時刻に呼び出された場合、つまり次のラインにある場合)で初期化されたランダムを作成しています。 –

1

は単純にメインクラス内でこの拡張クラスを追加します。あなたのシナリオでは、それを使用しての

public static Random _rand = new Random(); 

public IEnumerable<T> Randomise<T>(IList<T> list) 
{ 
    while(true) 
    { 
     // we find count every time since list can change 
     // between iterations 
     yield return list[_rand.Next(list.Count)]; 
    } 
} 

一つの方法:

// as a field somewhere so it's initialised once only 
public Random _r = new Random(); 

    // later in your code 
var _randList = new List<int>{4,5,8,9}; 
var _move = _r.Next(_randList.Count); 
return _randList[_move]; 

さらに良いことに、ここでは任意のリストをランダム化します何かがあります:

public static class Extensions 
{ 
    public static int randomOne(this List<int> theList) 
    { 
     Random rand = new Random(DateTime.Now.Millisecond); 
     return theList[rand.Next(0, theList.Count)]; 
    } 
} 

int value = mylist.randomOne(); 

EDIT:このメソッドをどのように使用するかを示すテストプログラムです。ランダムの誤った使用のために、それは100のうちの50以上の "ランダムな"数字が同じである、非常にアンバランスな結果を生成することに注意してください。

class Program 
{ 
    static void Main(string[] args) 
    { 
     var myList = Enumerable.Range(0, 100).ToList(); 
     var myRandoms = myList.Select(v => new { key = v, value = 0 }) 
       .ToDictionary(e => e.key, e => e.value); 

     for (int i = 0; i < 100; i++) 
     { 
      var random = myList.RandomOne(); 
      myRandoms[random]++; 
     } 

     Console.WriteLine(myRandoms.Values.Max()); 
     Console.ReadLine(); 
    } 
} 

問題を修正するには、Extensionクラスのランダムスタティックインスタンスを作成するか、プログラム内でより広く共有します。これはFAQ for Randomで議論されています。 randMoveDeciderにあるもの

public static class Extensions 
{ 
    static Random rand = new Random(); 
    public static int randomOne(this List<int> theList) 
    { 
     return theList[rand.Next(0, theList.Count)]; 
    } 
} 
+0

-1。これは、Randomクラスを使用しない方法の正確なコードです。 –

+0

これは以前に試しましたか? –

+0

しました。拡張機能の修正を含む編集のサンプルを参照してください。 –

0
var random = new Random(); 
var item = list.ElementAt(random.Next(list.Count())); 
+0

あなたは直接list indexer 'list [index]'を呼び出すことができます。これは、いくつかのチェック、キャスト、そして最後にコールリストインデクサーを行う拡張メソッドを呼び出すことなく行います。 –

+0

私はこれを意図的に行いましたが、あなたの意見を見ることができます。私はIEnumerableインターフェイスにプログラミングしていたので、このようにしました。具体的な型ではありません。 http://stackoverflow.com/questions/5326874/why-would-i-use-enumerable-elementat-versus-the-operatorポスターがIListを使用する場合、メソッド呼び出しよりもオーバーヘッドはほとんどありません(元のポスターはデータ型を指定していないことにも注意してください)。 – Sprague

関連する問題