ASP.net随机数应用实例
在.net Framework中提供了一個專門用來產(chǎn)生隨機(jī)數(shù)的類System.Random,使用這個類時必須導(dǎo)入System命名空間。當(dāng)然,命名空間System在每個ASP.net頁面中都是自動導(dǎo)入的,所以我們可以直接使用這個類。
對于隨機(jī)數(shù),大家都知道,計算機(jī)不可能產(chǎn)生完全隨機(jī)的數(shù)字,所謂的隨機(jī)數(shù)發(fā)生器都是通過一定的算法對事先選定的隨機(jī)種子做復(fù)雜的運(yùn)算,用產(chǎn)生的結(jié)果來近似的模擬完全隨機(jī)數(shù),這種隨機(jī)數(shù)被稱作偽隨機(jī)數(shù)。偽隨機(jī)數(shù)是以相同的概率從一組有限的數(shù)字中選取的。所選數(shù)字并不具有完全的隨機(jī)性,但是從實(shí)用的角度而言,其隨機(jī)程度已足夠了。偽隨機(jī)數(shù)的選擇是從隨機(jī)種子開始的,所以為了保證每次得到的偽隨機(jī)數(shù)都足夠地“隨機(jī)”,隨機(jī)種子的選擇就顯得非常重要。如果隨機(jī)種子一樣,那么同一個隨機(jī)數(shù)發(fā)生器產(chǎn)生的隨機(jī)數(shù)也會一樣。一般地,我們使用同系統(tǒng)時間有關(guān)的參數(shù)作為隨機(jī)種子,這也是.net Framework中的隨機(jī)數(shù)發(fā)生器默認(rèn)采用的方法。
我們可以使用兩種方式初始化一個隨機(jī)數(shù)發(fā)生器:
第一種方法不指定隨機(jī)種子,系統(tǒng)自動選取當(dāng)前時間作為隨機(jī)種子:
Random ro = new Random();
第二種方法可以指定一個int型參數(shù)作為隨機(jī)種子:
int iSeed=10;
Random ro = new Random(10);
之后,我們就可以使用這個Random類的對象來產(chǎn)生隨機(jī)數(shù),這時候要用到Random.Next()方法。這個方法使用相當(dāng)靈活,你甚至可以指定產(chǎn)生的隨機(jī)數(shù)的上下限。
不指定上下限的使用如下:
int iResult;
iResult=ro.Next();
下面的代碼指定返回小于100的隨機(jī)數(shù):
int iResult;
int iUp=100;
iResult=ro.Next(iUp);
而下面這段代碼則指定返回值必須在50-100的范圍之內(nèi):
int iResult;
int iUp=100;
int iDown=50;
iResult=ro.Next(iDown,iUp);
除了Random.Next()方法之外,Random類還提供了Random.NextDouble()方法產(chǎn)生一個范圍在0.0-1.0之間的隨機(jī)的雙精度浮點(diǎn)數(shù):
double dResult;
dResult=ro.NextDouble();
另外一個與Random.NextDouble()方法相似的方法是Random.Sample(),它跟Random.NextDouble()方法唯一的區(qū)別在于訪問級別,我們可以看看它們的原始聲明:
protected virtual double Sample();
public virtual double NextDouble();
Random.Sample()方法是保護(hù)方法,只允許子類的對象訪問,而Random.Sample()方法則可以看作是Random.Sample()的公開版本。一般地,用戶在Random的子類中重寫Sample()方法來得到更一般的分布。 這個例子中,我們使用Random.Next()方法來產(chǎn)生隨機(jī)數(shù)。
下面這個函數(shù)是這個例子的核心,我們利用他來產(chǎn)生一個隨機(jī)的int數(shù)組:
private int []GetRandomArray(int Length,int Up,int Down){ int iFirst=0; int []rtArray=new Int32[Length]; Random ro=new Random(Length*unchecked((int)DateTime.Now.Ticks)); iFirst=ro.Next(Up,Down); rtArray[0]=iFirst; for(int i=1;i
讀者或許都注意到了,我們采用了一種相當(dāng)麻煩的方式來產(chǎn)生這個隨機(jī)數(shù)組,為什么不簡單地使用如下代碼呢?請先看下面代碼,這里我們使用了系統(tǒng)時間作為隨機(jī)種子,連續(xù)獲取兩個隨機(jī)數(shù),并且將其輸出:
< %@ Page Language="C#" Debug="true" Trace="false" TraceMode="SortByCategory"% >< % @Import namespace="System" % >
< script language=C# runat=server >
public void Page_Load(object sender,EventArgs e){ int re=0; int re1=0; GetRandomDefault(ref re); GetRandomDefault(ref re1); RandomNum.Text=re.ToString(); RandomNum.Text+=" "+re1.ToString();}private void GetRandomDefault(ref int re){ Random ro=new Random(unchecked((int)DateTime.Now.Ticks)); re=ro.Next(10,20);}private void GetRandomByInt(ref byte []re){ Random ro=new Random(); ro.NextBytes(re);}
< /script >
< html >
< head >
< title >隨機(jī)數(shù)測試< /title >
< meta http-equiv="Content-Type" content="text/html; charset=gb2312" >
< /head >
< body bgcolor="#FFFFFF" text="#000000" >
< form runat=server >
< asp:Label id="RandomNum" runat=server / >
< /form >
< /body >
< /html >
下面是筆者機(jī)器上產(chǎn)生的結(jié)果的截圖:
是的,如你所見,產(chǎn)生了一樣的兩個隨機(jī)數(shù),無論重復(fù)多少次,都是一樣的。原因在哪里呢?
不要以為使用系統(tǒng)時間作為隨機(jī)種子就萬無一失了——如果應(yīng)用程序在一個較快的計算機(jī)上運(yùn)行,則該計算機(jī)的系統(tǒng)時鐘可能沒有時間在此構(gòu)造函數(shù)的調(diào)用之間進(jìn)行更改,Random 的不同實(shí)例的種子值可能相同。這種情況下,我們就需要另外的算法來保證產(chǎn)生的數(shù)字的隨機(jī)性。所以為了保證產(chǎn)生的隨機(jī)數(shù)足夠“隨機(jī)”,我們不得不使用復(fù)雜一點(diǎn)的方法來獲得隨機(jī)種子。
在上面的這段程序中,我們首先使用系統(tǒng)時間作為隨機(jī)種子,然后將上一次產(chǎn)生的隨機(jī)數(shù)跟循環(huán)變量和一個與系統(tǒng)時間有關(guān)的整型參數(shù)相乘,以之作為隨機(jī)種子,從而得到了每次都不同的隨機(jī)種子,保證了產(chǎn)生足夠“隨機(jī)”的隨機(jī)數(shù)。
得到整型的隨機(jī)數(shù)組以后,我們將它變成字符串,然后使用System.Drawing中與GDI+相關(guān)的類生成一個圖片并且在網(wǎng)頁上顯示出來。
生成圖片的ASP.net頁面全部代碼如下:< %@ Page Language="C#" Debug="true" Trace="false" TraceMode="SortByCategory"% >< % @Import namespace="System.Drawing" % >< % @Import namespace="System.Drawing.Imaging" % >< % @Import namespace="System.Drawing.Text" % >< % @Import namespace="System.IO" % >< script language=C# runat=server >
public void Page_Load(object sender,EventArgs e){ string strNum=GetRandomString();
string strFontName;
int iFontSize;
int iWidth;
int iHeight;
strFontName="宋體";
iFontSize=12;
iWidth=10*strNum.Length;
iHeight=25;
Color bgColor=Color.Yellow;
Color foreColor=Color.Red;
Font foreFont=new Font(strFontName,iFontSize,FontStyle.Bold);
Bitmap Pic=new Bitmap(iWidth,iHeight,PixelFormat.Format32bppArgb);
Graphics g=Graphics.FromImage(Pic);
Rectangle r=new Rectangle(0,0,iWidth,iHeight);
g.FillRectangle(new SolidBrush(bgColor),r);
g.DrawString(strNum,foreFont,new SolidBrush(foreColor),2,2);
MemoryStream mStream=new MemoryStream();
Pic.Save(mStream,ImageFormat.Gif);
g.Dispose();
Pic.Dispose();
Response.ClearContent();
Response.ContentType="image/GIF";
Response.BinaryWrite(mStream.ToArray());
Response.End();
}
private int []GetRandomArray(int Length,int Up,int Down)
{
int iFirst=0;
int []rtArray=new Int32[Length];
Random ro=new Random(Length*unchecked((int)DateTime.Now.Ticks));
iFirst=ro.Next(Up,Down);
rtArray[0]=iFirst;
for(int i=1;i< Length;i++)
{
Random ri=new Random(i*iFirst*unchecked((int)DateTime.Now.Ticks));
rtArray[i]=ri.Next(Up,Down);
iFirst=rtArray[i];
}
return rtArray;
}
其中生成圖片的部分相對復(fù)雜,但由于不是本文的主題所在,所以本文不對之做詳細(xì)說明,有興趣的讀者可以參考杜亮編寫的《親密接觸ASP.net》一書中的相關(guān)內(nèi)容。
最后我們可以編寫一個普通的HTML頁面來查看效果,只要把圖片的src屬性指向這個頁面就行了(這里我們假設(shè)上面那個ASP.net文件的名字是“RandomPic.aspx”):< !DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
< HTML >
< HEAD >
< TITLE > New Document < /TITLE >
< META NAME="Generator" CONTENT="EditPlus" >
< META NAME="Author" CONTENT="" >
< META NAME="Keywords" CONTENT="" >
< META NAME="Description" CONTENT="" >
< /HEAD >
< BODY >
< img src="RandomPic.aspx" >
< /BODY >
< /HTML >
在筆者的機(jī)器上成功地看到了如下結(jié)果:
要實(shí)現(xiàn)像Chinaren網(wǎng)站那樣的防惡意攻擊的效果,只需要在留言簿的頁面里產(chǎn)生隨機(jī)數(shù)并且編寫相應(yīng)的JavaScript驗證代碼(事實(shí)上這個工作可以交給ASP.net的驗證控件很容易地完成),然后傳遞到生成圖片的頁面里生成圖片提示用戶就可以了。
除此以外,隨機(jī)數(shù)還有其它很多用途,特別是開發(fā)游戲的時候更是必不可少。到此,讀者應(yīng)該完全掌握在ASP.net中隨機(jī)數(shù)的產(chǎn)生方法,如此,本文的目的也就達(dá)到了。
最后,有興趣的讀者可以試著解決這個問題:
在橋牌游戲中,發(fā)牌可以視作一個隨機(jī)過程,但是后續(xù)過程受到前面的影響,即已經(jīng)發(fā)出去的牌不可能再次發(fā)出。試編寫一個程序模擬發(fā)牌過程。
作者:未知? 請速與本人聯(lián)系
總結(jié)
以上是生活随笔為你收集整理的ASP.net随机数应用实例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Unix / Linux世界里的4-2-
- 下一篇: C#中调用Windows API的要点