我的项目有三个类:Card、Deck和BridgeConsole。Card类有两个字段:int rank和int suite。它有三种方法:toString、getSuitAsString和compareTo:
public class Card implements Comparable<Object>{
int suit; // 0-Hearts, 1-Clubs, 2-Diamonds, 3-Spades
int rank; // 2-10, 11-Jack, 12-Queen, 13-King, 14-Ace
public Card(int rank, int suit) {
this.rank = rank;
this.suit = suit;
}
public int getRank() {
return rank;
}
public int getSuit() {
return suit;
}
public String getSuitString() {
String str = null;
switch(suit){
case 0:
str = "Hearts";
break;
case 1:
str = "Clubs";
break;
case 2:
str = "Diamonds";
break;
case 3:
str = "Spades";
break;
default:
System.out.print("Fatal error!!!");
break;
}
return str;
}
@Override
public String toString() {
return rank + " of " + getSuitString() + ", ";
}
@Override
public int compareTo(Object o) {
Card c2 = (Card) o;
if( suit < c2.suit) {
return -1;
}
if( suit > c2.suit) {
return 1;
}
if( rank > c2.rank) {
return 1;
}
if( rank < c2.rank) {
return -1;
}
return 0;
}
public boolean compareTo(int firstSuit, Card c2) {
return suit == firstSuit && rank > c2.rank;
}
}我的Deck类构造了一套扑克牌,并有一种向玩家发送牌的方法:
public class Deck {
ArrayList<Card> deck = new ArrayList<>();
public Deck() {
for (int s = 0; s < 4; s++) {
for (int r = 2; r < 15; r++) {
deck.add(new Card(r, s));
}
}
Collections.shuffle(deck);
}
public void addCard(Card card) {
if (deck.size() < 52) {
deck.add(card);
}
}
public Card dealCard() {
Card card = null;
if (deck.size() > 0) {
card = deck.remove(deck.size() - 1);
}
return card;
}
}最后,游戏逻辑和主要方法包含在BridgeConsole类中。我使用模块化算法来跟踪前几轮的赢家,以便在下一轮中从那个球员开始。
public class BridgeConsole {
static Scanner stdin = new Scanner(System.in);
static Deck deck = new Deck();
static int playerCard;
static ArrayList<Card> player = new ArrayList<>();
static ArrayList<Card> ai1 = new ArrayList<>();
static ArrayList<Card> ai2 = new ArrayList<>();
static ArrayList<Card> ai3 = new ArrayList<>();
static ArrayList<Card> center = new ArrayList<>();
static int winner = 0;
static int team1 = 0;
static int team2 = 0;
static String whoWon = "";
public static int getPlyerCard() {
do {
System.out.print("\n player hands contains " + player.size() + " cards."
+ "\n Choose card [index]");
playerCard = stdin.nextInt();
while (playerCard > player.size()) {
System.out.print("Please enter a valid card index. [0-13]");
playerCard = stdin.nextInt();
}
} while (playerCard > player.size());
return playerCard;
}
public static void trackScore(ArrayList<Card> p_1, ArrayList<Card> p_2, ArrayList<Card> p_3, ArrayList<Card> p_4, ArrayList<Card> center, int winner) {
switch (winner) {
case 0:
team1++;
break;
case 1:
team2++;
break;
case 2:
team1++;
break;
case 3:
team2++;
break;
}
}
public static void playRound() {
System.out.println("PLAYER Hand:");
int index = 0;
for (Card c : player) {
System.out.print("[" + index + "] " + c.toString());
index++;
}
System.out.println("\n AI 1 hand");
displayCards(ai1);
System.out.println("\n AI 2 hand");
displayCards(ai2);
System.out.println("\n AI 3 hand");
displayCards(ai3);
switch (winner) {
case 0:
playerCard = getPlyerCard();
center.add(player.get(playerCard));
center.add(aiSelect(center.get(0), ai1));
center.add(aiSelect(center.get(0), ai2));
center.add(aiSelect(center.get(0), ai3));
ai1.remove(aiSelect(center.get(0), ai1));
ai2.remove(aiSelect(center.get(0), ai2));
ai3.remove(aiSelect(center.get(0), ai3));
player.remove(playerCard);
break;
case 1:
center.add(aiSelect(ai1));
center.add(aiSelect(center.get(0), ai2));
center.add(aiSelect(center.get(0), ai3));
System.out.print("\nCenter row of cards\n");
displayCards(center);
playerCard = getPlyerCard();
center.add(player.get(playerCard));
ai1.remove(aiSelect(ai1));
ai2.remove(aiSelect(center.get(0), ai2));
ai3.remove(aiSelect(center.get(0), ai3));
player.remove(playerCard);
break;
case 2:
center.add(aiSelect(ai2));
center.add(aiSelect(center.get(0), ai3));
System.out.print("\nCenter row of cards\n");
displayCards(center);
playerCard = getPlyerCard();
center.add(player.get(playerCard));
center.add(aiSelect(center.get(0), ai1));
ai2.remove(aiSelect(ai2));
ai3.remove(aiSelect(center.get(0), ai3));
player.remove(playerCard);
ai1.remove(aiSelect(center.get(0), ai1));
break;
case 3:
center.add(aiSelect(ai3));
System.out.print("\nCenter row of cards\n");
displayCards(center);
playerCard = getPlyerCard();
center.add(player.get(playerCard));
center.add(aiSelect(center.get(0), ai1));
center.add(aiSelect(center.get(0), ai2));
ai3.remove(aiSelect(ai3));
player.remove(playerCard);
ai1.remove(aiSelect(center.get(0), ai1));
ai2.remove(aiSelect(center.get(0), ai2));
break;
default:
break;
}
System.out.print("\nCenter row of cards\n");
displayCards(center);
System.out.print("\n Winning Card \n");
System.out.println(selectMax(center.get(0), center.get(1), center.get(2), center.get(3)).toString());
System.out.print("\n Player who won round \n");
winner = (winner + getWinningCard(center)) % 4;
System.out.println("At position [" + getPlayerPosition(center.get(getWinningCard(center)), center) + "]");
trackScore(player, ai2, ai3, ai1, center, winner);
center.clear();
}
public static int getPlayerPosition(Card playerCard, ArrayList<Card> center) {
int index = 0;
for (int i = 0; i < center.size(); i++) {
if (playerCard == center.get(i)) {
index = i;
}
}
return index;
}
public static int getWinningCard(ArrayList<Card> center) {
Card maxCard = selectMax(center.get(0), center.get(1), center.get(2), center.get(3));
return center.indexOf(maxCard);
}
public static Card aiSelect(Card current, ArrayList<Card> aiHand) {
Collections.sort(aiHand);
// var max will track highest card in AIs hand
Card max;
// contains all posible cards of the same sui as the current card
ArrayList<Card> followSuit = new ArrayList<>();
for (Card c : aiHand) {
if (c.suit == current.suit) {
followSuit.add(c);
}
}
if (!followSuit.isEmpty()) {
Collections.sort(aiHand);
max = followSuit.get(followSuit.size() - 1);
return max;
} else {
return aiHand.get(aiHand.size() - 1);
}
}
public static Card aiSelect(ArrayList<Card> aiHand) {
Collections.sort(aiHand);
// var max will track highest card in AIs hand
return aiHand.get(aiHand.size() - 1);
}
public static void displayCards(ArrayList<Card> hand) {
for (Card c : hand) {
System.out.print(c.toString());
}
}
public static void dealCards(Deck deck, ArrayList<Card> p1, ArrayList<Card> p2,
ArrayList<Card> p3, ArrayList<Card> p4) {
for (int i = 0; i < 13; i++) {
p1.add(deck.dealCard());
p2.add(deck.dealCard());
p3.add(deck.dealCard());
p4.add(deck.dealCard());
}
}
public static Card selectMax(Card c1, Card c2, Card c3, Card c4) {
// suit of card 1
int firsSuit = c1.suit;
if (c1.compareTo(firsSuit, c2) && c1.compareTo(firsSuit, c3)
&& c1.compareTo(firsSuit, c4)) {
return c1;
} else if (c2.compareTo(firsSuit, c1) && c2.compareTo(firsSuit, c3)
&& c2.compareTo(firsSuit, c4)) {
return c2;
} else if (c3.compareTo(firsSuit, c1) && c3.compareTo(firsSuit, c2)
&& c3.compareTo(firsSuit, c4)) {
return c3;
} else {
return c4;
}
}
public static void main(String[] args) {
System.out.println("Contract Bridge - Console");
System.out.println("Creating deck...");
System.out.println("Dealing Cards...");
dealCards(deck, player, ai1, ai2, ai3);
while (!player.isEmpty()) {
playRound();
}
System.out.print("Team1: " + team1 + " team2: " + team2);
stdin.close();
System.exit(0);
}
}我希望对设计、编程风格等有任何反馈意见。
发布于 2015-05-22 22:42:22
在变量和方法参数声明中使用ArrayList<Card>的地方随处可见。建议尽可能使用接口类型,在本例中是List<Card>。因此,例如:而不是:
ArrayList deck =新的ArrayList<>();
写成:
List<Card> deck = new ArrayList<>();在BridgeConsole类中,一切都是静态的。这会使单元测试变得困难,这是非常不寻常的。最好是把一切都变成非静态的,尽可能的多。您可能需要分成两个类:一个类管理游戏状态,另一个类刚刚开始运行整个过程(使用main方法)。
对于纸牌游戏中的套装建模,更常见的方法是使用enum。
enum Suit {
Hearts,
Clubs,
Diamonds,
Spades
}在switch语句中,当多个案例具有相同的主体时,可以将它们分组。所以,不是这样的:
开关(胜利者){案例0: team1++;中断;案例1: team2++;中断;案例2: team1++;中断;案例3: team2++;中断;}
您可以简化为:
switch (winner) {
case 0:
case 2:
team1++;
break;
case 1:
case 3:
team2++;
break;
}发布于 2015-05-22 23:18:24
getSuitString方法中不需要错误消息。compareTo不是类型安全的,如果传递的参数不是Card,它将抛出一个IllegalCastExcpetion,您可以实现Comparable<Card>类卡实现Comparable{ @Override int compareTo(Card o) {.}}equals和hashCode方法,避免引用相等。//比较引用而不是相等,如果(playerCard == center.get(i)) { index = i;}System.exit(0);是无用的,您最好删除它。发布于 2015-05-23 05:30:34
public boolean compareTo(int firstSuit, Card c2) {
return suit == firstSuit && rank > c2.rank;
}
}众所周知,每个compareTo都将this与参数进行比较,并返回一个int。每一个compareTo,除了这个。当你没有名字的时候,这太糟糕了,但是即使是_000也会更好。
AFAIK它是关于制作技巧的,你需要一些像class TrickEvaluator这样的成员
@Nullable private final Suit trumphSuit;以及类似的方法
boolean takes(Card oldCard, Card newCard) {
if (oldCard.getSuite() == newCard.getSuite()) {
return newCard.getRank() > oldCard.getRank();
} else {
return newCard.getSuite() == trumphSuit;
}
}
int trickWinner(List<Card> playedCards) {
checkArgument(0 < playedCards.size() && playedCards.size() <= 4);
Card winningCard = playedCards.get(0);
for (Card c : playedCards) {
if (takes(winningCard, c)) {
winningCard = c;
}
}
return playedCards.indexOf(winningCard);
}public void addCard(Card card) {这应该是私人的,因为卡从来没有真正增加后,建设。
public Card dealCard() {你不需要它。每个人一次得到13张牌,所以互相发一张牌是没有意义的。它可能是一个助手方法,但是应该是私有的。
实际上,我会使Deck不可变,并添加一个方法getHand(int)。
public class BridgeConsole {这节课太长了。您应该将不直接处理UI的所有内容提取到其他类中。
static ArrayList<Card> player = new ArrayList<>();
static ArrayList<Card> ai1 = new ArrayList<>();
static ArrayList<Card> ai2 = new ArrayList<>();
static ArrayList<Card> ai3 = new ArrayList<>();如果您在这里使用列表列表,您可以节省相当多的代码与索引模块4。您还获得了一些灵活性为以后,您可以更容易地使用更多的球员(而不是人工智能)。ANd,你摆脱了那个可怕的开关。
https://codereview.stackexchange.com/questions/91529
复制相似问题