Poker Ellerini Belirleme


19

Bir değerlendirmenin parçası olarak Texas Hold'Em oyunu yapıyorum ve mevcut 7 kartı nasıl inceleyeceğimi ve ellerin var olup olmadığını nasıl belirleyeceğime bakıyorum.

Düşünebileceğim tek olası yöntem, kartları sayısal olarak sıralamak, sonra olası her 5 kart grubunu incelemek ve mümkün olan her elin bir listesiyle eşleşip eşleşmediklerini kontrol etmektir. Bu uzun bir zaman alacaktır, takımın ilgisiz olması nedeniyle sadece çiftleri belirlemek için mümkün olacaktır.

Kartların her biri, bir sayı / a / j / q / k ve bir takımdan (char)3(biraz maça sembolü yapan) oluşan dizelerdir .

El analizi sistemi oluşturmak için kullanabileceğim herhangi bir öneri, formül veya bağlantı var mı?

Henüz ellerini birbirine göre sıralama konusunda endişelenme, bu farklı bir balık su ısıtıcısı.


1
Sadece işaret ediyor ama bağlamındaki vektör etiketi doğrusal cebirle ilgili. Konteyner değil.
Sidar

@Sidar Uygun olmadığına inanıyorsanız, gelecekte etiketleri düzenlemekten çekinmeyin. Fareyle etiketlerin üzerine gelirseniz ve "Etiketleri düzenle" seçeneği açılırsa (en azından benim için mi?) Ve soruyu düzenlemeden yalnızca etiketleri düzenleyebilirsiniz.
MichaelHouse

@ Byte56 Bu garip düşünme alışkanlığım var, doğru olup olmadığımdan emin değilim, bu yüzden pasif bir yorum yapıyorum ... Bu yüzden yazıyı düzenlemedim. Belki de gönderide bir şey kaçırdım, bu yüzden cevabını bekliyordum.
Sidar

Burada birkaç yıl önce Oyun Geliştiricisi'nde ortaya çıkan güzel bir makale de var: cowboyprogramming.com/2007/01/04/programming-poker-ai
celion

1
Java bir süre eğlence için bir uygulama geri burada bulabilirsiniz: codereview.stackexchange.com/questions/10973/… . PokerHand.java'ya bakarsanız, her el türünü test etmek için yöntemler bulacaksınız (örn. İsFullHouse). Yalnızca kartlar önce sıralanırsa çalışırlar.
bughi

Yanıtlar:


20

Poker ellerinin çoğunu, her bir rütbenin ve takımın elinde kaç kart olduğunu gösteren birkaç tablo yaparak bulabilirsiniz.

Başka bir deyişle, elinizdeki o sıradaki kart sayısına bir dizi eşleme kart sırası (sayılar ve A / J / Q / K) oluşturun. Oyuncunun bir çifti veya türünün üçü varsa, bu dizide 2 veya 3'e eşit bir öğe olacaktır, vb. 2 ve 3 olan bir öğe varsa ve bu dizide 1'e eşit beş öğe varsa.

Aynı şekilde, her bir takımın kart sayısında benzer bir dizi yapabilir ve floşları tespit etmek için kullanabilirsiniz.

Belirli bir elin varlığını tespit ettikten sonra, kullanıcı arayüzünde veya yapmanız gerekenleri vurgulamak için geri dönüp eldeki belirli kartları bulmak oldukça kolaydır.

Sözde kodda:

int countByRank[13] = { 0 };        // Initialize counter to zero for each rank
for (cards in hand)
    countByRank[card.rank] += 1;    // Increment counter for this card's rank
if (countByRank.find(2))
    // There's a pair
else if (countByRank.find(3))
    // There's a three-of-a-kind
// etc...

17

Biraz zor çünkü çok fazla kombinasyon var. Neyse ki çok kısa sürede çok sayıda kombinasyonu kontrol edebilen bir işlemciniz var.

Farklı el tiplerini tespit etmek için birkaç farklı stratejiye ihtiyacınız olacak. Neyse ki, farklı türlerden birkaçı stratejilerle çakışabilir. Elin sırasına göre araştırırdım.

  1. Düz yıkama
  2. Dörtlü
  3. Dolu ev
  4. floş
  5. Düz
  6. Üç çeşit
  7. İki çift
  8. Bir çift
  9. Yüksek Kart

2, 3, 6, 7,8 Tüm basit sayma vardır. As ile Kral arasındaki kartların bir listesini kullanarak, bulunan her ek kart için artarak her değerin sayısını listeye yerleştirmeniz yeterlidir. Sonra 4s için listeyi kontrol edin, 4s yoksa, bir tür 4'ünüz yok. 3s için kontrol edin, eğer 3s yoksa, 3'ünüz yok. 3'ünüz varsa, 2 (tam evi belirten) olup olmadığını kontrol edin. Ve bunun gibi...

İçin 1, 5aynı listeyi kullanabilir ve tüm kartların 5 kartlık bir dizi için listede bir veya daha fazla girişi olduğu sekansları arayabilirsiniz. Aynı kıyafete sahiplerse, düz bir sifon.

4aynı liste kurulumuna sahip olabilir, ancak bu sefer elbiseyi sayıyorsunuz. 5 veya daha yüksek sayıları arayın.

Son olarak, 9en yüksek karta sahip olursunuz, bu da yukarıdaki listelerinizden birinden en yüksek değere bakmak için basit bir mesele olmalıdır.

Sırayla arama yaparsanız bir eşleşme bulduğunuzda mola verebilirsiniz. Yine de, kullanıcıya tüm bu bilgileri vermek istiyorsanız aramaya devam etmek ve tüm eşleşmeleri bulmak önemsiz olacaktır.


Esasen, kovaları dolduruyorsunuz. Daha sonra kovaları kombinasyon açısından kontrol edin. Örneklemek gerekirse:

resim açıklamasını buraya girin

Bir dizi ile başlayarak, her kart için bir kova ile kartlar arasında tekrarlayın ve her kartın örneğini sayın. Ardından diziyi kolayca tekrarlayabilir ve belirli kombinasyonları kontrol edebilirsiniz. Bu örnekte, bir tür 4 olduğu açıktır, çünkü kovalardan birinde 4 öğe vardır.


6

Bu algoritmaya bir kez girdim. Elleri belirlemek için asal sayıları çarpar ve çok ilginç bir okumadır. Cactus Kev's Poker El Değerlendiricisi


1
Bu ilginç, ama hepsini okuduğunuzdan emin değilim. Bu algoritma 5 kart içindir . Yazarın 7 kart için bir algoritmaya sahip olduğunu, ancak paylaşmadığını belirttiği için 7 kartla ilgili bir Google aramada bulmuş olabilirsiniz. Sayfanın üst kısmındaki gri metne bakın. Bu algoritmanın 7 kartlık bir set için ne kadar yararlı olduğundan emin değilim.
MichaelHouse

1
7 kartlı bir elden yapılabilecek sadece 21 farklı 5 kartlı el olduğu için bir seçenek her biri için 5 kartlı bir değerlendirici kullanmak ve en iyisini seçmek.
Adam

@ Byte56 Haklısın, 7 karta kullandığımı hatırlıyorum, ancak önceden en iyi 5 kartı belirlemek zorunda kaldım, ki bu da verimliliği zayıflattı.
petervaz

Bu cevabın bağlantısı o zamandan beri çürümüş ve alan bir spam göndericisi tarafından alınmış. Bağlantıyı orijinal sayfanın bir arşivine yönlendirdim, ancak bu cevabı daha sağlam hale getirmek için cevabın gövdesinde önerilen algoritmanın bir özetini içerecek şekilde cevabı düzenlemek ideal olacaktır.
DMGregory

2

Bu sorunun zaten elde ettiği mükemmel cevapları desteklemek için, temel sınıflandırma tekniği uygulandıktan sonra elleri karşılaştırmanın en basit yollarından birini sunmanın yararlı olacağını düşündüm. Her şeyden önce, sayısız cevaplar önerildiği gibi elleri sınıflarıyla etiketlemek isteyeceksiniz - 'X el i Y'den daha iyi mi?' daha sonra iki elin sınıflarını karşılaştırarak ve hangi sınıfın daha iyi olduğunu görerek yapılabilir. Geri kalanı için, aslında kart bazında karşılaştırmanız gerekir ve sınıflandırmada biraz daha fazla çalışmanın bunu kolaylaştıracağı ortaya çıkar.

Temel durum olarak, her iki elin de 'yüksek kart' el olduğu durumu düşünün; bu durumda, ilk önce en yüksek iki kartı, daha sonra (eşleşen iki kartı vb.) karşılaştırırsınız. Her giriş elinin en yüksekten en düşük karta sıralandığını varsayarsanız, bu yaklaşım, bu:

int CompareHandsOfSameClass(Hand h1, Hand h2) {
  for ( int i = 0; i < 5; i++ ) {
    if ( h1[i].rank > h2[i].rank ) {
      return -1;
    } else if ( h1[i].rank < h2[i].rank ) {
      return 1;
    }
  }
  return 0;
}

Şimdi, iyi haber: bu sözlükbilimsel düzen , uygun bir şekilde ayarlanmış, herhangi bir eldeki iki eli karşılaştırmak için çalışıyorsınıfları, sınıfları aynı olduğu sürece. Örneğin, çiftleri karşılaştırmanın yolu önce çiftleri, sonra diğer üç kartı karşılaştırmak olduğundan, çifti önce (hatta çiftin ilk kartı!) Koymak ve aynı karşılaştırmayı çalıştırmak için elinizi sıralayabilirsiniz. (Örneğin, A9772 gibi bir el 77A92 veya daha iyisi 7A927 olarak saklanır; A9972 eli 9A729 olarak saklanır ve yukarıdaki kodu 7'ye 9'a karşı çukurlaştırarak ve A9972 kazandı). İki çiftten oluşan bir el önce iki çiftten daha yüksek, sonra daha düşük, daha sonra 'kicker' ile saklanır (yani, A9977 97A97 olarak saklanır); türünün üçü önce üç karttan biriyle, daha sonra vurucularla, daha sonra diğer kartlarla (örneğin, A7772 7A277 olacaktır) saklanır; dolu bir ev üçünden biriyle ve sonra ikisinden biriyle depolanır (örneğin, 99777 79779 olarak saklanır); ve düzlükler ve yıkamalar her ikisi de tıpkı yüksek kartlı ellerde olduğu gibi 'doğrudan sözlükbilimsel' düzende saklanabilir. Bu, zaten verilen işlevle tüm el sınıfları için çalışan basit bir dış karşılaştırma işlevine yol açar:

// Compare two hands, returning -1/0/+1 as hand 1 is less than, equal to,
// or greater than hand 2. Note that this function assumes the hands have
// already been classified and sorted!
int CompareHands(Hand h1, Hand h2) {
  if ( h1.handClass > h2.handClass ) {
    return -1;
  } else if ( h1.handClass < h2.handClass ) {
    return 1;
  } else {
    return CompareHandsOfSameClass(h1, h2);
  }
}

Umarım bu biraz yardımcı olacaktır!


1

Uygun kart gösterimleri ve bit döndürme kullanılarak bazı paralellikler olabilir. Örneğin, bu Java kodu, iki elin karşılaştırılması için kullanılabilecek bir tamsayı döndüren 7 kartlı sabitleri değerlendirir . Elin tipini daha kullanıcı dostu bir şekilde rapor edecek şekilde uyarlanabilir. Temel fikirler Cactus Kev'nun önceki bir cevabında atıfta bulunulan sayfasından geliyor.

Elinizi sadece verimlilik ve kod netliği yerine çeşitli dillerde adlandırmak için olası uygulamalarla ilgileniyorsanız , codegolf.SE'de poker eli meydan okumasını adlandırın.


1

İlk olarak, tüm kartların sırasını ve takımını bilmeniz gerekir; önemsiz ama gerekli.

Ardından, bu 7 kartı çevirin ve iki histogram oluşturun; biri sıralamaya göre (13 endeksli bir dizi kullanarak, hepsi sıfıra ilklendirilir ve bu sıralamaya sahip eldeki bir kart bulunursa ve 1 olduğunda artırılır) ve biri sıraya göre (sıralamaya benzer şekilde oluşturulmuş dört öğeden oluşan bir dizi kullanılarak) . Bunlar doğrusal işlemlerdir ve her bir kart için her iki işlemi yalnızca bir çapraz geçiş seti için yapabilirsiniz.

Daha sonra, her bir histogramı ölçütlerle eşleşen kovalar ve / veya basit bir takip testi için inceleyerek aşağıdaki ellerden herhangi birinin var olup olmadığını belirleyebilirsiniz:

  • Çifti: Tam olarak bir rütbe kovası tam olarak 2 değerine sahip mi, başka bir kepçe 1'in üzerinde bir değere sahip değil ve aynı hizada değil mi?
  • İki Çift: İki veya daha fazla rütbe kepçesinin değeri tam 2 mi, kepçenin 2'den fazla ve sifonu yok mu? (Açıkçası üç çift bir el değildir, ancak yedi kart verilen bir olasılıktır; en güçlü iki çift oyuncunun elidir)
  • TOAK: Tam olarak bir kova tam olarak 3 değerine sahip mi, başka hiçbir kova 1'den büyük ve yıkama yok mu?
  • Düz: Ardışık beş rütbe kabının floş olmadan 1 veya daha fazla değeri var mı? (Asların hem yüksek hem de düşük olduğunu unutmayın; 14 öğeden oluşan bir sıralama histogramı kullanabilir ve isterseniz iki kovada Asları sayabilirsiniz)
  • Floş: Herhangi bir takım kovasında 5 veya daha fazla kart var mı? (eğer öyleyse, elinizi bu takımın kartları için tarayın ve ilk 5'i seçin)
  • Full House: Herhangi bir rütbe kovası 3 değerine sahip mi ve diğer herhangi bir kova 2 değerine sahip mi?
  • Dörtlü: Herhangi bir rütbenin değeri 4 mü? (başka bir kombinasyon mümkün olmamalıdır)
  • Floş: Her iki düz var mıdır ve histogramlar ile gösterilen bir floş? Eğer öyleyse, belirtilen floş takımında belirtilen düzün her bir sırasına uygun bir sıraya sahip en az bir kart var mı? (bu muhtemelen en hesaplamalı olarak pahalıdır, ancak kaç ardışık sıralama olduğunu saymak basit olmalı ve eli 5 ardışık sıralama için sadece bir kez, 7 için 6 ve üç kez iki kez taramanız gerekir)

Doğal olarak, bu kontrollerin birkaçını birleştirebilirsiniz:

  • Bir sifon var mı?
  • Bir düz var mı?
    • Her ikisi de varsa, düz bir sifon mu?
    • Eğer düz bir yıkaysa, hem As hem de Kral var mı?
  • Eşi benzeri olmayan dört tane var mı?
  • Kaç tane üç çeşit var? (İki, tam bir ev. Bir, çiftleri kontrol et)
  • Kaç çift var? (İki veya daha fazla ile, iki çift. Biriyle, üç tane varsa, tam bir ev, aksi takdirde bir çifttir)
  • Yukarıdakilerin hiçbiri (yüksek kart).

Temel olarak, eğer bunların cevapları herhangi bir el verirse, ortaya çıkan "el gücü" değerini, eğer değer daha yüksek değilse , bulunan elin gücüne ayarlayın . Örneğin, tam bir eviniz varsa, gücü 7/9, o zaman da üçlü, güç 4 ve bir çift, güç 2 var.

Birkaç kısayol ve hızlı çıkış var, ancak genel olarak tüm kontrolleri yapmak o kadar pahalı değil .


0

Basit bir yinelemeli yaklaşımla poker ellerini nispeten kolay bir şekilde yapabilirsiniz.

Her kart için, çift veya üç / dört tür olup olmadığını kontrol etmek için aynı yüze sahip bir veya iki veya üç tane başka bir tane olup olmadığını kontrol edin.

Dolu evler benzer. Ya da aynı yüz olmayan bir çift ve üç tür bulursanız, tam bir evi bulduğu gibi işaretleyin.

Yıkamalar için, aynı elbiseden beş tane olup olmadığını görmek için her elbiseyi kontrol edin.

Sıralanmamış olsa bile düz kontrol etmek kolaydır. Her kart için bir tane daha yüksek olup olmadığını kontrol edin ve art arda beş kart bulunup bulunmayana kadar tekrarlayın.

Kraliyet yıkamaları ve düz yıkamalar, düzlüklere benzer şekilde bulunabilir. Royal flush'ların daha düşük değerli kartların göz ardı edilebileceği bazı ekstra koşulları vardır.

Evet, bu yaklaşım verimsizdir, ancak çoğu poker oyunu için bu önemsizdir. Saniyede binlerce eli kontrol etmeden, yarım dakikada bir küçük bir avuç oyuncuyu kontrol ediyorsunuz.

Daha iyi yöntemler var, ancak kodlanması daha fazla zaman alabilir ve muhtemelen bir algoritmanın zeki ve verimliliğinin yanı sıra oyuncuların bakış açısından daha iyi bir oyun elde etmek için zaman / para harcamak için daha önemli şeyleriniz vardır.


0

çiftleri, çift çiftleri, toaks, tam evler, pokers vb bulmak için basit bir yol şunlardır:

yuvalanmış bir döngüdeki her kartı birbiriyle şu şekilde karşılaştırın:

int matches=0;
for (int i=0;i<5;i++)
   for (int j=0;j<5;j++)
      if (i!=j && cardvalue(card[j])==cardvalue(card[i])) matches++;

maçlar aşağıdakileri tutacaktır:
2 çift için
4 iki çift için
6 toak için
8 bir fullhouse için
12 bir poker için

Bunu hızlandırmak için: j-loop'u 5'e kadar çalıştırmak gerekmez, i-1'e çalıştırılabilir. daha sonra "i! = j" karşılaştırması kaldırılabilir, eşleşme değerleri yarıya indirilir (1 = çift, 2 = 2 çift vb.)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.