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?
答案 0 :(得分:6)
bsxfun
对这种情况不起作用。这是计数问题。这都是计算你拥有的东西的问题。具体来说,扑克牌手可以计算每张牌的数量,并找出正确的计数组合以获得有效牌。这里有一张漂亮的照片,向我们展示了人类所知道的每一个可能的扑克牌:
http://www.bestonlinecasino.tips/wp-content/uploads/2013/07/poker-hand-rankings3.png
来源:http://www.bestonlinecasino.tips
因为我们的矩阵中没有套装,所以我会忽略皇家同花顺,同花顺和同花顺场景。你想要识别的每一只手都可以用每行的直方图从1到13的二进制位,并确定是否(按排名顺序):
因此,根据您的MATLAB版本,使用histc
或histcounts
查找手的直方图。我还会在每一行上预先排序,以便在找到直线时简化操作。您在帖子中提到矩阵是预先排序的,但我会假设它可能没有排序的一般情况。
因此,这里有一些预处理代码,因为您的矩阵在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'