3 回答
TA贡献1880条经验 获得超4个赞
不想为你做作业...
这是个问题:
class Deck extends Card
牌组不是卡牌的子类型。一副牌有牌,所以:
class Deck { List<Card> cards; }
是一个更好的选择。
另外,以下代码对牌组没有任何作用:
public void shuffleDeck() { Collections.shuffle(Arrays.asList(deck_card)); }
它会洗牌牌组的副本,使牌组保持不变。
另外,您不应该在循环中构建字符串。相反,在 Card 和 Deck 上实现(覆盖) toString() 方法。
另外,制作西装enum
。
另外,card_rank
完全删除 - 它没有任何意义。相反,int rank;
向 Card 添加一个字段,或者更好地使排名成为enum
。
首先修复这些问题,然后通过编写一个方法来重新解决问题,该方法传递一个具有 List 的 Hand (一个新类),以及一个通过评估该手牌是否是同花而返回 HandType (另一个枚举)的方法,否则有四种,否则...一直到高牌 - 从最高到最低。
TA贡献1817条经验 获得超14个赞
为了对游戏进行建模,首先要识别Card、Deck等实体(大多数情况下您已经完成了)。我会添加更多内容,例如Player、Evaluator(如下所述)等。
排名和花色不是字符串/整数,但它们是预定义的(在游戏的生命周期中不会改变)卡牌中可能的变化。始终使用领域词汇来获得最佳模型。每张卡牌属于一种花色和一种等级。(将 Rank 和 Suit 视为枚举,这将避免未知值在运行时破坏代码。
不给出 Card 中的套件和等级的设置方法是必要的(它们组合形成 Card 的标识)
全牌组(初始化时)由花色和等级的叉积形成。意思是牌组有(包含)多张牌。请记住,卡牌在牌组之外(在玩家手中时)也可以是活的,因此它不是组合。从 Card 继承 Deck 是绝对错误的。它翻译为陈述Deck 是一种 Card,这是不正确的。牌组将收集卡片。使用继承,会导致违反里氏替换原则(SOLID之一)。
为了对 Deck 进行建模,请考虑以下事实:Deck 不包含重复的牌,Deck 一旦形成就不会改变其顺序(除非洗牌)。这是 Set 和 List 之间的棘手选择,我会选择带有添加编程约束的 List 以避免重复(仅在初始化时才需要完成)。
但是,最好不要将 Modeling Deck 作为 java 集合,而是让类 Deck 包含合适选择的 java 集合,并且通过定义所需的 API(从领域角度来看)如 shuffle、getTopCard() 等,Deck 类作为包装器工作。这称为对象适配器设计模式。这使得我们的设计平台(实现)独立。
您需要对更多的类进行建模,例如Player持有CardInHand等。
关于评估手中的卡片,最好将其建模为单独的类,因为其不同的关注点和规则可以独立于其他类而改变。
扑克游戏是学习面向对象编程的最佳作业。
TA贡献1805条经验 获得超10个赞
看来你的类Card只有静态字段;我会更改它,以便 的实例Card代表 中的一张卡Deck。我也会把套房做成一种enum类型。您还可以为数字和 A 添加整数常量。该类可以实现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);
}
现在 aHand是从 a 中取出的一组五张牌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;
}
请注意,常数是从最低到最高排列的。此外,牌的排列方式必须能够在出现平局的情况下,您可以比较牌来确定获胜者。
我建议你将相同等级的卡牌分组;如果您有五个不同的组,它仍然可以是同花或顺子。
另一种方法是声明Handfor every 的子类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;
}
}
添加回答
举报