使用Java对扑克手进行分类

问题描述 投票:0回答:3

我目前正在进行一个CS项目,该项目对玩家的手进行了分类。我解决了项目的前半部分,以打印出牌组,混洗的牌组以及玩家1,玩家2和其余牌组的手牌。当我必须评估双手时出现问题。我的代码必须以某种方式评估手牌的类别,并打印出玩家1或玩家2获胜。到目前为止,我有三堂课:

public class Card {

    static String[] card_suit = {"hearts", "diamonds", "clubs", "spades"};

    static int[] card_rank = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};// 11 is Jack, 12 is Queen, 13 is King and 14 is Ace 

    public int[] getRank() {
        return card_rank;
    }
    public String[] getSuit() {
        return card_suit;
    }
}
public class Driver {

    public static void main(String[] args) {
        Card card = new Card();
        Deck deck = new Deck();

        deck.getDeck();
        System.out.print("ORIGINAL DECK: ");
        deck.printDeck();
        deck.shuffleDeck();
        System.out.print("SHUFFLED DECK: ");
        deck.printDeck();

        System.out.println();


        System.out.print("PLAYER ONE: ");
        System.out.println(java.util.Arrays.toString(deck.playerOneHands()));
        System.out.print("PLAYER TWO: ");
        System.out.println(java.util.Arrays.toString(deck.playerTwoHands()));
        System.out.print("REMAINING DECK: ");
        System.out.println(java.util.Arrays.toString(deck.remainingDeckCards()));               
        }

}
import java.util.Arrays;
import java.util.Collections;

public class Deck extends Card {

    Card card = new Card();

    private String[] deck_card = new String[52];

    public String[] getDeck() {
        int i = 0;
        for(int s = 0; s < 4; s++) {
            for(int r = 0; r < 13; r++) {
                deck_card[i]=(card_suit[s] + " of " + card_rank[r]);
                i++;
                }

            }
        return deck_card;
    }

    public void printDeck() {
        System.out.println (java.util.Arrays.toString (deck_card));
    }

    public void shuffleDeck() {
        Collections.shuffle(Arrays.asList(deck_card));
    }

    public String[] playerOneHands() {
        String [] firsthand = new String[5];
        for(int a = 0; a < 5; a++) {
            firsthand[a] = deck_card[a];
        }
        return firsthand;
    }

    public String[] playerTwoHands() {
        String[] secondhand = new String[5];
        for(int a = 0; a < 5; a++) {
            secondhand[a] = deck_card[a+5];
        }
        return secondhand;
    }

    public String[] remainingDeckCards() {
        String[] remainDeck = new String[42];
        for(int a = 0; a < 42; a++){
            remainDeck[a] = deck_card[a+10];
        }
        return remainDeck;
    }

}

我认为这是可行的,因为Deck类是Card类的扩展,我可以使用getRank方法比较每只手,但是我不确定如何构造条件。

非常感谢您的帮助。谢谢。

java arrays oop poker
3个回答
1
投票
  1. 为了对游戏进行建模,请首先标识诸如CardDeck等(大多数情况下已完成)的实体。我还要添加一些其他内容,例如PlayerEvaluator(下面解释)等。
  2. [Rank and Suit不是string / int,但是它们是预定义的(不会改变游戏的生存时间)在Cards中可能的变化。始终使用领域词汇表作为最佳模型。每张卡属于一个西服和一个等级。 (考虑将Rank和Suit设为枚举,这将避免在运行时未知值破坏代码。
  3. 不给卡中的套房和等级设定方法是必不可少的(它们结合在一起构成卡的身份)
  4. Full Deck(在初始化时)由Suit和Rank的叉积形成。含义Deck有(包含)多个卡。请记住,卡牌也可以在Deck外面(在玩家手中时)还活着,因此不是组成牌。从Card继承Deck是绝对错误的。它转换为语句Deck是卡的一种,这是不正确的。甲板将收集卡片。使用继承,将导致违反Liskov的替代原则(SOLID之一)。
  5. 要为Deck建模,请考虑Deck不包含重复卡片的事实,Deck形成后不会更改其顺序(除非混洗)。这是Set和List之间的棘手选择,我会选择具有附加编程约束的List来避免重复(仅在初始化时才需要这样做)。
  6. 但是最好将类Deck包含适当选择的Java集合,并通过定义必需的API(从域角度)像shuffle,getTopCard()等使Deck类作为包装器,而不是将Deck建模为java集合。这是称为对象适配器设计模式。这使我们的设计平台(实现)独立。
  7. 您需要建模更多的类,例如Player持有CardInHand等。
  8. 关于评估手牌,最好将其建模为单独的类,因为其不同的关注点和规则可以独立于其他类而改变。
  9. 扑克游戏是学习面向对象编程的最佳作业。

1
投票

不想为您做作业...

这是一个问题:

class Deck extends Card

卡片组不是卡片的子类型。一副牌组[[has牌,所以:

class Deck { List<Card> cards; }
是更好的选择。

此外,以下代码对平台没有任何作用:

public void shuffleDeck() { Collections.shuffle(Arrays.asList(deck_card)); }

它打乱了甲板的

副本

,而保持甲板不变。此外,您不应该在循环中构建字符串。而是在Card and Deck上实现(重写)toString()方法。

另外,将enum作为西装。

也请完全删除card_rank-它没有用。而是将int rank;字段添加到Card中,或者最好将排名设为enum

先解决这些问题,然后编写传递给具有List的Hand(一个新类)的方法,并通过评估该手是否为直线来返回HandType(另一个枚举)的方法,以重新攻击该问题。同花顺,否则四种,直到高牌-从高到低。


0
投票
似乎您的班级Card只有静态字段;我将其更改为Card的实例代表Deck中的一张卡。我也将套件设置为enum类型。您还可以为数字和ace添加整数常量。该类可以实现Comparable<Card>

public class Card implements Comparable<Card> { public enum Suite {CLUBS, DIAMONDS, HEARTS, SPADES}; public static final int JACK = 11; public static final int QUEEN = 12; public static final int KING = 13; public static final int ACE = 14; public final Suite suite; public final int rank; public Card(Suite suite, int rank) { if (suite == null) { throw new IllegalArgumentException("Suite cannot be null"); } if (rank < 2 || rank > 14) { throw new IllegalArgumentException( "Value must be between 2 and 14"); } this.suite = suite; this.rank = rank; } public Suite getSuite() { return suite; } public int getRank() { return rank; } @Override public String toString() { StringBuilder buf = new StringBuilder(); if (rank >= 2 && rank <= 10) { buf.append(rank); } else { switch (rank) { case JACK: buf.append("jack"); break; case QUEEN: buf.append("queen"); break; case KING: buf.append("king"); break; case ACE: buf.append("ace"); break; } } buf.append(" of "); buf.append(suite.toString().toLowerCase()); return buf.toString(); } @Override public int compareTo(Card other) { if (rank > other.rank) { return 1; } else if (rank < other.rank) { return -1; } else { return suite.compareTo(other.suite); } } }

请注意,您还可以具有Card的两个子类:一个代表数字,另一个代表数字。 

Deck是52张卡片的集合。通过将每张卡添加到列表中进行初始化。一个人可以shuffle一个牌组,或take一张牌组中的一张牌:

public class Deck { private final List<Card> cards = new ArrayList<>(); public Deck() { for (Card.Suite suite: Card.Suite.values()) { for (int i = 2; i <= 14; ++i) { cards.add(new Card(suite,i)); } } } public void shuffle() { Collections.shuffle(cards); } public boolean isEmpty() { return cards.isEmpty(); } public Card take() { if (cards.isEmpty()) { throw new IllegalStateException("Deck is empty"); } return cards.remove(0); } }

您可以像这样从牌堆中随机抽出5张牌:

Deck deck = new Deck(); deck.shuffle(); for (int i = 0; i < 5; ++i) { Card card = deck.take(); System.out.println(card); }

现在Hand是从Deck中取出的五张牌的集合。我们可以将Hand声明为实现Comparable<Hand>,以便我们可以知道两只手中哪个具有最高价值:

public class Hand implements Comparable<Hand> { private final Card[] cards = new Card[5]; public Hand(Deck deck) { for (int i = 0; i < 5; ++i) { cards[i] = deck.take(); } Arrays.sort(cards); } @Override public int compareTo(Hand other) { ... } }

现在是有趣的部分:您必须将手的类型识别为以下之一(枚举类型):

public enum HandType { SINGLE, PAIR, TWO_PAIRS, THREE, STRAIGHT, FLUSH, FULL_HOUSE, FOUR, STRAIGHT_FLUSH, ROYAL_FLUSH; }

注意,常数从最低到最高排列。另外,必须对卡片进行整理,以便在出现平局的情况下,您可以比较卡片以识别获胜者。

我建议您将几组相同等级的卡;如果您有五个不同的组,则仍然可以是同花或顺子。

另一种方法是为每个Hand声明一个HandType的子类,但我认为这样做不会带来很多好处。

public class Hand implements Comparable<Hand> { public enum HandType { SINGLE, PAIR, TWO_PAIRS, THREE, STRAIGHT, FLUSH, FULL_HOUSE, FOUR, STRAIGHT_FLUSH, ROYAL_FLUSH; } private final Card[] cards = new Card[5]; private final int[] groupSize; private final HandType type; public Hand(Deck deck) { for (int i = 0; i < 5; ++i) { cards[i] = deck.take(); } groupSize = group(cards); type = identifyType(groupSize, cards); } @Override public int compareTo(Hand other) { int r = type.compareTo(other.type); if (r != 0) { return r; } for (int i = cards.length; --i >= 0; ) { int r1 = cards[i].getRank(); int r2 = other.cards[i].getRank(); if (r1 < r2) { return -1; } else if (r1 > r2) { return 1; } } return 0; } @Override public String toString() { StringBuilder buf = new StringBuilder(); buf.append(type); buf.append(": "); buf.append(cards[0]); for (int i = 1; i < 5; ++i) { buf.append(", "); buf.append(cards[i]); } return buf.toString(); } private static int[] group(Card[] cards) { Arrays.sort(cards); List<List<Card>> groups = new ArrayList<>(); int val = -1; // invalid rank List<Card> currentGroup = null; for (Card card: cards) { if (val == card.getRank()) { currentGroup.add(card); } else { if (currentGroup != null) { groups.add(currentGroup); } currentGroup = new ArrayList<>(); currentGroup.add(card); val = card.getRank(); } } if (currentGroup != null) { groups.add(currentGroup); } // identify groups of cards of same value // sort groups by size and highest card Collections.sort(groups, (List<Card> group1, List<Card> group2) -> { int s1 = group1.size(); int s2 = group2.size(); if (s1 < s2) { return -1; } else if (s1 > s2) { return 1; } else { return group1.get(s1-1).compareTo(group2.get(s2-1)); } }); int[] groupSize = new int[groups.size()]; int g = 0; int i = 0; for (List<Card> group: groups) { groupSize[g++] = group.size(); for (Card card: group) { cards[i++] = card; } } assert sum(groupSize) == 5; return groupSize; } private static HandType identifyType(int[] groupSize, Card[] cards) { switch (groupSize.length) { case 2: // can be a full house or four cards if (groupSize[0] == 1) { return HandType.FOUR; } else if (groupSize[0] == 2) { return HandType.FULL_HOUSE; } else { assert false; return null; } case 3: if (groupSize[0] == 1) { // three cards or double pair if (groupSize[1] == 1) { return HandType.THREE; } else { assert groupSize[1] == 2 && groupSize[2] == 2; return HandType.TWO_PAIRS; } } else { assert false; return null; } case 4: // one pair return HandType.PAIR; case 5: // all different values: check for flush Card prev = cards[0]; boolean sameSuite = true; boolean straight = true; for (int i = 1; i < 5; ++i) { Card card = cards[i]; straight &= card.getRank() == prev.getRank()+1; sameSuite &= card.getSuite() == prev.getSuite(); } if (sameSuite) { if (straight) { if (cards[4].getRank() == Card.ACE) { return HandType.ROYAL_FLUSH; } return HandType.STRAIGHT_FLUSH; } else { return HandType.FLUSH; } } else { if (straight) { return HandType.STRAIGHT; } else { return HandType.SINGLE; } } default: assert false; return null; } } private static int sum(int[] groupSize) { int sum = 0; for (int s: groupSize) { sum += s; } return sum; } }

© www.soinside.com 2019 - 2024. All rights reserved.