Recognizing poker hands from a 2D matrix of values

时间:2015-07-28 16:39:17

标签: matlab

I have a 1000 x 5 sorted matrix with numbers from 1-13. Each number denotes the numerical value of a playing card. The Ace has the value 1, then the numbers 2 through 10 follow, then the Jack has value 11, Queen with value 12 and King with value 13. Therefore, each row of this matrix constitutes a poker hand. I am trying to create a program that recognizes poker hands using these cards that are enumerated in this way.

For example:

A =  [1 1 2 4 5;  2 3 4 5 7;  3, 3, 5, 5, 6; 8, 8, 8, 9, 9]

Therefore, in this matrix A, the first row has a pair (1,1). The second row has high card (7), the third row has two pair ((3,3) and (5,5)) and the last one is a full house (Pair of 9s and 3 of a kind (8).

Is there a good way to do this in MATLAB?

1 个答案:

答案 0 :(得分:6)

bsxfun对这种情况不起作用。这是计数问题。这都是计算你拥有的东西的问题。具体来说,扑克牌手可以计算每张牌的数量,并找出正确的计数组合以获得有效牌。这里有一张漂亮的照片,向我们展示了人类所知道的每一个可能的扑克牌:

http://www.bestonlinecasino.tips/wp-content/uploads/2013/07/poker-hand-rankings3.png

来源:http://www.bestonlinecasino.tips

因为我们的矩阵中没有套装,所以我会忽略皇家同花顺,同花顺和同花顺场景。你想要识别的每一只手都可以用每行的直方图从1到13的二进制位,并确定是否(按排名顺序):

  • 情况#1:高手 - 所有垃圾箱的箱数都恰好为1
  • 情况#2:一对 - 你只有一个数量为2的bin
  • 情况#3:两对 - 你有两个数量为2的箱子
  • 情况#4:三种类型 - 你只有一个数量为3的bin
  • 情况#5:直 - 你不需要在这里计算直方图。只需对您的手进行排序,并获取相邻差异,并确保连续值之间的差异为1。
  • 情况#6:满屋 - 你只有1个数量为2 的容器你正好有1个数​​量为3的垃圾箱。
  • 情况#7:四种 - 你有一个数量为4的bin。

因此,根据您的MATLAB版本,使用histchistcounts查找手的直方图。我还会在每一行上预先排序,以便在找到直线时简化操作。您在帖子中提到矩阵是预先排序的,但我会假设它可能没有排序的一般情况。

因此,这里有一些预处理代码,因为您的矩阵在A中:

Asort = sort(A,2); %// Sort rowwise
diffSort = diff(Asort, 1, 2); %// Take row-wise differences
counts = histc(Asort, 1:13, 2); %// Count each row up

diffSort包含每行的逐列差异,counts为您提供N x 13矩阵,其中N是您正在考虑的总牌数。 ..所以在你的情况下,那是1000.对于每一行,它会告诉你遇到了多少特定的卡。所以你现在要做的就是经历每一种情况,看看你有什么。

让我们制作一个ID数组,它的矢量大小与你拥有的手数相同,ID会告诉你我们玩了哪只手。具体做法是:

* ID = 1 --> High Hand
* ID = 2 --> One Pair
* ID = 3 --> Two Pairs
* ID = 4 --> Three of a Kind
* ID = 5 --> Straight
* ID = 6 --> Full House
* ID = 7 --> Four of a Kind

因此,您可以采取以下措施检查每种情况,并分配out以包含我们的ID:

%// To store IDs
out = zeros(size(A,1),1);

%// Variables for later
counts1 = sum(counts == 1, 2);
counts2 = sum(counts == 2, 2);
counts3 = sum(counts == 3, 2);
counts4 = sum(counts == 4, 2);

%// Situation 1 - High Hand
check = counts1 == 5;
out(check) = 1;

%// Situation 2 - One Pair
check = counts2 == 1;
out(check) = 2;

%// Situation 3 - Two Pair
check = counts2 == 2;
out(check) = 3;

%// Situation 4 - Three of a Kind
check = counts3 == 1;
out(check) = 4;

%// Situation 5 - Straight
check = all(diffSort == 1, 2);
out(check) = 5;

%// Situation 6 - Full House
check = counts2 == 1 & counts3 == 1;
out(check) = 6;

%// Situation 7 - Four of a Kind
check = counts4 == 1;
out(check) = 7; 

情境#1基本上检查是否所有遇到的箱子都包含1张卡。如果我们检查所有只有1个计数的垃圾箱并将它们加在一起,我们应该得到5张卡。

情境#2检查我们是否只有1个有2张卡的垃圾箱,而且只有一个垃圾箱

情况#3检查我们是否有2个包含2张卡的箱子。

情况#4检查我们是否只有一个包含3张卡的垃圾箱。

情境#5检查排序结果的每一行的相邻差异是否都等于1.这意味着在找到相邻距离时整行包含1。如果是这种情况,那么我们就是顺利的。我们使用all并独立检查每一行,以查看所有值是否等于1.

情境#6检查我们是否有一个包含2张卡一个包含3张卡的纸槽。

最后,情境#7检查我们是否有1个包含4张卡的垃圾箱。

有几点需要注意:

  • 根据我们的定义,直手在技术上也是一个高手,但由于直接检查发生在管道的后期,所以最初被分配为高手的任何手都被分配为直线...所以& #39;对我们来说没问题。

  • 此外,满屋也可以是三种类型,因为我们只考虑满屋所包含的三种类型。然而,后来检查整个房子还将包括检查一对卡片,因此任何被指派三人的手最终将成为满堂红。

我还要注意的另一件事是,如果你有一个无效的扑克牌,它将自动被赋值为0。

贯穿你的例子,这就是我得到的:

>> out

out =

     2
     1
     3
     6

这说第一手是一对,下一手是高牌,下一对是两对,最后一手是满满的。作为奖励,我们实际上可以输出每只手的字符串:

str = {'Invalid Hand', 'High Card', 'One Pair', 'Two Pair', 'Three of a Kind', 'Straight', 'Full House', 'Four of a Kind'};
hands = str(out+1);

我为无效的手做了一个占位符,如果我们在向量中有合法的手,你只需要为每个索引添加1来访问右手。如果我们没有好手,它会向您显示Invalid Hand字符串。

我们得到了这个字符串:

hands = 

    'One Pair'    'High Card'    'Two Pair'    'Full House'