已解决:问题最终不在于排序,而是在我不断添加经销商卡但从未删除的循环中。最终导致两次向经销商分发同一张卡片(或多次),从而导致明显的分类问题。

因此,我要对此类进行排序:

public class Card implements Comparable<Card> {
    private int suit;
    private int numeral;
    private int ID;

    public Card(int cardNo) {
        assert cardNo >= 0;
        assert cardNo < 52;
        this.suit = cardNo % 4;
        this.numeral = cardNo / 4;
        this.ID = cardNo;
    }

    public int compareTo(Card otherCard) {
        return Integer.compare(this.ID, otherCard.ID);
    }

public int getSuit() {
    return this.suit;
}

public int getNumeral() {
    return this.numeral;
}

    public String toString() {
        String[] suits = {"C", "D", "H", "S"};
        //String[] suits = {"♣", "♦", "♥", "♠"}; //clubs, diamonds, hearts, spades
        String[] numerals = {"2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K", "A"};
        return numerals[this.getNumeral()] + suits[this.getSuit()];
    }
}


当我稍后创建一个列表并对其进行排序时,排序似乎已中断。这是一个示例:2H 2S 3C 3D 3H 3S 4C分为2H 2S 3C 3D 3H 3S 3S。

如您所见,它创建了3S的副本,并完全摆脱了4C。我究竟做错了什么?

编辑:这是它打破的部分:

List<Card> sortedHand = new ArrayList<>(sevenCardHand);
System.out.println(sortedHand.get(0).toString() + " " + sortedHand.get(1).toString() + " " +
        sortedHand.get(2).toString() + " " + sortedHand.get(3).toString() + " " + sortedHand.get(4).toString() +
        " " + sortedHand.get(5).toString() + " " + sortedHand.get(6).toString() + "potato");
Collections.sort(sortedHand);
System.out.println(sortedHand.get(0).toString() + " " + sortedHand.get(1).toString() + " " +
        sortedHand.get(2).toString() + " " + sortedHand.get(3).toString() + " " + sortedHand.get(4).toString() +
        " " + sortedHand.get(5).toString() + " " + sortedHand.get(6).toString() + "tomato");


没有遗漏的代码,因此不应执行其他任何操作(因为这是一个线程),但是第二个打印输出具有重复的卡,而第一个打印输出则没有。更奇怪的是,我无法在单元测试中复制它。

EDIT2:这是完整的代码,如描述的那样中断(使用上面的Card类)

@Test
void run() {
    SevenCardEvaluator sce = new SevenCardEvaluator();
    List<Card> deck = createDeck();
    Card playerCard2 = new Card(1);
    Card playerCard1 = new Card(0);
    deck.remove(playerCard2.getNumeral());
    deck.remove(playerCard1.getNumeral());
    for (int a = 0; a < 46; a++) {
        for (int b = a + 1; b < 47; b++) {
            for (int c = b + 1; c < 48; c++) {
                for (int d = c + 1; d < 49; d++) {
                    for (int e = d + 1; e < 50; e++) {
                        List<Card> playerHand = new ArrayList<>();
                        playerHand.add(playerCard1);
                        playerHand.add(playerCard2);
                        playerHand.add(deck.get(a));
                        playerHand.add(deck.get(b));
                        playerHand.add(deck.get(c));
                        playerHand.add(deck.get(d));
                        playerHand.add(deck.get(e));
                        int playerHandValue = sce.evaluate(playerHand);
                        List<Card> dealerDeck = new ArrayList<>(deck);
                        dealerDeck.remove(e);
                        dealerDeck.remove(d);
                        dealerDeck.remove(c);
                        dealerDeck.remove(b);
                        dealerDeck.remove(a);
                        List<Card> dealerHand = new ArrayList<>();
                        dealerHand.add(deck.get(a));
                        dealerHand.add(deck.get(b));
                        dealerHand.add(deck.get(c));
                        dealerHand.add(deck.get(d));
                        dealerHand.add(deck.get(e));
                        for (int i = 0; i < 44; i++) {
                            for (int j = i + 1; j < 45; j++) {
                                dealerHand.add(dealerDeck.get(i));
                                dealerHand.add(dealerDeck.get(j));
                                int dealerHandValue = sce.evaluate(dealerHand);
                                int playerWin = evaluateWin(playerHandValue, dealerHandValue);
                                addResult(playerWin, new int[]{deck.get(a).getNumeral(), deck.get(b).getNumeral(), deck.get(c).getNumeral(),
                                        deck.get(d).getNumeral(), deck.get(e).getNumeral()});
                            }
                        }
                    }
                }
            }
        }
    }
}

List<Card> createDeck(){
    List<Card> deck = new ArrayList<>();
    for(int i = 0; i<52; i++){
        deck.add(new Card(i));
    }
    return deck;
}

int evaluateWin(int playerHandValue, int dealerHandValue){
    return 0; //dummy method
}

void addResult(int win, int[] cardIndices){
    //dummy method
}


这是它使用的SevenCardEvaluator类:

public class SevenCardEvaluator {
    public SevenCardEvaluator(){}
    public int evaluate(List<Card> sevenCardHand){
        List<Card> sortedHand = new ArrayList<>(sevenCardHand);
        System.out.println(sortedHand.get(0).toString() + " " + sortedHand.get(1).toString() + " " +
                sortedHand.get(2).toString() + " " + sortedHand.get(3).toString() + " " + sortedHand.get(4).toString() +
                " " + sortedHand.get(5).toString() + " " + sortedHand.get(6).toString() + "potato");
        Collections.sort(sortedHand);
        System.out.println(sortedHand.get(0).toString() + " " + sortedHand.get(1).toString() + " " +
                sortedHand.get(2).toString() + " " + sortedHand.get(3).toString() + " " + sortedHand.get(4).toString() +
                " " + sortedHand.get(5).toString() + " " + sortedHand.get(6).toString() + "tomato");
//dummy class
        return -1;
    }
}

最佳答案

很长的帖子很抱歉,但是精心设计的对象模型可能会走很长一段路。如果您将卡座和指针容器化,则可以在分发卡并将其插入时互换使用。

以下是您可以在下面找到的类:


AbstractDeck.java
Actions.java
Card.java
CardHolder.java
Casino.java
Container.java
Deck.java
Hand.java
Player.java
TexasHoldem.java


赌场

一个驱动程序,用于洗牌,向玩家分发卡并对其手进行排序。

package casino;

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

public class Casino {
    public static void main(String[] args) {
        List<Player> players = Arrays.asList("Bob", "Jill", "Thomas").stream()
                .map(Player::new).collect(Collectors.toList());
        TexasHoldem holdem = new TexasHoldem();

        holdem.dealCards(players, 2);
        holdem.sortHands(players);
        holdem.play(players);
        holdem.printInfo(players);
    }
}


乌普特

# FLOP
Player [name=Bob, hand=Hand [cards=[5S, JS]]] => Hand [cards=[5S, 7D, JD, JS, QD]]
Player [name=Jill, hand=Hand [cards=[9H, AH]]] => Hand [cards=[7D, 9H, JD, QD, AH]]
Player [name=Thomas, hand=Hand [cards=[4C, 8S]]] => Hand [cards=[4C, 7D, 8S, JD, QD]]

# TURN
Player [name=Bob, hand=Hand [cards=[5S, JS]]] => Hand [cards=[5H, 5S, 7D, JD, JS, QD]]
Player [name=Jill, hand=Hand [cards=[9H, AH]]] => Hand [cards=[5H, 7D, 9H, JD, QD, AH]]
Player [name=Thomas, hand=Hand [cards=[4C, 8S]]] => Hand [cards=[4C, 5H, 7D, 8S, JD, QD]]

# RIVER
Player [name=Bob, hand=Hand [cards=[5S, JS]]] => Hand [cards=[5H, 5S, 6C, 7D, JD, JS, QD]]
Player [name=Jill, hand=Hand [cards=[9H, AH]]] => Hand [cards=[5H, 6C, 7D, 9H, JD, QD, AH]]
Player [name=Thomas, hand=Hand [cards=[4C, 8S]]] => Hand [cards=[4C, 5H, 6C, 7D, 8S, JD, QD]]

# INFO
Deck [cards=[8C, TS, 3C, AD, QH, 7C, QC, 8D, TH, 4H, 4S, 6H, 2S, 6S, KC, TC, 3H, 4D, KS, 8H, JC, 9D, KH, 5D, TD, 2C, QS, KD, AC, 7S, 7H, 3S, JH, 2D, 2H, 3D, 5C, AS, 9C, 6D, 9S]]
Hand [cards=[7D, JD, QD, 5H, 6C]]
Player [name=Bob, hand=Hand [cards=[5S, JS]]]
Player [name=Jill, hand=Hand [cards=[9H, AH]]]
Player [name=Thomas, hand=Hand [cards=[4C, 8S]]]


德州扑克

package casino;

import java.util.List;

public class TexasHoldem {
    private Deck deck;
    private Hand communityHand;

    public TexasHoldem() {
        deck = new Deck();
        communityHand = new Hand();
        deck.shuffle();
    }

    void printInfo(List<Player> players) {
        System.out.println("# INFO");
        System.out.println(deck);
        System.out.println(communityHand);
        players.stream().forEach(System.out::println);
    }

    void play(List<Player> players) {
        for (int i = 0; i < 5; i++) {
            communityHand.insert(deck.draw());
            if (i == 2) {
                System.out.println("# FLOP");
                compareHands(players, communityHand);
                System.out.println();
            }
            if (i == 3) {
                System.out.println("# TURN");
                compareHands(players, communityHand);
                System.out.println();
            }
            if (i == 4) {
                System.out.println("# RIVER");
                compareHands(players, communityHand);
                System.out.println();
            }
        }
    }

    public Hand viewHand(Player player, Hand community) {
        Hand view = new Hand();
        for (Card card : player.getHand().getCards()) {
            view.insert(card);
        }
        for (Card card : community.getCards()) {
            view.insert(card);
        }
        return view;
    }

    public void compareHands(List<Player> players, Hand community) {
        for (Player player : players) {
            Hand view = viewHand(player, community);
            view.sort();
            System.out.printf("%s => %s%n", player, view);
        }
    }

    public void dealCards(List<Player> players, int cardsPerPlayer) {
        for (int round = 0; round < cardsPerPlayer; round++) {
            for (Player player : players) {
                player.getHand().insert(deck.draw());
            }
        }
    }

    void sortHands(List<Player> players) {
        for (Player player : players) {
            player.getHand().sort();
        }
    }
}


甲板

一个标准的52张牌,按等级和西装排列。

package casino;

import java.util.*;

public class Deck extends AbstractDeck<Card> implements CardHolder {
    public Deck() {
        items = new Stack<Card>();
        for (int cardNo = 0; cardNo < 52; cardNo++) {
            items.add(new Card(cardNo));
        }
    }

    public List<Card> getCards() {
        return items;
    }

    public void setCards(Stack<Card> cards) {
        this.items = cards;
    }

    @Override
    public String toString() {
        return String.format("Deck [cards=%s]", items);
    }
}


播放器

持有一手牌的玩家。

package casino;

public class Player {
    private String name;
    private Hand hand;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Hand getHand() {
        return hand;
    }

    public void setHand(Hand hand) {
        this.hand = hand;
    }

    public Player(String name, Hand hand) {
        this.name = name;
        this.hand = hand;
    }

    public Player(String name) {
        this(name, new Hand());
    }

    @Override
    public String toString() {
        return String.format("Player [name=%s, hand=%s]", name, hand);
    }
}




代表一手牌。

package casino;

import java.util.*;

public class Hand extends AbstractDeck<Card> implements CardHolder {
    public Hand() {
        items = new Stack<Card>();
    }

    public List<Card> getCards() {
        return items;
    }

    public void setCards(Stack<Card> cards) {
        this.items = cards;
    }

    @Override
    public String toString() {
        return String.format("Hand [cards=%s]", items);
    }
}




代表具有西装和等级的标准扑克牌。

package casino;

public class Card implements Comparable<Card> {
    public static final String[] SUIT = { "C", "D", "H", "S" };
    public static final String[] RANK = { "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K", "A" };

    private int id;
    private int suit;
    private int numeral;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getSuit() {
        return suit;
    }

    public void setSuit(int suit) {
        this.suit = suit;
    }

    public int getNumeral() {
        return numeral;
    }

    public void setNumeral(int numeral) {
        this.numeral = numeral;
    }

    public Card(int cardNo) {
        assert cardNo >= 0;
        assert cardNo < 52;

        this.id = cardNo;
        this.suit = cardNo % 4;
        this.numeral = cardNo / 4;
    }

    public int compareTo(Card otherCard) {
        return Integer.compare(this.id, otherCard.id);
    }

    public String toString() {
        return String.format("%s%s", RANK[this.getNumeral()], SUIT[this.getSuit()]);
    }
}


持卡人

因为它们扩展了AbstractDeck,所以通常将Deck和Hand用作卡持有者。

package casino;

public interface CardHolder extends Container<Card> {
    // Just used as a category for Collection utilities of need be.
}


容器

模拟通用项目堆栈的界面,例如牌。

package casino;

public interface Container<E> {
    E peek();
    E draw();
    boolean insert(E element);
    void insertAt(int index, E element);
    void shuffle();
    void sort();
}


抽象甲板

包含可比较项的Container的抽象实现。在这个意义上,甲板和手非常相似。

package casino;

import java.util.Stack;

public class AbstractDeck<T extends Comparable<T>> implements Container<T> {
    protected Stack<T> items;

    @Override
    public T peek() {
        return items.peek();
    }

    @Override
    public T draw() {
        return items.pop();
    }

    @Override
    public boolean insert(T item) {
        return items.add(item);
    }

    @Override
    public void insertAt(int index, T item) {
        items.add(index, item);
    }

    @Override
    public void shuffle() {
        Actions.shuffle(items);
    }

    @Override
    public void sort() {
        Actions.sort(items);
    }
}


动作

用于对通用列表进行操作的静态实用程序类。

package casino;

import java.util.*;

public class Actions {
    private static final Random rnd = new Random();

    /** Fisher–Yates shuffle */
    public static <E> void shuffle(List<E> list) {
        for (int i = list.size() - 1; i > 0; i--) {
            int index = rnd.nextInt(i + 1);
            E tmp = list.get(index);
            list.set(index, list.get(i));
            list.set(i, tmp);
        }
    }

    public static <E extends Comparable<E>> void sort(List<E> list) {
        Collections.sort(list);
    }
}

09-26 19:59