JavaScript中提供了sort()和reverse()方法對數組項重新排序。但很多時候這兩個方法無法滿足我們實際業務的需求,比如說撲克牌游戲中的隨機洗牌。

在這篇文章一起來學習如何完成上面這個示例的效果,以及一些有關于數組隨機排序的相關知識。
在網上查了一下有關于數組隨機排序的相關資料,都看到了Math.random()的身影。打開瀏覽器控制器,輸入:
Math.random()

從圖中可以看出Math.random()得到的是0~1之間的隨機數。眾所周知,sort()可以調用一個函數做為參數,如果這個函數返回的值為-1表示數組中的a項排在b項前。如此一來,可以寫一個隨機函數,讓Math.random()隨機出來的數與0.5做為一個比較,如果大于.5就返回 -1(a排在b前面),反之返回1(b排在a前面):
function randomSort(a, b) {return Math.random() > 0.5 ? -1 : 1;}看個示例:
var arr = [1,2,3,4,5,6,7,8,9];arr.sort(randomSort);

這樣一來,就可以實現文章開頭的示例效果:
雖然前面的方法實現了數組的隨機排序,但總感覺每個元素被派到新數組的位置不是隨機的。就如前面的示例,數組arr中值為1的元素,它的原先鍵值為0,隨機排序后,1的鍵值要求上為0-8的幾率是一樣的。然后在這里是遞減的,原因是sort()方法是依次比較的。
針對這種現象,我們可以使用下面這種遞歸的方法來處理:
function randomSort(arr, newArr) {// 如果原數組arr的length值等于1時,原數組只有一個值,其鍵值為0// 同時將這個值push到新數組newArr中if(arr.length == 1) {newArr.push(arr[0]);return newArr; // 相當于遞歸退出}// 在原數組length基礎上取出一個隨機數var random = Math.ceil(Math.random() * arr.length) - 1;// 將原數組中的隨機一個值push到新數組newArr中newArr.push(arr[random]);// 對應刪除原數組arr的對應數組項arr.splice(random,1);return randomSort(arr, newArr);}如此一來,我們就可以這樣使用:
for (var i = 0; i < 10; i++) {var arr=[1,2,3,4,5,6,7,8,9];var newArr=[];randomSort(arr,newArr);console.log(newArr);}輸出結果:

執行randomSort(arr,newArr)函數之后,原數組arr就清空了。
如果使用這種方法來做文章開頭洗牌的示例,就要在resetPic()函數中重置pukePic數組:
除了上面的兩種方法之外,@Traveller在DIV.IO分享了一篇《數組元素隨機化排序算法實現》,這篇文章提供了三種數組項隨機排序的實現方法:
使用數組sort方法對數組元素隨機排序
Array.prototype.shuffle = function(n) {var len = this.length ,num = n ? Math.min(n,len) : len,arr = this.slice(0);arr.sort(function(a,b){return Math.random()-0.5;});return arr.slice(0,num-1);}隨機交換數組內的元素
lib = {}lib.range = function(min,max) {return min + Math.floor(Math.random()*(max-min+1));}Array.prototype.shuffle = function(n) {var len = this.length,num = n ? Math.min(n,len) : len,arr = this.slice(0),temp,index;for (var i=0;i<len;i++){index = lib.range(i,len-1);temp = arr[i];arr[i] = arr[index];arr[index]=temp;}return arr.slice(0,num);}隨機從原數組抽取一個元素,加入到新數組
lib = {}lib.range = function(min,max) {return min+Math.floor(Math.random()*(max-min+1));}Array.prototype.shuffle = function(n) {var len = this.length, num = n ? Math.min(n,len) : len,arr = this.slice(0),result=[],index;for (var i=0;i<num;i++){index = lib.range(0,len-1-i);// 或者 result.concat(arr.splice(index,1))result.push(arr.splice(index,1)[0]);}return result}洗牌算法
數組隨機排序其基本原理是洗牌算法(Fisher 主站蜘蛛池模板: 赣州市| 财经| 加查县| 遂昌县| 固镇县| 陵川县| 双鸭山市| 阿坝县| 桦南县| 阳信县| 贵南县| 石棉县| 柳州市| 翼城县| 平湖市| 宁波市| 阜南县| 观塘区| 侯马市| 阿坝| 桓仁| 鄄城县| 册亨县| 赣榆县| 旺苍县| 张家港市| 内乡县| 广河县| 太原市| 南城县| 南皮县| 且末县| 哈密市| 墨江| 阿瓦提县| 丹东市| 揭西县| 清水河县| 法库县| 蓝田县| 竹溪县|