已解决:问题最终不在于排序,而是在我不断添加经销商卡但从未删除的循环中。最终导致两次向经销商分发同一张卡片(或多次),从而导致明显的分类问题。
因此,我要对此类进行排序:
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);
}
}