2010-10-23 82 views
5

我有一個算法來計算玩家的手是否在德州撲克中持有直線。它工作正常,但我不知道是否有做一個簡單的方法,不涉及陣列/串轉換等有沒有比這更簡單的方法來計算直撲撲克?

這裏是什麼,我有一個簡化版本。假設玩家處理的是一個卡片值爲52個元素的陣列:

var rawHand = [1,0,0,0,0,0,0,0,0,0,0,0,0, //clubs 
       0,0,0,0,0,0,0,0,0,0,0,0,0, //diamonds 
       0,1,1,0,1,0,0,0,0,0,0,0,0, //hearts 
       0,0,0,1,0,0,0,0,1,0,0,0,0];//spades 

A 1表示卡片在該值插槽中。上面的牌有2個球杆,沒有鑽石,3個心形,4個心形,6個心形,5個黑桃和10個黑桃。現在我看着它找到一條直線。

var suits = []; //array to hold representations of each suit 

for (var i=0; i<4; i++) { 
    var index = i*13; 
    // commenting this line as I removed the rest of its use to simplifyy example 
    //var hasAce = (rawHand[i+13]); 

    //get a "suited" slice of the rawHand, convert it to a string representation 
    //of a binary number, then parse the result as an integer and assign it to 
    //an element of the "suits" array 
    suits[i] = parseInt(rawHand.slice(index,index+13).join(""),2); 
} 

// OR the suits  
var result = suits[0] | suits[1] | suits[2] | suits[3]; 

// Store the result in a string for later iteration to determine 
// whether straight exists and return the top value of that straight 
// if it exists; we will need to determine if there is an ace in the hand 
// for purposes of reporting a "low ace" straight (i.e., a "wheel"), 
// but that is left out in this example 
var resultString = result.toString(2); 

//Show the result for the purposes of this example 
alert("Result: " + resultString); 

這裏的訣竅是對各種套裝進行OR處理,所以只有一個2對ACE表示法。我錯在認爲必須有一個更簡單的方法來做到這一點?

+2

看起來對我來說非常簡單,你認爲它可以更簡單嗎?爲了檢測輪子,我只需在陣列前面插入每個套裝陣列的最後一個元素的副本,然後將它們放在一起。然後你可以搜索'11111'的字符串結果。 – 2010-10-23 16:21:12

+0

它可以更快地使用反向while/for循環for(var i = 3; i - ;){...}' – vol7ron 2010-10-23 16:36:46

+0

@Larry Lustig:這是我認爲可能更簡單的parseInt行。你知道,在「也許如果我在這更好,我不會轉換爲數組=>字符串=> int,然後回到一個字符串」... – Robusto 2010-10-24 00:08:52

回答

2

你的代碼幾乎所有的工作都是類型轉換。如果你只是有存儲位格式的手開始(需要> 32位類型),你可以這樣做:

var mask = 2^13 - 1; // this will zero out all but the low 13 bits 
var suits = (rawHand | rawHand>>13 | rawHand>>26 | rawHand>>39) & mask; 

使用一個線環等效爲:

var suits = []; 
for(var i=0; i < 13; i++) { 
    suits[i] = rawHand[i] || rawHand[i+13] || rawHand[i+26] || rawHand[i+39]; 
} 

這是更短,更容易理解。

轉換和從逐位表示需要更多的代碼和CPU時間比你使用save位OR操作。

+0

謝謝,這是有道理的。 – Robusto 2010-10-26 17:20:32

2

嘛,直必須包括一個5或10,這樣你就可以扔出去的手開始,如果它不具備一個或其它:

if (rawHand[3] || rawHand[16] || rawHand[29] || rawHand[42] || 
    rawHand[8] || rawHand[21] || rawHand[34] || rawHand[47]) { 
    // do some more checks 
} else { 
    // not a straight 
} 
1

不,這是我們所一樣簡單得到。我前段時間看過撲克牌手評價,我認爲最快的方法是使用像您這樣的方法。請參閱this site中的第一個結果。它使用按位操作來計算指針。

編輯:通過第一個結果,我的意思是「Pokersource撲克評價儀計算器」。

+0

最快!=最簡單 – vol7ron 2010-10-23 16:34:29

+0

是的,但是方法不簡單?我想不出任何簡單的事情。順便說一句,這種方法幾乎與埃爾科在他/她的回答中提到的完全相同。 – 2010-10-23 19:13:49

2

您可以使用一個整數值作爲卡片值的位域,ace獲得兩個點低和高。然後,您將比較與十個可能的直線對比。

或者使用for循環並檢查連續五個數字 - 實際上它們都是一樣的。

2

這個問題讓我感興趣。我最終失足了。並寫了一個網頁來計算任何一隻手。它可能不是最高效的,但它確實有效。我只用JavaScript做了這個(沒有jQuery)。這裏是一個demohttp://jsbin.com/izuto4/2/

下面是代碼:

<html> 
<head> 
<script> 
    // var myrawHand = [1,0,0,0,0,0,0,0,0,0,0,0,0, //clubs 
    // 0,0,0,0,0,0,0,0,0,0,0,0,0, //diamonds 
    // 0,1,1,0,1,0,0,0,0,0,0,0,0, //hearts 
    // 0,0,0,1,0,0,0,0,0,0,0,0,0];//spades 

    function getCardsInHand(rawHand) { 
     var cardsInHand = new Array(); 
     var counter = 0; 
     for (var i = 0; i < rawHand.length; i ++) { 
      if (rawHand[i]) { 
       cardsInHand[counter] = i; 
       counter ++; 
      } 
     } 
     return cardsInHand; 
    } 

    function cardsfiltered(rawHand) { 
     var cards = getCardsInHand(rawHand) 

     var cardsfiltered = new Array(); 
     for (var j = 0; j < cards.length; j ++){ 
      cardsfiltered[j] = cards[j] - (parseInt(cards[j]/13) * 13); 
     } 
     cardsfiltered.sort(); 
     return {cards : cards, cardsfiltered : cardsfiltered}; 
    } 

    function whatIsMyHand(rawHand) { 
     var cardObject = cardsfiltered(rawHand); 
     if (((cardObject.cards[0] == 0 && cardObject.cards[1] == 9) 
       || (cardObject.cards[0] == 13 && cardObject.cards[1] == 22) 
       || (cardObject.cards[0] == 26 && cardObject.cards[1] == 35) 
       || (cardObject.cards[0] == 39 && cardObject.cards[1] == 48)) 
       && cardObject.cards[4] == cardObject.cards[3] + 1 && 
       cardObject.cards[3] == cardObject.cards[2] + 1 && 
       cardObject.cards[2] == cardObject.cards[1] + 1) { 
      return "Royal Flush"; 
     } 
     else if (cardObject.cards[4] == cardObject.cards[3] + 1 && 
       cardObject.cards[3] == cardObject.cards[2] + 1 && 
       cardObject.cards[2] == cardObject.cards[1] + 1 && 
       cardObject.cards[1] == cardObject.cards[0] + 1) { 
      return "Straight Flush"; 
     } 
     else if ((cardObject.cardsfiltered[1] == cardObject.cardsfiltered[2] 
       && cardObject.cardsfiltered[2] == cardObject.cardsfiltered[3]) 
       && (cardObject.cardsfiltered[0] == cardObject.cardsfiltered[1] 
       || cardObject.cardsfiltered[3] == cardObject.cardsfiltered[4])) { 
      return "Four of a Kind"; 
     } 
     else if ((cardObject.cardsfiltered[0] == cardObject.cardsfiltered[1] 
       && cardObject.cardsfiltered[1] == cardObject.cardsfiltered[2] 
       && cardObject.cardsfiltered[3] == cardObject.cardsfiltered[4]) 
       || (cardObject.cardsfiltered[0] == cardObject.cardsfiltered[1] 
       && cardObject.cardsfiltered[2] == cardObject.cardsfiltered[3] 
       && cardObject.cardsfiltered[3] == cardObject.cardsfiltered[4])) { 
      return "Full House"; 
     } 
     else if (parseInt(cardObject.cards[0]/13) == parseInt(cardObject.cards[1]/13) 
       && parseInt(cardObject.cards[0]/13) == parseInt(cardObject.cards[2]/13) 
       && parseInt(cardObject.cards[0]/13) == parseInt(cardObject.cards[3]/13) 
       && parseInt(cardObject.cards[0]/13) == parseInt(cardObject.cards[4]/13)) { 
      return "Flush"; 
     } 
     else if ((cardObject.cardsfiltered[4] == cardObject.cardsfiltered[3] + 1 
       && cardObject.cardsfiltered[3] == cardObject.cardsfiltered[2] + 1 
       && cardObject.cardsfiltered[2] == cardObject.cardsfiltered[1] + 1 
       && cardObject.cardsfiltered[1] == cardObject.cardsfiltered[0] + 1) 
       || (cardObject.cardsfiltered[0] == 0 
       && cardObject.cardsfiltered[1] == 10 
       && cardObject.cardsfiltered[2] == 11 
       && cardObject.cardsfiltered[3] == 12 
       && cardObject.cardsfiltered[4] == 9)) { 
      return "Straight"; 
     } 
     else if ((cardObject.cardsfiltered[0] == cardObject.cardsfiltered[1] 
       && cardObject.cardsfiltered[1] == cardObject.cardsfiltered[2]) 
       || (cardObject.cardsfiltered[1] == cardObject.cardsfiltered[2] 
       && cardObject.cardsfiltered[2] == cardObject.cardsfiltered[3]) 
       || (cardObject.cardsfiltered[2] == cardObject.cardsfiltered[3] 
       && cardObject.cardsfiltered[3] == cardObject.cardsfiltered[4])) { 
      return "Three of a Kind"; 
     } 
     else if ((cardObject.cardsfiltered[0] == cardObject.cardsfiltered[1] 
       && (cardObject.cardsfiltered[2] == cardObject.cardsfiltered[3] 
       || cardObject.cardsfiltered[3] == cardObject.cardsfiltered[4])) 
       || (cardObject.cardsfiltered[1] == cardObject.cardsfiltered[2] 
       && cardObject.cardsfiltered[3] == cardObject.cardsfiltered[4])) { 
      return "Two Pair" 
     } 
     else if (cardObject.cardsfiltered[0] == cardObject.cardsfiltered[1] 
       || cardObject.cardsfiltered[1] == cardObject.cardsfiltered[2] 
       || cardObject.cardsfiltered[2] == cardObject.cardsfiltered[3] 
       || cardObject.cardsfiltered[3] == cardObject.cardsfiltered[4]) { 
      return "Pair"; 
     } 
     else { 
      return "High Card"; 
     } 
    } 
    var CardCheckCount = 0; 
    function MaxCardCheck(element) { 
     if (element.checked) { 
      if (CardCheckCount < 5) { 
       CardCheckCount++; 
       return true; 
      } 
     } 
     else { 
      CardCheckCount--; 
      return true; 
     } 
     element.checked = !element.checked; 
     alert("You can only pick 5 cards."); 
     return false; 
    } 

    function calculateHand() { 
     var checkboxes = document.getElementsByTagName("input"); 
     var myrawHand = new Array(); 
     for (var i = 0, element; element = checkboxes[i]; i++) { 
      myrawHand[parseInt(element.name)] = element.checked ? element.value : 0; 
     } 
     alert(whatIsMyHand(myrawHand)); 
    } 
</script> 
</head> 
<body> 
<table> 
    <thead> 
     <tr> 
      <td>&nbsp;A</td> 
      <td>&nbsp;2</td> 
      <td>&nbsp;3</td> 
      <td>&nbsp;4</td> 
      <td>&nbsp;5</td> 
      <td>&nbsp;6</td> 
      <td>&nbsp;7</td> 
      <td>&nbsp;8</td> 
      <td>&nbsp;9</td> 
      <td>10</td> 
      <td>&nbsp;J</td> 
      <td>&nbsp;Q</td> 
      <td>&nbsp;K</td> 
      <td>&nbsp;</td> 
     </tr> 
    </thead> 
    <tbody> 
     <tr> 
      <td><input name="0" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="1" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="2" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="3" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="4" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="5" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="6" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="7" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="8" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="9" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="10" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="11" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="12" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td>Clubs</td> 
     </tr> 
     <tr> 
      <td><input name="13" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="14" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="15" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="16" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="17" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="18" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="19" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="20" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="21" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="22" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="23" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="24" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="25" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td>Diamonds</td> 
     </tr> 
     <tr> 
      <td><input name="26" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="27" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="28" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="29" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="30" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="31" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="32" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="33" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="34" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="35" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="36" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="37" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="38" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td>Hearts</td> 
     </tr> 
     <tr> 
      <td><input name="39" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="40" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="41" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="42" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="43" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="44" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="45" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="46" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="47" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="48" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="49" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="50" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td><input name="51" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td> 
      <td>Spades</td> 
     </tr> 
    </tbody> 
</table> 
<button onclick="calculateHand()">Calculate Hand</button> 
</body> 
</html> 
0

爲什麼不按職級的卡片進行排序,然後檢查每個級別比前一個。 「rows」是一個長度爲5的數組,ACE = 1,2,...,J = 11,Q = 12,K = 13。我認爲這比這裏介紹的其他方法更簡單。

function isStraight(ranks) { 
    ranks.sort(); 
    return (ranks[0] + 1 == ranks[1] || (ranks[0] == 1 && ranks[4] == 13)) && 
     (ranks[1] + 1 == ranks[2]) && 
     (ranks[2] + 1 == ranks[3]) && 
     (ranks[3] + 1 == ranks[4]); 
} 
0

您可以使用SpecialK的7張和5張貼評估和here要求其排名手中。如果返回的等級在5854和5863之間(包括兩端)或者在7453和7462(包括兩端)之間,那麼你的牌就是5或7張​​牌,分別是或者是直的。

請注意,黑桃王牌由0表示,心臟的王牌由1表示,直到以51表示的兩個俱樂部。該算法將「添加」您的卡片並在小的時候查找排名表,佔用9MB的RAM。它也將做更多,但嘿...