代码之家  ›  专栏  ›  技术社区  ›  Logan Serman

确定扑克手牌是否为直牌的功能?

  •  7
  • Logan Serman  · 技术社区  · 17 年前

    在一次家庭作业中,我上了一门卡片课,上面列举了等级和花色的类型。我需要比较两个扑克手(每只手都是一个 ArrayList 5张牌)并决定获胜者。

    这个 isStraight() 函数真的让我很困扰,因为我必须在Ace之后重新开始计数。例如,

    女王,国王,王牌,二,三

    仍然被认为是直的。编写此功能的最佳方式是什么?

    如果有帮助的话,这是Rank/Suit枚举类型代码。

    public enum Rank
    {
        TWO(2), THREE(3), FOUR(4), FIVE(5), SIX(6), SEVEN(7), EIGHT(8), NINE(9),
        TEN(10), JACK(11), QUEEN(12), KING(13), ACE(14);
    
        private final int points;
    
        private Rank(int points)
        {
            this.points = points;
        }
    
        public int points()
        {
            return this.points;
        }
    }
    
    public enum Suit
    {
        DIAMONDS, CLUBS, HEARTS, SPADES;
    }
    
    10 回复  |  直到 14 年前
        1
  •  10
  •   shsteimer    17 年前

    你知道吗,根据我玩过或听说过的任何扑克游戏的规则,直投都不能打对?Ace可以是低[A,2,3,4,5]或高[10,J,Q,K,A],但它不能包裹。根据这些规则(不是你的),我以前也实施过类似的事情。基本上,你对数组进行排序并遍历它,确保当前的卡片比前一张高。在第一次迭代中,如果它是一个ace,那么你显式地检查[A,2,3,4,5]。如果是,则返回true,如果不是,则继续正常的直接逻辑。这应该会让你走上正确的方向。

        2
  •  5
  •   Austin Salonen gmlacrosse    13 年前

    你可以编写一个花哨的算法,不管可能有多少张牌,都能返回true,但如果你意识到排序后的手牌上只有10个有效的组合,你可以找这些:

    2-6, 3-7, 4-8, 5-9, 6-T, 7-J, 8-Q, 9-K, T-A, (2-5,A)
    
        3
  •  3
  •   supercat    14 年前

    一般来说,解决扑克手牌问题的一个好方法是为每张牌分配一个位值,设置位((rank-2)*2)位和位(suit+28)位(因此2=1,3=4,4=16等,直到A=0x1000000)。然后将所有卡片加在一起(将结果称为“Sum”。计算V1=(Sum&0x2AAAAAA)>>1,V0=(求和&0x1555555),V2=V1&V0。同时,将五张牌的值相加,并计算V3=OrValue&0xF000000;

    1. 对于一对,V1将设置一个比特,V0将设置多个比特,V2将为零。
    2. 对于两对,V1将设置两个比特,V2将等于零。
    3. 对于三类,V1将有一个比特集,V2将等于V1。
    4. 对于直线,V0要么是0x1000055,要么是0x155的两倍的幂。
    5. 对于刷新,V2将精确地设置一个位。
    6. 对于满屋子的情况,V1将设置两个比特,V2将为非零。
    7. 对于四类,V1将是v0的两倍,两者都有一个比特集,或者v0将恰好有两个比特集并且V1将为零。
    8. 对于直接冲洗,将满足直接冲洗和冲洗的条件。

    这种方法所需的测试应该可以用最少的分支快速实现。

        4
  •  2
  •   Rik elirevach    17 年前

    由于你的列表中只有5张牌,你可以对其进行排序,并确定连续2张牌之间的差异。如果它包含一张王牌,你也需要将其视为一张低牌。如果所有的差异都是1(或-1,取决于排序顺序),那么你就得到了你的直线。

        5
  •  0
  •   Instantsoup    17 年前

    我认为,根据RANK的定义,直道只能从ACE.points()-4的最大值开始。

    因此,如果您对手部进行排序,最低RANK为>ACE.points()-4,那么你就不能有一条直线,否则你只需迭代手牌,看看每张牌都是之前的RANK+1。

    如果ACE可以高或低,那么就按照SHS的回答。

        6
  •  0
  •   Bill K    17 年前

    有了内环,它就变得相当微不足道,挑战在于在没有内环的情况下做到这一点。..

    此外,这取决于你是否理解你的老师,或者你的老师是否误解(或歪曲)了游戏规则。

    我想我会忍不住创建一个数组[2..14],并将卡片放置在与它们的排名相对应的位置。如果你点击了一个重复,它就不是直线,当你完成时,你应该有8个空格。如果你一排的空格少于8个,那就不是直线。

    我能想到的所有其他解决方案都需要一个内部循环——如果你想成为一名受人尊敬的程序员,内部循环是你需要尽可能避免的草率编程之一。

    编辑:此外,如果你误解了老师,唯一的包装条件是“10,j,q,k,a”(就像在真实的规则中一样),那么你需要进行一个额外的测试,如果2、13和14都设置好了,这也是一个失败(2-a-k包装)。

    (重读问题后,再次编辑,将ace的1替换为14)

        7
  •  0
  •   Eric    17 年前

    我不太使用枚举,我更喜欢命名常量,但我认为从“ACE”到“14”是微不足道的

    我懒得写真正的java代码(其实你还得做功课^^)

    check if the list has 5 cards
    convert card names to a card number list named array
    sort the list array
    for i=1 to 4
    if not (array[i] + 1) % 13 == (array[i+1]) % 13
    then it is not a straight
    

    %运算符称为模,因此(15%13)==2 每当我面临“覆盖”挑战时,我都会使用这个运算符

    编辑:重读你的问题后,我的答案无法开箱即用。您应该重新排序枚举,使TWO==0

        8
  •  0
  •   hacken    17 年前

    我建议使用位向量来表示卡片。这避免了排序。你可以两次添加ace(一次作为1,另一次作为国王),或者你可以在检查2是否设置之前检查ace位是否设置,从而对起始情况进行特殊处理)。如果速度很重要,你可以建立一个大的查找表。这种方法还可以清洁鳞片,找到剩下的手(冲水、两双、满屋、绊倒等)。它还可以很容易地找出给定的直线是否高于另一条直线。它干净地扩展到7个卡片评估器

    在伪代码中,对于非常一般的情况,它看起来像这样(你可以有任意数量的卡。它返回第一条直线)

     long cardBitMask
     for each card in hand
       setBit in cardBitMask
    
     hearts = mask(cardBitMask)
     diamonds = mask(cardBitMask)
     clubs = mask(cardBitMask)
     spades = mask(cardBitMask)
    
     // find straight
     uniqueCards = hearts|diamonds|clubs|spades
     int cardsInaRow = 0
     if uniqueCards&AceCardMask:
        cardsInaRow = 1
     for card = 2...King
       if uniqueCards&(1<<card)
          cardsInARow++
       else 
          if cardsInARow == 5
             break
          cardsInARow = 0
     if cardsInARow==5:
         return true
     return false
    
        9
  •  0
  •   Apocalisp    17 年前

    将所有排名按顺序添加到列表中,两次。然后,要检查一只手是否是直的,请按排名对手进行排序,然后检查该手是否是该列表的子列表。

        10
  •  -2
  •   Germán Rodríguez    17 年前

    你可以编写一个类,将每张卡转换为特定的卡值

    小丑=11 女王=12 国王=13 Ace=0或14

    这将使卡片处理和寻找可能的手变得容易得多。