2016-09-24 155 views
0

我買了一本JavaScript書,正在按照我的方式工作。我已經達成了一本沒有意義的書。我希望你們和女孩能夠澄清,因爲這本書沒有。用隨機整數值填充數組

請參閱下面的代碼,生成6個隨機數並將它們呈現給id=panel

function init(){ 
var panel = document.getElementById('panel'); 
var i, rand, temp, str, num = []; 

for (i = 1; i < 50; i ++){ 
    num[i] = i; 
} 

for (i = 1; i < 50; i ++){ 
    rand = Math.ceil(Math.random()*49); 
    temp = num[i]; 
    num[i] = num[rand]; 
    num[rand] = temp; 
} 

str = 'Your six lucky numbers:<br>'; 
for (i = 1; i < 7; i ++){ 
    str += num[i]; 
    if (i !==6){str += ' - ';} 
} 
panel.innerHTML += str; 

} 
document.addEventListener('DOMContentLoaded', init, false); 

書中說,第二環路(即initilizes隨機變量)中包含的確保無兩個元素包含相同數量的排序算法。

我不知道這是如何可能的,我沒有看到任何代碼在那裏停止rand包含一個重複的號碼,並因此有該值存儲在num。這本書並沒有提供很多關於發生的事情的解釋。

有人請讓我知道,如果有的話,循環二是防止'num`包含相同的數字?

謝謝全部

P.S.很抱歉,如果這個問題不符合堆棧溢出指南。我不經常來這裏,只有當我真的陷入困境,無法在其他地方找到答案時。

回答

1

第一for循環剛剛創建49個元件的陣列,其中每個陣列元素等於其索引:

num[1] = 1 
num[2] = 2 
etc. 

第二個for循環,這是您的問題的重點,隨機洗牌這有序數組。

爲例:

的for循環第一次迭代,蘭特得到的值說,在迴路中的邏輯,然後用在NUM值[1 swops在NUM [23]的值]這樣你結束:

num[1] being equal to 23 (because num[23] was equal to 23 as per above) 
num[23] being equal to 1 

的for循環第二次迭代,蘭特得到的值說,在迴路中的邏輯然後swops在NUM [18]與所述值的值num [2],以便最終:

num[2] being equal to 18 (because num[18] was equal to 18 as per above) 
num[18] being equal to 2 

這將發生49次。

這也是的Math.random)被乘以49的原因(中,只有49的數組元素與值。

TL; DR;有序數組被洗牌。

+0

非常感謝您的解釋。我必須以完全相同的方式去理解它,但不確定我是否正確。 有什麼可以阻止'Math.random()'產生兩次相同的數字? – Pete

+0

沒有,但可以說隨機在第3次和第15次迭代中生成32。它將交換第32和第3個值,因此在swop之後num [32] = 3和num [3] = 32。現在,在第15次迭代中,它將用num [32]替換num [15],但現在num [32]包含3,所以在swop之後num [15] = 3和num [32] = 15。所以,如果它不止一次產生一個隨機值,它並不重要。 –

+0

非常感謝你!我不能爲我的生活找出一個。我瞭解該計劃正在做什麼,而不是它會造成的影響。再次感謝你的分解,正是我需要的+1:D – Pete

1

這個循環產生從1到49排序後的數組:與另一隨機位置rand陣列的通過交換兩個

for (i = 1; i < 50; i ++){ 
    num[i] = i; 
} 

這個循環重新排序每個位置(i)。它不會生成新的隨機數字,只是隨機地重新排序現有數字。 rand索引,在這種情況下不是值。沒有兩個數字可以是相同的,因爲第一個循環只將數字中的每個數字的一​​個實例放入數組中。

for (i = 1; i < 50; i ++){ 
    rand = Math.ceil(Math.random()*49); 
    temp = num[i]; 
    num[i] = num[rand]; 
    num[rand] = temp; 
} 
+0

非常感謝你的幫助。我的理解從每個人都告訴我的都是正確的。 我仍然困惑的是'Math.ceil(Math.random()* 49);'產生一個介於1到49之間的隨機數。雖然它只循環了49次。 'Math.random'不可能產生 - 例如 - 14兩次? – Pete

+1

幾乎可以肯定,它會產生兩次相同的數字。所以一個號碼將被替換爲14,然後這個號碼將與另一個號碼再次交換。數字甚至有可能回到原來的位置。但是,嘿,那是隨機的! 即使我使用它,我也有填充這個算法是有偏見的。我認爲最好在第一個數組中填入一個隨機數字。 – bokan

1

這種循環填充,並與1 50點的整數數組50

然後,它只是將它們混合。 rand變量用於指向數組中的隨機索引。

2

你可以把兩個循環如下:第一個生成的49「卡片」(在此由數字1到49表示)的甲板。然後第二個循環通過反覆交換每張牌隨機洗牌這些「牌」。

有兩個問題的代碼。首先,當僅選擇6個元素時,不需要對整個數組進行洗牌。因此,第二個循環可以結束於6而不是50.

但是有一個更嚴重的問題,它使用錯誤的算法來洗牌數組元素。該算法不會以相同的概率產生所有可能的元素排列。

下面是正確的版本:

for (i = 1; i < 50; i ++){ 
    rand = i + Math.floor(Math.random()*(50 - i)); 
    temp = num[i]; 
    num[i] = num[rand]; 
    num[rand] = temp; 
} 

的想法是交換當前元素的循環,只有一個後續元素(包括自身)。請注意,如果您編寫上面的循環向後運行(即從49到1),它會使它稍微簡單一些,我更喜歡這種方法。

+0

我不會說第二個問題是嚴重的 - 至少在這種情況下不是這樣。這是「幸運數字」,而不是火箭科學。 – Xufox

+0

那麼,正確的算法並不複雜得多,也沒有理由教人們使用錯誤的算法。 – redneb

+1

爲我等於1,這將返回可能50作爲索引,它不存在(如果Math.random()返回0.9999然後0.9999 *(51-1)+ 1等於49.99其中的上限爲50)但同意,最好是學習一些關於隨機早期的規則 –