2017-09-16 46 views
2

我對JavaScript很新,我有一個小問題。比javascript中的「開關」更好的方法

作爲我的第一個「項目」,我希望我的程序給我一張隨機的撲克牌。沒什麼好看的,但我試圖找出一個優雅的方式來做到這一點。 現在我唯一的想法是給1到52之間的一個隨機數字一個特定的卡,但是有一個更好的方法。

這裏是我當前的代碼:

function newCard() { 
var card_id = document.getElementById("card_id"); 
var c1 = Math.floor(Math.random() * 52) + 1; 
switch(c1) { 
    case 1: 
     c1 = "ace of spades"; 
     break; 
    case 2: 
     c1 = "2 of spades"; 
     break; 
    case 3: 
     c1 = "3 of spades"; 
     break; 


    // ...I think you get the idea here 


     } 

card_id.innerHTML = c1; 
} 

你有我一個提示,如何使這個更快/更好?

+0

你應該使用一些陣列,一個套裝,一個用於1-10jqk,以及一個用於甲板...查看https://stackoverflow.com/questions/26248001/創建播放 - – Stuart

+0

檢查下面的鏈接是否可以幫助你。 https://stackoverflow.com/questions/32769010/generate-a-deck-of-cards-in-javascript – msg

回答

7

function newCard() { 
 
    // Pick from 0 to 51, not 1 to 52 
 
    var cardId = Math.floor(Math.random() * 52); 
 
    
 
    var ranks = ["ace", "2", "3", "4", "5", "6", "7", "8", "9", "ten", "jack", "queen", "king"]; 
 
    var suits = ["spades", "hearts", "diamonds", "clubs"]; 
 
    
 
    // % is the modulo operator, so 0 => 0, 1 => 1, ... 12 => 12, 13 => 0, 14 => 1, ... 
 
    // Math.floor(cardId/13) gets the suit (0, 1, 2, 3) 
 
    return ranks[cardId % 13] + " of " + suits[Math.floor(cardId/13)]; 
 
} 
 

 
for (var i = 0; i < 10; i++) { 
 
    console.log(newCard()); 
 
}

UPDATE

因爲這導致了一點討論圍繞從非無限的甲板(不重複卡)的交易,這裏是產生一個典型的解決方案全套牌,洗牌,然後發牌。基本上上述解決方案是cardIdToEnglishshuffleFisher-Yates shuffle。請注意,使用pop交易從結束的甲板,這可能看起來很奇怪,但也請注意,這是無關緊要的。 :-)

function cardIdToEnglish(id) { 
 
    var ranks = ["ace", "2", "3", "4", "5", "6", "7", "8", "9", "ten", "jack", "queen", "king"]; 
 
    var suits = ["clubs", "diamonds", "hearts", "spades"]; 
 

 
    return ranks[id % 13] + " of " + suits[Math.floor(id/13)]; 
 
} 
 

 
function shuffle(arr) { 
 
    // Fisher-Yates shuffle 
 
    var n = arr.length; 
 

 
    for (var i = 0; i < arr.length - 2; i++) { 
 
     var j = Math.floor(Math.random() * (n - i)) + i; 
 

 
     // Swap a[i] and a[j] 
 
     var temp = arr[i]; 
 
     arr[i] = arr[j]; 
 
     arr[j] = temp; 
 
    } 
 
} 
 

 
function newDeck() { 
 
    var deck = []; 
 
    for (var i = 0; i < 52; i++) { 
 
     deck.push(i); 
 
    } 
 

 
    shuffle(deck); 
 
    return deck; 
 
} 
 

 
var deck = newDeck(); 
 
for (var i = 0; i < 52; i++) { 
 
    var card = deck.pop(); 
 
    console.log(cardIdToEnglish(card)); 
 
}

+0

非常感謝!這真是一個很好的方式:D – Robin

+0

雖然我喜歡這個 - 我想知道是否應該有一種機制來阻止選擇相同的選定的牌 - 兩個後續抽牌由於相同的隨機數而選擇相同的牌不是不可能的。所以選擇2個鑽石應該從後面的抽籤中刪除這個選項 - 這就像創建一個選定的卡對象(數字和花色)陣列一樣簡單,並且在選擇之後但在顯示選擇之前檢查它。然後,如果卡片中存在卡片 - 重繪隨機數等。 – gavgrif

+0

對於使用非無限牌組的遊戲,典型的解決方案是先洗牌,然後從洗牌平臺上抽取牌。 – smarx

0

這裏有一個想法:

var deck = ['ace of spades', 'two of spades', 'three of spades', '...']; 
// and so on, all 52 cards 
var rand = Math.floor(Math.random() * 52); 

console.log(deck[rand]); // will print a random card from the deck 

或者,你也可以從甲板上取下畫卡,如果你想繼續「遊戲」。

deck.splice(rand, 1); 

在此之後,你就需要重新生成隨機的小甲板:

rand = Math.floor(Math.random() * deck.length); 
0

這是一個有趣的問題。這就是我在想什麼......數字卡片從2到9.如果我們繼續使用整數作爲卡片值,傑克,王后,國王和王牌可以分別表示爲10,11,12和13 。

但是,當然,我們有四個這些值的四個西裝的形式。一個快速的谷歌search顯示,在英語國家,套裝的相對價值可以從俱樂部,鑽石,心臟和黑桃的排名從最低到最高。因此,我們可以說,2 - 13是俱樂部,14 - 25鑽石,26 - 37顆心,28 - 49黑桃。按照這個公式,你的隨機數應該在2到49之間。

所以記住這一點,你可以寫一個函數來做一些數學運算來根據生成的數字來確定確切的卡片。顯然,你不能處理同一張卡片兩次,所以一旦產生了一個數字,它就應該存儲在一張髮卡中。每次您生成一個號碼時,您都需要檢查該號碼是否在髮卡陣列中。如果是,你會想要生成另一個號碼。我有一個想法來設置和檢查這個數組。如果您認爲我的想法值得追求,請告訴我,我會將其添加到此答案中。

+0

嘿,如果它不會付出很大的努力,我很樂意看到這個! – Robin

+0

看看我對我的解決方案所做的編輯,它顯示了處理一副紙牌的更典型方式。 (先把它刷洗一下。)「畫一張卡片,如果是複製的,再畫一張卡片」效率不高......畫一張新卡需要的時間越來越長,因爲卡片已經耗盡,理論上說,不能保證你會成功!跟蹤剩餘的可用卡並總是從該池中抽取更好。 Fisher-Yates shuffle基本上是這樣做的。 – smarx

+0

不錯! @Robin,我會用smarx的答案去。我打算爲它投票。 –

1

我會創建一個所有卡片的數組作爲套裝和行列的對象(使用嵌套的forEach循環來輕鬆 - 迭代套裝和排列數組),然後使用隨機數生成卡片ID。然後這將給出該卡的等級和套裝。然後我從卡組中移除卡 - 以防止它被處理兩次並減少可用卡的數量)。這樣做意味着選定的卡是隨機的,不會重複。我還放置了一個按鈕,將其全部重置並允許進一步處理10張牌。

var deck = []; 
 

 
function setCards(){ 
 
    var suits = ["Spades", "Hearts", "Diamonds", "Clubs"]; 
 
    var ranks = ["Ace", "2", "3", "4", "5", "6", "7", "8", "9", "Ten", "Jack", "Queen", "King"]; 
 
    
 
    
 
    //creates an array of card objects that have the rank and suit as properties 
 
//eg: deck = [ {suit: "Spades", rank: "Ace"}, {suit: "Spades", rank: "2"},...etc] 
 
    suits.forEach(function(suit){ 
 
    ranks.forEach(function(rank){ 
 
     var card = {}; 
 
     card.suit = suit; 
 
     card.rank = rank; 
 
     deck.push(card); 
 
    }); 
 
     
 
    }); 
 
} 
 

 
function newCard(count) { 
 
    //decreases the count of the deck since some cards have already been dealt 
 
    var remainingCards = 52 - count; 
 
    var index = Math.floor(Math.random() * remainingCards); 
 
    var card= deck[index]; 
 
    deck.splice(index,1); //removes the selected card from the deck 
 
    return card; 
 
} 
 

 
function dealCards() { 
 
    document.getElementById('hand').innerHTML = '<dt>My Hand </dt>'; 
 
    setCards(); 
 
    
 
    for (var i = 0; i < 10; i++) { 
 
    var card = newCard(i); 
 
    document.getElementById('hand').innerHTML += '<dd>'+ card.rank + ' of ' + card.suit + '</dd>'; 
 
    } 
 
}
<button type="button" onclick="dealCards()">Deal New Hand</button> 
 
<hr/> 
 

 

 
<dt id = "hand"></dt>

+0

嗨,謝謝你的代碼:)。你能解釋一下代碼如何記住被取出的具體卡片嗎?我看不到這個 – Robin

+0

'deck.splice(index,1);'將卡從卡座上移開。因此,不要記住哪些卡已被刪除,代碼是記住哪些卡仍然存在。 – smarx

+0

@gavgrif爲什麼不使用'deck.length'而不是傳入'count'? – smarx