ランダムといえばやっぱり乱数
.NETには、ざっくりと言うと、「とりあえず乱数を生成するクラス」と、「より厳密な乱数を生成するクラス」が用意されております。
具体的には、System.Randomクラスと、System.Security.Cryptography.RNGCryptoServiceProviderクラスです。
ここでは、それほど厳密な乱数は必要ないので、System.Randomクラスを使用しています。
System.Randomクラスは、シード値を指定するコンストラクタと、指定しないコンストラクタが用意されております。
シード値を指定しない場合には、Environment.TickCount(システム起動後のミリ秒単位の経過時間)がシード値として使用されます。
System.Randomクラスは、シード値が同じであれば全く同じ乱数(乱数と言ってよいかは不明)を返しますので、一回の処理の中で複数回使用する場合にはシード値を変える必要があるかと思います。
次のような具合にシード値を指定すると、手っ取り早いです。
var __seed = Environment.TickCount;
var __rnd1 = System.Random(__seed++);
var __rnd2 = System.Random(__seed++);
また、乱数を連続して生成する場面では、同じ数字を何度も生成してよい場合と、一度しか生成したくない場合とがあります。
System.Randomクラスは、同じ数字を何度も生成しますので、同じ数字を一度しか生成したくない場合は、System.Collections.Generic.Listクラスなどの配列を用いるとよいです。
そしてたぶん、次の関数をコピペして使っていただく方法が、最も手っ取り早い方法になるのかなと。
static int[] __GetRandomNumbers(int _minValue, int _maxValue, int _numbers, int _seed)
{
return __GetRandomNumbers(_minValue, _maxValue, _numbers, _seed, true);
}
static int[] __GetRandomNumbers(int _minValue, int _maxValue, int _numbers, int _seed, bool _repeat)
{
if(_maxValue < _minValue)
{
var __temp = _maxValue;
_maxValue = _minValue;
_minValue = __temp;
}
if (!_repeat && _numbers > _maxValue - _minValue + 1)
_numbers = _maxValue - _minValue + 1;
var __ret = new int[_numbers];
var __rng = new System.Random(_seed);
if (_repeat)
{
for (var i = 0; i < __ret.Length; i++)
__ret[i] = __rng.Next(_minValue, _maxValue);
}
else
{
var __mother = new System.Collections.Generic.List<int>();
for (var i = _minValue; i <= _maxValue; i++)
__mother.Add(i);
for (var i = 0; i < __ret.Length; i++)
{
var __index = __rng.Next(0, __mother.Count);
__ret[i] = __mother[__index];
__mother.RemoveAt(__index);
}
}
return __ret;
}
_repeatにtrueを渡すと同じ数字を何度も生成する乱数になり、falseを渡すと同じ数字を一度しか生成しない乱数になります。
なお、発生したい乱数の範囲が狭い場合(例えば、0か1かを繰り返し発生させる場合など)に、発生する数字が著しく偏るようです(何度やっても0ばかり出る、みたいな・・・)。
範囲が狭いときには、乱数としては幅広く(0~99とか)発生させておきつつ、剰余を取って目的の範囲に収めてあげると、うまくいきました。
QueryStringを含むURLを簡単に生成するには
今回、パラメータを渡す方法としてQueryStringを採用したわけですが、URLに続けて「?hoge=fuga&aaa=bbb」といった文字列を生成するのって、エンコードとかいろいろ神経を使うものです。
そんな悩みを一発で解決する方法が、ASP.NETに用意されております。
var __query = System.Web.HttpUtility.ParseQueryString(string.Empty);
__query["hoge"] = "hoge";
__query["fuga"] = "fuga";
__query["aaa"] = "bbb";
__query["hensu_x"] = x;
__query["hensu_y"] = y;
var __urlWithQueryString = "test.aspx?" + __query.ToString();
という、嘘のようなホントの話です。
最後に、一度訪問したURLを指定するとWebブラウザはキャッシュを読みにいきますので、可変画像なのに変わらない!という事態に直面することになります。
URLの中に、たとえば、DateTime.Now.Ticks.ToString()を含めておくとよいでしょう。