2013-10-26 42 views
0

所以我有這些代碼行生成一個隨機數actualy一個唯一的隨機數,但是這個代碼是不是很好,當你必須生成160個數字。每個生成的數字都被添加到一個數組中,並且每次生成一個新數字時都將檢查該數組,並且如果該數字在數組上,則如果該數字不在它所顯示的數組中,則會生成另一個數字。請幫我簡化這段代碼,以便它不需要那麼多的內存,而且:一切運行良好,直到隨機生成器重新開始157然後它破解...我似乎無法知道爲什麼... 請幫我做它更好! THX請幫我簡化這個隨機生成函數

var randomNum:int = 0; 
var randomGen:int = 0; 
var myArray:Array = []; 

function setup() 
{ 
displayRandomNumber(); 

var_corect.addEventListener(MouseEvent.CLICK, randomNumberEvent); 
} 
setup(); 

function randomNumberEvent(e:MouseEvent) 
{ 
displayRandomNumber(); 
} 
function displayRandomNumber() 
{ 
randomGen = randBetween(1, 160); 
randomNumberText.text = randomGen.toString(); 
trace ('Number is:'+ randomNumberText.text); 
if(myArray.indexOf(randomGen) == -1){ 
myArray.push(randomGen); 

}else{ 
displayRandomNumber() 
    } 
trace("my array" + myArray); 

} 

function randBetween(min:int, max:int):int 
{ 
return Math.round(Math.random() * (max - min) + min); 
} 
+0

由於您的算法設計,它在接近尾聲時變得效率低下。考慮:最後,隨機選擇最後一個不存在的數字的可能性僅爲1/168 - 所有其他值必須循環和重新選擇。此外,掃描陣列的成本是掃描一個元素的168倍。總之,你最後一次迭代將比第一次慢28.224倍。倒數第二次將減慢14028倍。倒數第三將會慢9296倍。迭代成本與(168 /(168-N))* N成正比。 –

回答

2

這裏有一個非常快速的方式,因爲你沒有檢查它是否之前被選中:

--create 168號的數組 - 或怎麼過多少號碼你想和什麼範圍。

- 創建一個多少你想要選擇的循環。

- 每個迭代選擇一個隨機從數組拼接它 - 例如:

var randomIndex:int = Math.random() * pool.length; 

var choice:int = pool.splice(randomIndex,1).pop(); 

陣列 - - 如果是空的創建一個新的和重複同樣的過程中,如果那是你想做。

使用此過程,您將永遠不必檢查數字是否唯一。你只需要檢查數組是否爲空,這意味着你選擇了每個數字一次。

更快,因爲你永遠不必生成第二,第三或第四等時間的隨機數。

+0

作出修改後,忘記做拼接選擇。您必須執行'pop()',因爲拼接返回拼接值的數組。 – prototypical

+0

我需要一個唯一的數字來生成,直到所有數字從1到160生成 –

+0

這就是這樣做。無論該數組中的數字是什麼,都將隨機選擇,直到沒有剩餘數字爲止。將不會有重複。 – prototypical

1

由於您的算法設計,它在接近尾聲時變得效率低下。在處理隨機數時,「循環和重新選擇」是一個相當着名的反模式。

考慮:最後,隨機選擇不存在的最後一個數字的機率只有1/168 - 所有其他值必須循環和重新選擇。

此外,掃描陣列的成本是掃描一個元素的168倍。

總之,最後一次迭代將比第一次慢28.224倍。倒數第二次將減慢14028倍。倒數第三將會慢9296倍。迭代成本正比於(168 /(168-N))* N.

作爲對方的回答說,而不是選擇具有到環號碼& - 產生數字,然後選擇內的索引列表「洗牌」。這就是他們如何與卡...

+0

對我來說很好的新信息thx –

1

你可以檢查這個算法(Fisher-Yates shuffle)它看起來非常有用。

  • 的選擇轉動你的數組的最後一個元素開始(它您可以與第一元素開始只是修改while循環)

  • 挑選隨機元素使用Pivot的指數從你的陣列

  • 並重新定位,從陣列

順便說一句這兩個元件它可以隨機地,但它不是挑相同元件如果你想獲得更好的結果只是調用函數多次你是洗牌的一個問題....

我把代碼從here

function shuffle(array) { 
    var m = array.length, t, i; 

    // While there remain elements to shuffle… 
    while (m) { 

    // Pick a remaining element… 
    i = Math.floor(Math.random() * m--); 

    // And swap it with the current element. 
    t = array[m]; 
    array[m] = array[i]; 
    array[i] = t; 
    } 

    return array; 
} 
+0

這是真正優化的更多,但除非你有大量要素洗牌,否則我會選擇第二個選項該頁面(這基本上是我的答案),因爲它更乾淨。即使是相對較小的數組,原始代碼也會顯着減速。對於像一副牌或這168個號碼那樣小的東西來說,走第三條路線甚至不會有明顯的差異。 – prototypical

+0

是的,但我認爲這一個更清楚瞭解。無論如何,所有的都是eac其他的迭代。 –

+0

以及我將需要在未來使用很多元素,我將至少有300個元素,所以我能做什麼,所以它不需要太多的resorces也......? –

0

請與數陣列從1到160之間的隨機0和159.把隨機指數放到最後。下一次隨機在0到158之間,並將該指數放到最後。隨機0至157等等...

function shuffle(theArray:Array) { 
var m=theArray.length; var num:Int; var i:int; 
while (m) { 

i = Math.floor(Math.random() * m--); 
num=index[i]; 
theArray.splice(i,1); 
theArray.push(num);} 

return theArray;} 
+0

thx但我需要一個真正優化的功能,這些只會添加很多功能,不會幫助我很多thx –

+0

添加代碼以顯示如何,與以前的答案非常相似。想想那裏會有一個數組方法,然後放在最後,但沒有找到。如果有的話,你可以在while循環中使代碼少得多。 theArray.theMethodIdontfind(Math.floor(的Math.random()* M--)); – user1894606