3 回答

TA貢獻(xiàn)1880條經(jīng)驗(yàn) 獲得超4個(gè)贊
不想為你做作業(yè)...
這是個(gè)問題:
class Deck extends Card
牌組不是卡牌的子類型。一副牌有牌,所以:
class Deck { List<Card> cards; }
是一個(gè)更好的選擇。
另外,以下代碼對牌組沒有任何作用:
public void shuffleDeck() { Collections.shuffle(Arrays.asList(deck_card)); }
它會(huì)洗牌牌組的副本,使牌組保持不變。
另外,您不應(yīng)該在循環(huán)中構(gòu)建字符串。相反,在 Card 和 Deck 上實(shí)現(xiàn)(覆蓋) toString() 方法。
另外,制作西裝enum
。
另外,card_rank
完全刪除 - 它沒有任何意義。相反,int rank;
向 Card 添加一個(gè)字段,或者更好地使排名成為enum
。
首先修復(fù)這些問題,然后通過編寫一個(gè)方法來重新解決問題,該方法傳遞一個(gè)具有 List 的 Hand (一個(gè)新類),以及一個(gè)通過評估該手牌是否是同花而返回 HandType (另一個(gè)枚舉)的方法,否則有四種,否則...一直到高牌 - 從最高到最低。

TA貢獻(xiàn)1817條經(jīng)驗(yàn) 獲得超14個(gè)贊
為了對游戲進(jìn)行建模,首先要識(shí)別Card、Deck等實(shí)體(大多數(shù)情況下您已經(jīng)完成了)。我會(huì)添加更多內(nèi)容,例如Player、Evaluator(如下所述)等。
排名和花色不是字符串/整數(shù),但它們是預(yù)定義的(在游戲的生命周期中不會(huì)改變)卡牌中可能的變化。始終使用領(lǐng)域詞匯來獲得最佳模型。每張卡牌屬于一種花色和一種等級(jí)。(將 Rank 和 Suit 視為枚舉,這將避免未知值在運(yùn)行時(shí)破壞代碼。
不給出 Card 中的套件和等級(jí)的設(shè)置方法是必要的(它們組合形成 Card 的標(biāo)識(shí))
全牌組(初始化時(shí))由花色和等級(jí)的叉積形成。意思是牌組有(包含)多張牌。請記住,卡牌在牌組之外(在玩家手中時(shí))也可以是活的,因此它不是組合。從 Card 繼承 Deck 是絕對錯(cuò)誤的。它翻譯為陳述Deck 是一種 Card,這是不正確的。牌組將收集卡片。使用繼承,會(huì)導(dǎo)致違反里氏替換原則(SOLID之一)。
為了對 Deck 進(jìn)行建模,請考慮以下事實(shí):Deck 不包含重復(fù)的牌,Deck 一旦形成就不會(huì)改變其順序(除非洗牌)。這是 Set 和 List 之間的棘手選擇,我會(huì)選擇帶有添加編程約束的 List 以避免重復(fù)(僅在初始化時(shí)才需要完成)。
但是,最好不要將 Modeling Deck 作為 java 集合,而是讓類 Deck 包含合適選擇的 java 集合,并且通過定義所需的 API(從領(lǐng)域角度來看)如 shuffle、getTopCard() 等,Deck 類作為包裝器工作。這稱為對象適配器設(shè)計(jì)模式。這使得我們的設(shè)計(jì)平臺(tái)(實(shí)現(xiàn))獨(dú)立。
您需要對更多的類進(jìn)行建模,例如Player持有CardInHand等。
關(guān)于評估手中的卡片,最好將其建模為單獨(dú)的類,因?yàn)槠洳煌年P(guān)注點(diǎn)和規(guī)則可以獨(dú)立于其他類而改變。
撲克游戲是學(xué)習(xí)面向?qū)ο缶幊痰淖罴炎鳂I(yè)。

TA貢獻(xiàn)1805條經(jīng)驗(yàn) 獲得超10個(gè)贊
看來你的類Card只有靜態(tài)字段;我會(huì)更改它,以便 的實(shí)例Card代表 中的一張卡Deck。我也會(huì)把套房做成一種enum類型。您還可以為數(shù)字和 A 添加整數(shù)常量。該類可以實(shí)現(xiàn)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);
}
}
}
請注意,您還可以有 的兩個(gè)子類Card:一個(gè)用于數(shù)字,一個(gè)用于數(shù)字。
這Deck是 52 張卡片的集合。它是通過將每張卡添加到列表中來初始化的。一個(gè)人可以使用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);
}
現(xiàn)在 aHand是從 a 中取出的一組五張牌Deck。我們可以聲明Hand為實(shí)現(xiàn)Comparable<Hand>,這樣我們就可以知道兩只手中哪一只的價(jià)值最高:
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) {
...
}
}
現(xiàn)在有趣的部分來了:您必須將手牌類型識(shí)別為以下類型之一(枚舉類型):
public enum HandType {
SINGLE, PAIR, TWO_PAIRS, THREE, STRAIGHT, FLUSH, FULL_HOUSE, FOUR,
STRAIGHT_FLUSH, ROYAL_FLUSH;
}
請注意,常數(shù)是從最低到最高排列的。此外,牌的排列方式必須能夠在出現(xiàn)平局的情況下,您可以比較牌來確定獲勝者。
我建議你將相同等級(jí)的卡牌分組;如果您有五個(gè)不同的組,它仍然可以是同花或順子。
另一種方法是聲明Handfor every 的子類HandType,但我認(rèn)為這樣做不會(huì)獲得太多好處。
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;
}
}
添加回答
舉報(bào)