2015-09-04 41 views
1

我編寫了一個簡單的隨機化函數,它循環訪問數組中的元素並逐個顯示它們。從數組中獲取隨機元素,顯示它並循環 - 但從未使用過相同的元素

See it here.

function changeSubTitle() { 
    var whatAmI = ["Webdesigner", "Drummer", "Techie", "Linguistics student", "Photographer", "Geek", "Coder", "Belgian", "Batman", "Musician", "StackExchanger", "AI student"]; 
    setTimeout(function() { 
     $(".page-header > h2").animate({ 
      "opacity": 0 
     }, 700, function() { 
      $(this).text(whatAmI[Math.floor(Math.random() * whatAmI.length)]); 
      $(this).animate({ 
       "opacity": 1 
      }, 700, changeSubTitle); 
     }); 
    }, 1000); 
} 

然而,這顯然是非常可能的是相同的元素顯示兩次,一個後另一個。發生這種情況是因爲我每次調用該函數時都會隨機化數組。我將如何防止一個元素相繼顯示兩次?

我想最直接的方式做,這是獲得隨機化功能了循環,運行循環,每一個元素被調用時,從陣列中刪除索引和填充數組的時候它是空的。很多關於SO的問題都考慮了這個問題,但並不像我的那樣具體:我不確定如何在循環中執行此操作來顯示每個元素。

+0

我會做的是先洗牌數組,然後像通常那樣逐個顯示每個元素。檢查這個http://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array-in-javascript關於如何洗牌 – astroanu

回答

1

舉個甚至所有元素的機會,除了前一個被用來執行以下操作:

var i, j, n = 10; 
setInterval(function() { 
    // Subtract 1 from n since we are actually selecting from a smaller set 
    j = Math.floor(Math.random() * (n-1)); 
    // if the number we just generated is equal to or greater than the previous 
    // number then add one to move up past it 
    if (j >= i) j += 1; 
    document.write(j + ' '); 
    i = j; 
}, 1000); 

在代碼中的註釋應該解釋這是如何工作的。關鍵要記住的是,您實際上是從9個可能的值中選擇,而不是從10.

您應該在啓動之前將i初始化爲數組中的隨機元素。

對於一個簡單的步行通過與第二元件的3元件陣列上選定的:

i=1, n=3

的隨機結果爲我們提供了0或1

如果它是0,則返回j >= i假,我們選擇元素零

如果它是1,那麼j >= i返回true,我們選擇第三個元素。

你可以做同樣的事情,我是0,我是2,看到它永遠不會超過緩衝區,並且總是有相同的機會來選擇所有其他元素。

然後,您可以將相同的邏輯擴展爲任意大小的數組。它的工作方式完全相同。

+0

感謝你的解釋。由於'i'沒有在第一次運行中定義,所以不會'if(j> = i)j + = 1;'拋出一個錯誤? –

+0

讓我們[在聊天中繼續討論](http://chat.stackoverflow.com/rooms/88786/discussion-between-wawawared-and-tim-b)。 – leaf

3

停止upvoting請:-D

以下的答案是更好:https://stackoverflow.com/a/32395535/1636522。我和蒂姆之間的extended discussion啓發你爲什麼應該避免使用我的解決方案。我的回答是,從這個角度來看纔有意思,因此,它不值得任何給予好評:-D


你可以保存的最後一個整數和「外衣」,直到下一個是不同的:

var i, j, n = 10; 
 
setInterval(function() { 
 
    while ((j = Math.floor(Math.random() * n)) === i); 
 
    document.write(j + ' '); 
 
    i = j; 
 
}, 1000);

或者更簡單,只需添加1 ... :-D模n防止索引溢出:

應用到你的代碼

解決方案一:

var whatAmI = ["Webdesigner", "Drummer", "Techie", "Linguistics student", "Photographer", "Geek", "Coder", "Belgian", "Batman", "Musician", "StackExchanger", "AI student"]; 
 
var j; 
 
var i = 1; // since you start with "Drummer" 
 
var n = whatAmI.length; 
 

 
function changeSubTitle() { 
 
    setTimeout(function() { 
 
    while ((j = Math.floor(Math.random() * n)) === i); 
 
    $(".page-header > h2").animate({ 
 
     "opacity": 0 
 
    }, 700, function() { 
 
     $(this).text(whatAmI[j]); 
 
     $(this).animate({ 
 
     "opacity": 1 
 
     }, 700, changeSubTitle); 
 
    }); 
 
    }, 1000); 
 
    i = j; 
 
} 
 

 
changeSubTitle();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<header class="page-header"> 
 
    <h1>Bananas</h1> 
 
    <h2>Drummer</h2> 
 
</header>

+0

在這種情況下'i'是來自數組的索引,'n '陣列的長度,對吧?你能將它應用於我的代碼嗎? –

+0

是的,這個作品(我認爲)!你能解釋一下while循環的作用嗎?這看起來很直截了當,但我無法把頭圍住它! –

+1

@BramVanroy我已經更新了演示。請注意根據您想要首先顯示的值設置「i」。關於小循環:'while((j = something)=== i);'設置「j」爲某事物,與'i'比較,如果'j === i'則重做。這足夠清楚了嗎? : -/ – leaf

0
var whatAmI = ["Webdesigner", "Drummer", "Techie", "Linguistics student", "Photographer", "Geek", "Coder", "Belgian", "Batman", "Musician", "StackExchanger", "AI student"]; 

var prev = 1; //1 because "drummer" is the first array element displayed in the HTML 

function getIndex(){ 
    var next = Math.floor(Math.random() * whatAmI.length); 
    if(next==prev) 
     return getIndex(); 
    else { 
     prev = next; 
     return next; 
    }  
} 

function changeSubTitle() { 
    setTimeout(function() { 
     $(".page-header > h2").animate({ 
      "opacity": 0 
     }, 700, function() { 
      $(this).text(whatAmI[getIndex()]); 
      $(this).animate({ 
       "opacity": 1 
      }, 700, changeSubTitle); 
     }); 
    }, 1000); 
} 
changeSubTitle(); 

嘗試此方法。