これよりも簡単な方法は、ポーカーのストレートを計算しますか?
-
25-09-2019 - |
質問
プレーヤーの手がテキサスホールデムでストレートを保持しているかどうかを計算するためのアルゴリズムがあります。正常に動作しますが、配列/文字列変換などを伴わないより簡単な方法があるのではないかと思います。
これが私が持っているものの単純化されたバージョンです。プレイヤーが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);
ここでの秘trickは、またはさまざまなスーツであるため、2つの表現が1つしかありません。これを行うためのより簡単な方法があるに違いないと思って間違っていますか?
解決
コードのほとんどすべての作業は、タイプ変換です。最初からハンドをビット形式で保管していた場合(ニーズ> 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;
1行ループを使用する同等のものは次のとおりです。
var suits = [];
for(var i=0; i < 13; i++) {
suits[i] = rawHand[i] || rawHand[i+13] || rawHand[i+26] || rawHand[i+39];
}
これははるかに短くて理解しやすいです。
ビットワイズの表現との間での変換には、ビットごとのオペレーターまたは演算子を使用して保存するよりも多くのコードとCPU時間が必要です。
他のヒント
まあ、ストレートには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
}
整数値をカード値のビットフィールドとして使用できます。ACEは、2つのスポットが低くなり、高くなります。次に、10の可能なストレートに対してビットワイズエンドと比較します。
または、for -loopを使用して、5つの連続した数字をチェックしてください - 事実上、それはすべて同じです。
この質問は私に興味を持ちました。私は船外に出ました。そして、手を計算するためにWebページを書きました。おそらく最も効率的ではありませんが、機能します。 JavaScriptだけでこれを行いました(jqueryなし)。がここにあります デモ http://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> A</td>
<td> 2</td>
<td> 3</td>
<td> 4</td>
<td> 5</td>
<td> 6</td>
<td> 7</td>
<td> 8</td>
<td> 9</td>
<td>10</td>
<td> J</td>
<td> Q</td>
<td> K</td>
<td> </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>
いいえ、それはそれが得るのと同じくらい簡単です。私はしばらく前にポーカーハンド評価を調べましたが、最速の方法であなたのようなアプローチを使用していると思います。最初の結果を参照してください このサイト. 。ビットワイズ操作を使用して手を計算します。
編集:最初の結果とは、「PokerSource Poker-Eval Evaluator」を意味します。
ランクごとにカードを並べ替えてから、各ランクが前のランクよりも多いことを確認してください。 「ランク」は、ACE = 1、2 = 2、... j = 11、q = 12、k = 13の長さ5の配列です。これは、ここに示されている他の方法よりも簡単だと思います。
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]);
}
SpecialKの7カードと5カードの評価者を使用することができます ここ そして、それに手をランク付けするように頼みます。返品されるランクが5854〜5863(両方とも包括的)または7453と7462(両方とも包括的)の間で、それぞれ5枚または7枚のカードの手を持っている場合、それはストレートです。
注のエースは0、ハートオブハートのエースが1で、51で表される2つのクラブに示されます。アルゴリズムはカードを「追加」し、小さなテーブルでランクを調べ、 9MBのRAM。それももっと多くのことをしますが、ちょっと...