java - Java 中 ArrayList 扑克游戏的比较

标签 java arraylist poker

问题(简​​短版):如何比较 ArrayList 中的元素?

我已经掌握了 ArrayList 的大部分基础知识(添加、获取、设置、大小...)。我无法进入 ArrayList 来比较对象(扑克牌的值和花色)以确定最佳的扑克牌。我有一个类来存储有关卡片的信息。

卡片类别:

    /** class Card : for creating playing card objects
     *  it is an immutable class.
     *  Rank - valid values are 1 to 13
     *  Suit - valid values are 0 to 3
     *  Do not modify this class!
     */
    class Card {

        /* constant suits and ranks */
        static final String[] Suit = {"Clubs", "Diamonds", "Hearts", "Spades" };
        static final String[] Rank = {"","A","2","3","4","5","6","7","8","9","10","J","Q","K"};

        /* Data field of a card: rank and suit */
        private int cardRank;  /* values: 1-13 (see Rank[] above) */
        private int cardSuit;  /* values: 0-3  (see Suit[] above) */

        /* Constructor to create a card */
        /* throw PlayingCardException if rank or suit is invalid */
        public Card(int rank, int suit) throws PlayingCardException { 
        if ((rank < 1) || (rank > 13))
            throw new PlayingCardException("Invalid rank:"+rank);
        else
                cardRank = rank;
        if ((suit < 0) || (suit > 3))
            throw new PlayingCardException("Invalid suit:"+suit);
        else
                cardSuit = suit;
        }

        /* Accessor and toString */
        /* You may impelemnt equals(), but it will not be used */
        public int getRank() { return cardRank; }
        public int getSuit() { return cardSuit; }
        public String toString() { return Rank[cardRank] + " " + Suit[cardSuit]; }


        /* Few quick tests here */
        public static void main(String args[])
        {
        try {
            Card c1 = new Card(1,3);    // A Spades
            System.out.println(c1);
            c1 = new Card(10,0);    // 10 Clubs
            System.out.println(c1);
            //c1 = new Card(10,5);        // generate exception here
        }
        catch (PlayingCardException e)
        {
            System.out.println("PlayingCardException: "+e.getMessage());
        }
        }
    } 

还有一个检查每手牌的类(这是我无法弄清楚的类)。我目前已经添加了代码来添加一个 ArrayList 并再次打印每只手(只是为了确保我可以创建一个单独的 ArrayList,因为我对自己的能力不太满意),但我不知道如何比较每张牌的元素(点数和花色)。

检查牌型:

/** Check current currentHand using multipliers and goodHandTypes arrays
*  Must print yourHandType (default is "Sorry, you lost") at the end o function.
*  This can be checked by testCheckHands() and main() method.
*/
    private void checkHands()
    {
        // implement this method!
        ArrayList<Card> multiplierCheck = new ArrayList<Card>();
        String yourhandtype = "Sorry, you lost";

        for (int toList = 0; toList<5; toList++) {
                multiplierCheck.add(currentHand.get(toList));
            }
        System.out.println(multiplierCheck);

        System.out.println(yourhandtype);
    }

以及一种测试过牌手牌的方法,该方法可创建获胜手牌(顺子、同花、同种三手牌)。我不知道如何在我的“检查手牌”类(class)中比较这些牌。

testCheckHands()方法

public void testCheckHands()
    {
        try {
            currentHand = new ArrayList<Card>();

        // set Royal Flush
        currentHand.add(new Card(1,3));
        currentHand.add(new Card(10,3));
        currentHand.add(new Card(12,3));
        currentHand.add(new Card(11,3));
        currentHand.add(new Card(13,3));
        System.out.println(currentHand);
            checkHands();
        System.out.println("-----------------------------------");

        // set Straight Flush
        currentHand.set(0,new Card(9,3));
        System.out.println(currentHand);
            checkHands();
        System.out.println("-----------------------------------");

        // set Straight
        currentHand.set(4, new Card(8,1));
        System.out.println(currentHand);
            checkHands();
        System.out.println("-----------------------------------");

        // set Flush 
        currentHand.set(4, new Card(5,3));
        System.out.println(currentHand);
            checkHands();
        System.out.println("-----------------------------------");

        // "Royal Pair" , "Two Pairs" , "Three of a Kind", "Straight", "Flush   ", 
        // "Full House", "Four of a Kind", "Straight Flush", "Royal Flush" };

        // set Four of a Kind
        currentHand.clear();
        currentHand.add(new Card(8,3));
        currentHand.add(new Card(8,0));
        currentHand.add(new Card(12,3));
        currentHand.add(new Card(8,1));
        currentHand.add(new Card(8,2));
        System.out.println(currentHand);
            checkHands();
        System.out.println("-----------------------------------");

        // set Three of a Kind
        currentHand.set(4, new Card(11,3));
        System.out.println(currentHand);
            checkHands();
        System.out.println("-----------------------------------");

        // set Full House
        currentHand.set(2, new Card(11,1));
        System.out.println(currentHand);
            checkHands();
        System.out.println("-----------------------------------");

        // set Two Pairs
        currentHand.set(1, new Card(9,1));
        System.out.println(currentHand);
            checkHands();
        System.out.println("-----------------------------------");

        // set Royal Pair
        currentHand.set(0, new Card(3,1));
        System.out.println(currentHand);
            checkHands();
        System.out.println("-----------------------------------");

        // non Royal Pair
        currentHand.set(2, new Card(3,3));
        System.out.println(currentHand);
            checkHands();
        System.out.println("-----------------------------------");
        }
        catch (Exception e)
        {
        System.out.println(e.getMessage());
        }
    }

最佳答案

要评估扑克牌,您要做的最常见的事情可能是循环遍历数据结构(可以是数组、列表等)并将牌相互比较。例如这里有一些伪Java来比较直:

for (int i = 1; i < /* length of hand */; i++) {

    if (/* rank for card i is not 1 greater
           than rank for card i - 1 */) {

         /* not a straight */
    }
}

请注意,上面假设结构已排序,我将对此进行排序。此外,由于扑克手牌如此不同,因此并没有真正的“最佳方法”来完成所有这些牌局。您必须为每个人编写一个例程。所以我建议你想出一些可以帮助你的抽象概念。我要做的是使用枚举。这是一个基本示例:

enum PokerHand {
    STRAIGHT {
        @Override
        boolean matches(List<Card> hand) {

            for (int i = 1; i < hand.size(); i++) {
                if (
                    card.get(i).getRank() !=
                    card.get(i - 1).getRank() + 1
                ) {
                    return false;
                }
            }

            return true;
        }
    },
    FOUR_OF_A_KIND {
        @Override
        boolean matches(List<Card> hand) {

            int[] rankCount = new int[14];

            /* count up the ranks in the hand */
            for (Card card : hand) {
                rankCount[card.getRank()]++;
            }

            boolean foundHasOne = false;
            boolean foundHasFour = false;

            /* now evaluate exclusively
             * there must be only a 1 count and a 4 count
             */
            for (int i = 1; i < rankCount.length; i++) {

                if (rankCount[i] == 1) {
                    if (!foundHasOne) {
                        foundHasOne = true;
                    } else {
                        return false;
                    }

                } else if (rankCount[i] == 4) {
                    if (!foundHasFour) {
                        foundHasFour = true;
                    } else {
                        return false;
                    }

                } else if (rankCount[i] != 0) {
                    return false;
                }
            }

            return true;
        }
    },
    ROYAL_FLUSH {
        final int[] rfRanks = {
            1, 10, 11, 12, 13
        };

        @Override
        boolean matches(List<Card> hand) {

            for (int i = 0; i < rfRanks.length; i++) {
                if (rfRanks[i] != hand.get(i).getRank())
                    return false;
            }

            return true;
        }
    };

    abstract boolean matches(List<Card> hand);
}

当然,以上内容并未涵盖所有扑克牌局,仅举几个例子。另外,我不玩扑克,所以这些可能有点错误,但重点是展示一些评估示例。

正如我之前所说,如果您提前对列表进行排序,这会变得更加简单。 java.util.Collections 和 java.util.Arrays 具有用于此目的的实用方法,因此它相当简单。如果您不希望在检查手牌后继续保持排序,请确保在排序之前制作一份副本。

/* make a shallow copy */
List<Card> sortedHand = new ArrayList<Card>(playerHand);

/* sort based on rank */
Collections.sort(sortedHand, new Comparator<Card>() {
    @Override
    public int compare(Card card1, Card card2) {
        int rank1 = card1.getRank();
        int rank2 = card2.getRank();

        if (rank1 > rank2) {
            return 1;

        if (rank1 < rank2)
            return -1;

        return 0;
    }
});

参见Comparator#compare有关其工作原理的描述,但这基本上就是排序。

使用枚举或类似的东西会使评估在逻辑上变得相当简单。

现在我建议制定一个评估方法,因为这样你就可以方便地返回手牌的常量。

static PokerHand evaluateHand(List<Card> hand) {
    for (PokerHand potential : PokerHand.values()) {
        if (potential.matches(hand))
            return potential;
    }

    /* imply there is not a matching hand */
    return null;
}

因此,在制作手牌副本并对其进行排序后,您可以调用对其进行评估:

PokerHand evaluated = evaluateHand(sortedHand);

if (evaluated != null) {
    /* it's a recognized hand */
}

您不必创建方法,您可以执行如下操作:

PokerHand evaluated = null;
for (PokerHand potential : PokerHand.values()) {
    if (potential.matches(sortedHand)) {
        evaluated = potential;
        break;
    }
}

if (evaluated != null) {
    /* it's a recognized hand */
}

但是使用辅助方法有助于组织您的代码。

我希望这会有所帮助。如果您还需要对牌进行评分来决定是否有获胜者,只需向返回分数的枚举添加另一个方法即可。然后看看哪一个最大。

关于java - Java 中 ArrayList 扑克游戏的比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20578235/

相关文章:

java - 为什么我的 bufferedReader 从文本文件中读取 `java.lang.String;@70177ecd` ?

java - 测试失败时如何使用 Log4j 写入日志文件

java - TimerTask 的问题

java - 为什么整数除法代码给出错误的答案?

java - 为什么循环前索引会增加

java - 抽象类和嵌套类的ArrayList冲突

java - 从服务器接收测验 JSON 字符串并显示在屏幕上

javascript - 扑克牌生成器和评估器

security - 击败扑克机器人

java - (如何操作)Poker Positioning using ENUM