2013-07-12 87 views
1

我試圖建立對唯一編號的超過x次一個療程在對隨機生成唯一的號碼多次

例如,如果x = 8我想產生類似:

(5,3) (1,4) (7,2) (8,6) 

目前我有:

var playerArray = [0,1,2,3,4,5,6,7]; 
var loopLength = playerArray.length; 
var player1 = 0; 
var player2 = 0; 
for(var i = 1; i <= loopLength;i++){ 
    var num = Math.floor(Math.random() * playerArray.length); 
    if(player1 == 0){ 
     player1 = num+1; 
     playerArray.splice(num, 1); 
    }else if(player2 == 0){ 
     player2 = num+1; 
     playerArray.splice(num, 1); 
    } 

    if((player1 != 0) && player2 != 0){ 
     alert(player1 + ' vs ' + player2); 
     player1 = 0; 
     player2 = 0; 
    } 

} 

的問題,我想,是我使用的指標分配編號,當我它們接起來它重置索引,這樣我就可以1比2,1比結束3,2和3等等。

任何幫助,將不勝感激。謝謝!

+2

爲什麼不只是洗牌數組,讓循環運行直到'i

+0

@LeeMeador:如果你洗牌並且總是拿走剩下的前兩名球員並與之匹配,那麼這有什麼問題? –

+0

@JeroenVannevel也許我誤解了你。您可以發佈代碼作爲答案。但是......它必須允許在陣列的後半部分有5個和6個。你不能讓上半場的某個人與下半場的某個人相匹配。 –

回答

0
var playerArray = [0,1,2,3,4,5,6,7]; 
var opponentArray = []; 

// mark everyone unassigned 
for (var i = 0; i < playerArray.length; ++i) { 
    opponentArray[i] = -1; 
} 

for (var i = 0; i < playerArray.length; ++i) { 
    if (opponenentArray[i] == -1) { 
     for (;;) { // Keep trying until you get one that isn't assigned yet 
      var num = Math.floor(Math.random() * playerArray.length); 
      if (num != i && opponentArray[num] == -1) { // this one is unassigned and not me 
       opponentArray[i] = num; // assign them to each other 
       opponentArray[num] = i; 
       break; 
      } 
     } 
    } 
} 

注意

有人指出,他們是參與獲得的隨機數,然後扔掉效率低下。

它將不得不被測試,但我懷疑這是由於缺乏與在內存中移動數組元素相關的成本。大多數splice正在重新排列數組元素,並在內存中創建更多對象,並增加內存管理和垃圾收集成本。

謝謝@JimmiTh發現有人可能最終會自己玩的錯誤。我想即使這個代碼需要測試:)

+0

那最糟糕的運行時間是多少? –

+0

@MichaelGeary它可以永遠運行,但其可能性非常小,真的很渺茫。對於第一個選秀權,它總會得到一個未使用的選秀權。對於第二順位來說,賠率是8中的6,以獲得未使用的賠率。對於第三,第四和第八。最後一個選擇有8的機會得到未使用的一個(你可以添加測試,只挑三次,讓剩下的兩個互相玩。我用這個,它只是(我想如果你需要一組8萬的球隊配對,那麼它可能會加起來) –

+0

非常真實,我有點挑剔,想把它變成像這樣的短陣列。 –

1
var playerArray = [0,1,2,3,4,5,6,7]; //your array 
var loopLength = playerArray.length/2; //divid by 2 since you only want pairs 
var player1 = 0; //intialize varibles 
var player2 = 0; 
for(var i = 1; i <= loopLength;i++){ 
    var num = Math.floor(Math.random() * playerArray.length); //generate a random number 
    player1 = playerArray.splice(num, 1); //player1 = number from array 
    num = Math.floor(Math.random() * playerArray.length); //generate a new random number 
    player2 = playerArray.splice(num, 1); //player2 = number from array 
    alert(player1 + ' vs ' + player2); //result 

} 
2

我喜歡@使用洗牌,或在這裏的JeroenVannevel的想法是,想到了我的頭頂部的方法:

// Given an array of player IDs, return an array of random pairs 
function randomPairs(players) { 
    var pairs = []; 
    while(players.length) { 
     pairs.push([ 
      pluckRandomElement(players), 
      pluckRandomElement(players) 
     ]); 
    } 
    return pairs; 
} 

// Return a random element and remove it from the array 
function pluckRandomElement(array) { 
    var i = randomInt(array.length); 
    return array.splice(i, 1)[0]; 
} 

// Return a random integer 0 <= n < limit 
function randomInt(limit) { 
    return Math.floor(Math.random() * limit); 
} 

@ LeeMeador分享了這段代碼有趣的見解:

 output.push([ 
      pluckRandomElement(array), 
      pluckRandomElement(array) 
     ]); 

這是沒有必要使用隨機元素這裏的值。由於該數組已被隨機化,因此可以採用第一個數組元素和隨機數組元素。或者使用array.pop()掐了最後一個元素—了很長的陣列,可能會略微高效:

 output.push([ 
      array.pop(), 
      pluckRandomElement(array) 
     ]); 

而這裏的另一個版本,採用了洗牌的吉榮建議:

// Given an array of player IDs, return an array of random pairs 
function randomPairs(players) { 
    shuffle(players); 
    var output = []; 
    for(var i = 0, n = players.length; i < n; i += 2) { 
     output.push([ players[i], players[i+1] ]); 
    } 
    return output; 
} 

// Shuffle an array in place using the Fisher-Yates algorithm, 
// adapted from http://bost.ocks.org/mike/shuffle/ 
function shuffle(array) { 
    for(var m = array.length; m;) { 
     var i = Math.floor(Math.random() * m--); 
     var t = array[m]; 
     array[m] = array[i]; 
     array[i] = t; 
    } 
    return array; 
} 

任一版本可以與此代碼進行測試:

// Create an array of length n and values 1 through n 
function createPlayerArray(nPlayers) { 
    var array = []; 
    for(var i = 0; i < nPlayers; ++i) { 
     array.push(i + 1); 
    } 
    return array; 
} 

var players = createPlayerArray(8); 
console.log(randomPairs(players)); 

我從代碼的其餘部分分離出的播放器陣列的創建,以允許PO非順序播放器ID的功能(例如來自數據庫的ID字段等)。

+0

我喜歡你的代碼,爲什麼不總是爲一對第一個玩家選擇第一個數組元素,同樣的隨機性發生在你身上 –

+0

@LeeMeador - 我沒有想到 - 這是一個有趣的見解,謝謝! –

+0

我認爲2nd for循環除了將'input'複製到'output'上不必要的複雜時尚。好吧,我猜,它確實創建了4個小陣列。 –

1

我對javascript不熟悉,所以請原諒任何語法錯誤:隨時糾正它們。

我腦子裏想的是什麼是這樣的:

var playerArray = [0,1,2,3,4,5,6,7]; 
// Shuffle the array here. I just googled 
// and I noticed there is no shuffle function in JS, is this correct? 
var player1 = 0; 
var player2 = 0; 
for(var i = 0, len = Math.floor(playerArray.length/2); i < len; i++) { 
    player1 = playerArray[i * 2]; 
    player2 = playerArray[(i * 2) + 1]; 
    alert(player1 + " vs " + player2); 
} 

所有你必須做的就是添加一個隨機播放功能。

附加澄清:

通過洗牌一組項目,你可以提取它們並檢索隨機結果。這裏最關鍵的是存儲你提取的最後一個項目的指針,這樣你就知道該繼續哪裏了。因爲我們需要多個隨機元素,所以我們應該以邊界線的方式工作,從邊界開始(在這種情況下,第一個索引和結束時)。

我們讓循環運行直到數組大小的一半。因爲我們使用整數作爲索引,所以將一個分成兩半的奇數整數(7 => 3.5)將被放置,並且循環將運行3次。因爲我們有一個循環,我們也有我們的指針(i)。唯一棘手的部分是確保你指向正確的索引:循環的每次遍歷實際上使用2個索引,所以我們必須乘以2。通過這樣做,我們得到循環的第一項和第二項一個使用相同的方法,但將索引加1以獲得下一個項目。

+2

+1 - 你對JavaScript沒有內置shuffle是正確的。對於一個shuffle算法,我建議在這裏選出一個高票:http://stackoverflow.com/questions/2450954/how-to- randomize-a-javascript-array - 不要推出自己的數組混排(因爲原因,請參閱例如:http://www.codinghorror.com/blog/2007/12/the-danger-of-naivete。 HTML) – JimmiTh

0

我想你正在尋找的東西沿着這一線路多,除非是我弄錯了:

var playerArray = [0,1,2,3,4,5,6,7]; 
var player1 = 0; 
var player2 = 0; 

// While there are still numbers in the array, keep pairing up the players 
while (playerArray.length > 0) { 
    // Get the first players number from the array and then and remove it from the array 
    var arrayNum1 = Math.floor(Math.random() * playerArray.length); 
    player1 = playerArray[arrayNum1] + 1; 
    playerArray.splice(arrayNum1, 1); 

    // Get the second players number from the array and then and remove it from the array 
    var arrayNum2 = Math.floor(Math.random() * playerArray.length); 
    player2 = playerArray[arrayNum2] + 1; 
    playerArray.splice(arrayNum2, 1); 

    // Display the pairing 
    alert(player1 + ' vs ' + player2); 
} 

從測試的一些樣品的結果:

1st run - (7, 3), (8, 1), (6, 5), (4, 2) 
2nd run - (4, 6), (5, 7), (2, 3), (8, 1) 
3rd run - (1, 8), (2, 6), (3, 5), (7, 4) 
4th run - (6, 3), (5, 8), (7, 1), (4, 2) 
5th run - (2, 4), (7, 5), (8, 6), (3, 1) 
0

我不得不這樣做最近。我喜歡洗牌算法的想法。我創建了一個混合數組的副本數組(對),然後將該數組旋轉1,然後匹配每個數組的索引以創建對。我認爲這將創建唯一的對,除了大小爲1和2的數組外。