最近要做一個(gè)項(xiàng)目,有關(guān)商品顯示搶購(gòu)的功能。比如我們的網(wǎng)站很帶流量,那么成千上萬(wàn)的用戶(hù)在幾秒內(nèi)同時(shí)點(diǎn)你的商品,確實(shí)會(huì)出現(xiàn)“搶購(gòu)人數(shù)過(guò)多,會(huì)提示,系統(tǒng)繁忙。
但是呢,大部分網(wǎng)站然而并沒(méi)有這么牛叉。為了讓用戶(hù)感受到商品很搶手,動(dòng)不動(dòng)就提示”系統(tǒng)繁忙“的效果,我們需要做一個(gè)程序來(lái)”假裝很繁忙“。 (除了淘寶,大家不要以為其他網(wǎng)站真的很繁忙哦,只不過(guò)人家是故意讓你覺(jué)得不搶就買(mǎi)不到,求懂)
本文來(lái)設(shè)定一個(gè)規(guī)則,大家可以根據(jù)我的思路擴(kuò)展即可。
1、商品購(gòu)買(mǎi)鏈接,每個(gè)人都可以點(diǎn)。
2、我們要讓用戶(hù)有70%的可能性出現(xiàn)“排隊(duì)中,商品繁忙”
本文用 php代碼實(shí)現(xiàn)。其他語(yǔ)言一樣,改改。
首先我們用小學(xué)學(xué)到的知識(shí)想一下:
1、 如果有10個(gè)球,其中3個(gè)紅球,7個(gè)籃球。放在袋子里。隨便胡亂的混合一下,讓你用手伸進(jìn)去摸,那么摸到籃球的幾率是多少?顯然,是70%
之前我把這個(gè)需求給了一個(gè)小伙伴看。他給出的答案如下:
$arr=array(“red”,”red”,”red”,”blue”,”blue”,”blue”,”blue”,”blue”,”blue”,”blue”);
然后 echo $arr[rand(0,9)];
然后告訴我,他兩句話就搞定了。
這個(gè)做法其實(shí)已經(jīng)蠻聰明了。但是這位小伙伴忽略了很重要的一點(diǎn)
2、如果第二個(gè)人來(lái)摸呢? 這里有個(gè)注意點(diǎn),如果第二個(gè)人來(lái)摸,那么必定要把這10個(gè)球補(bǔ)滿(mǎn)(依然是3個(gè)紅球,7個(gè)籃球)
然后最重要的,還要繼續(xù)“胡亂的、隨便的”混合一下。這樣,第二個(gè)人來(lái)摸到籃球的幾率才會(huì)依然是70%.
上面的程序明顯忽略了:繼續(xù)“胡亂的、隨便的”混合一下。 如果每個(gè)人都按這個(gè) 前三個(gè)紅后七個(gè)藍(lán) 來(lái)摸球。那么php的rand函數(shù)不能保證籃球是70%。
說(shuō)到這,很多大神要拿出各種高級(jí)算法,譬如啥貝葉斯、矩陣之類(lèi)的字眼出來(lái)。如果這么一個(gè)電商功能要用這么復(fù)雜的運(yùn)算,我相信你的老板不會(huì)同意你花這么多時(shí)間來(lái)完成這個(gè)功能吧。
接下來(lái),我放出一種簡(jiǎn)單,但也不失精準(zhǔn)性的算法。我們的目標(biāo)是:使用php的簡(jiǎn)單函數(shù),盡可能的讓摸到籃球的幾率接近于70%。
第一步: $arr=array(“red”,”red”,”red”,”blue”,”blue”,”blue”,”blue”,”blue”,”blue”,”blue”); 這個(gè)東西要有,這就是初始化的三個(gè)紅球,7個(gè)籃球
第二步:隨意的、胡亂的混合。
上面一個(gè)數(shù)組有10個(gè)元素,我們可以采取隨機(jī)兩個(gè)球交換,交換多少次可以自己定
先寫(xiě)個(gè)交換函數(shù) (如果這個(gè)函數(shù)看不懂,就要惡補(bǔ)基礎(chǔ)知識(shí)啦)
1
2
3
4
5
6
7
|
function swap( $i , $j , $arr ) { $tmp = $arr [ $i ]; $arr [ $i ]= $arr [ $j ]; $arr [ $j ]= $tmp ; return $arr ; } |
這個(gè)函數(shù)實(shí)現(xiàn),我輸入兩個(gè)隨便什么序號(hào),實(shí)現(xiàn)對(duì)這個(gè)數(shù)組中符合該序號(hào)的求交換一下。
第三步:優(yōu)化交換算法。
因?yàn)樯厦娴慕粨Q函數(shù),輸入的隨機(jī)參數(shù)導(dǎo)致,紅球和紅球交換,或者籃球和籃球交換。那么然而并沒(méi)有實(shí)現(xiàn)“真正的”混合
所以我們要寫(xiě)個(gè)補(bǔ)充函數(shù),確保每次交換,都必須是紅球和籃球進(jìn)行隨意交換
1
2
3
4
5
6
7
8
9
10
11
12
|
function getRange( $arr , $v ) { $ret = array (); for ( $i =0; $i < count ( $arr ); $i ++) { if ( $arr [ $i ]== $v ) { $ret []= $i ; } } return $ret [rand(0, count ( $ret )-1)]; } |
這個(gè)函數(shù)的作用是:在10個(gè)球中找到 紅球或籃球,然后分別取出他們目前所在的序號(hào),然后利用rand函數(shù)隨機(jī)取一個(gè)籃球或者紅球的序號(hào)。
諾看一下這里:
$i=getRange($arr,”red”); //這樣可以取出隨機(jī)一個(gè)紅球的序號(hào)
$j=getRange($arr,”blue”); //這樣可以取出隨機(jī)一個(gè)籃球的序號(hào)
第四步:比較重要。
開(kāi)始隨意的、胡亂的混合
1
2
3
4
5
6
7
8
9
10
|
for ( $num =0; $num <10; $num ++) { $i =getRange( $arr ,”red”); $j =getRange( $arr ,”blue”); $arr =swap( $i , $j , $arr ); // echo implode(“,”, $arr).”|”.$i.”|”.$j.”<br/>”; //這個(gè)語(yǔ)句可以看一下輸出,混合過(guò)后的排列,是否每次都不一樣 } |
這里的注意點(diǎn)是,$num<10 。代表我混合10次。 等于用你的大手到袋子里胡亂攪10次。 理論上攪的越多,隨機(jī)性越強(qiáng)。這里其實(shí)10次足以。
第四步執(zhí)行完成后出來(lái)的$arr 就是攪拌好的 紅球和籃球的混合體。
第五步:再次調(diào)用 rand函數(shù)
echo $arr[rand(0,9)];
如果出來(lái)的是內(nèi)容是blue ,則直接exit(“老子很忙,別煩”)
如果是red,那么讓程序繼續(xù)執(zhí)行購(gòu)買(mǎi)程序吧。