Ranking Poker Hands

泪湿孤枕 提交于 2020-04-21 20:51:15

地址:https://www.codewars.com/kata/5739174624fc28e188000465/java

总结:不好写,各种牌的可能的情况都要考虑到,同种牌型之间还需要比较牌的大小。

package codewar;

import java.util.*;
import java.util.stream.Collectors;

// https://www.codewars.com/kata/5739174624fc28e188000465/train/java
public class PokerHand {
    static char[] CARDS = new char[]{'2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A'};
    static Map<Character, Integer> VALUES = new HashMap<>();

    static {
        int i = 0;
        for (char c : CARDS) {
            VALUES.put(c, i++);
        }
    }

    static char[] SUITS = new char[]{'S', 'H', 'D', 'C'};

    public enum Result {TIE, WIN, LOSS}

    Set<String> cards;
    Map<Character, Integer> cardCount = new HashMap<>();
    List<Integer> value = new ArrayList<>();

    PokerHand(String hand) {
        this.cards = new HashSet<>(Arrays.asList(hand.split(" ")));
        cards.forEach(a -> {
            cardCount.put(a.charAt(0), 1 + cardCount.getOrDefault(a.charAt(0), 0));
        });
        computeValue();
    }

    public Result compareWith(PokerHand hand) {
        int len = Math.min(hand.value.size(), value.size());
        for (int i = 0; i < len; i++) {
            if (value.get(i) > hand.value.get(i)) {
                return Result.WIN;
            }
            if (value.get(i) < hand.value.get(i)) {
                return Result.LOSS;
            }
        }
        return Result.TIE;
    }

    public void computeValue() {
        if (royalFlush()) {
            value.add(10);
        } else if (straightFlush()) {
            value.add(9);
            value.addAll(cardValueWithNumber(1));
        } else if (fourOfKind()) {
            value.add(8);
            value.addAll(cardValueWithNumber(4));
            value.addAll(cardValueWithNumber(1));
        } else if (fullHouse()) {
            value.add(7);
            value.addAll(cardValueWithNumber(3));
            value.addAll(cardValueWithNumber(2));
        } else if (flush()) {
            value.add(6);
            value.addAll(cardValueWithNumber(1));
        } else if (straight()) {
            value.add(5);
            value.addAll(cardValueWithNumber(1));
        } else if (threeOfKind()) {
            value.add(4);
            value.addAll(cardValueWithNumber(3));
            value.addAll(cardValueWithNumber(1));
        } else if (twoPair()) {
            value.add(3);
            value.addAll(cardValueWithNumber(2));
            value.addAll(cardValueWithNumber(1));
        } else if (onePair()) {
            value.add(2);
            value.addAll(cardValueWithNumber(2));
            value.addAll(cardValueWithNumber(1));
        } else {
            value.add(1);
            value.addAll(cardValueWithNumber(1));
        }
    }

    List<Character> exactNumberOfCard(int n) {
        List<Character> result = new ArrayList<>();
        for (char card : cardCount.keySet()) {
            if (cardCount.get(card) == n) {
                result.add(card);
            }
        }
        return result;
    }

    List<Integer> cardValueWithNumber(int number) {
        List<Character> cs = exactNumberOfCard(number);
        return cs.stream()
                .map(c -> VALUES.get(c))
                .sorted(Collections.reverseOrder())
                .collect(Collectors.toList());
    }

    boolean containsCard(char card, char suit) {
        return cards.contains(card + "" + suit);
    }

    boolean containsCard(char card) {
        for (char suit : SUITS) {
            if (cards.contains(card + "" + suit)) {
                return true;
            }
        }
        return false;
    }

    boolean royalFlush() {
        for (char suit : SUITS) {
            char[] C = {'A', 'K', 'Q', 'J', 'T'};
            int cnt = 0;
            for (char c : C) {
                if (containsCard(c, suit)) {
                    cnt += 1;
                } else {
                    break;
                }
            }
            if (cnt == 5) {
                return true;
            }
        }
        return false;
    }

    boolean straightFlush() {
        for (char suit : SUITS) {
            int i = 0;
            while (i < CARDS.length) {
                while (i < CARDS.length && !containsCard(CARDS[i], suit)) {
                    i++;
                }
                int cnt = 0;
                int tmp = i;
                i += 1;
                while (tmp < CARDS.length && containsCard(CARDS[tmp], suit)) {
                    cnt += 1;
                    tmp += 1;
                }
                if (cnt == 5) {
                    return true;
                }
            }
        }
        return false;
    }

    // contains the number of card with same suit
    boolean numberOfKind(int n) {
        return cardCount.containsValue(n);
    }

    boolean fourOfKind() {
        return numberOfKind(4);
    }

    boolean fullHouse() {
        return numberOfKind(3) && numberOfKind(2);
    }

    boolean flush() {
        for (char suit : SUITS) {
            int cnt = 0;
            for (char card : cardCount.keySet()) {
                if (containsCard(card, suit)) {
                    cnt += 1;
                }
            }
            if (cnt == 5) {
                return true;
            }
        }
        return false;
    }

    boolean straight() {
        int i = 0;
        while (i < CARDS.length) {
            while (i < CARDS.length && !containsCard(CARDS[i])) {
                i += 1;
            }
            int tmp = i;
            i += 1;
            int cnt = 0;
            while (tmp < CARDS.length && containsCard(CARDS[tmp])) {
                cnt += 1;
                tmp += 1;
            }
            if (cnt == 5) {
                return true;
            }
        }
        return false;
    }

    boolean threeOfKind() {
        return numberOfKind(3) && exactNumberOfCard(1).size() == 2;
    }

    boolean twoPair() {
        return exactNumberOfCard(2).size() == 2 && exactNumberOfCard(1).size() == 1;
    }

    boolean onePair() {
        return exactNumberOfCard(2).size() == 1 && exactNumberOfCard(1).size() == 3;
    }

}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!