首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >控制台牌游戏-合同桥

控制台牌游戏-合同桥
EN

Code Review用户
提问于 2015-05-22 21:12:53
回答 4查看 1.5K关注 0票数 6

我的项目有三个类:CardDeckBridgeConsoleCard类有两个字段:int rankint suite。它有三种方法:toStringgetSuitAsStringcompareTo

代码语言:javascript
复制
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类构造了一套扑克牌,并有一种向玩家发送牌的方法:

代码语言:javascript
复制
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类中。我使用模块化算法来跟踪前几轮的赢家,以便在下一轮中从那个球员开始。

代码语言:javascript
复制
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);

    }
}

我希望对设计、编程风格等有任何反馈意见。

EN

回答 4

Code Review用户

发布于 2015-05-22 22:42:22

在变量和方法参数声明中使用ArrayList<Card>的地方随处可见。建议尽可能使用接口类型,在本例中是List<Card>。因此,例如:而不是:

ArrayList deck =新的ArrayList<>();

写成:

代码语言:javascript
复制
List<Card> deck = new ArrayList<>();

BridgeConsole类中,一切都是静态的。这会使单元测试变得困难,这是非常不寻常的。最好是把一切都变成非静态的,尽可能的多。您可能需要分成两个类:一个类管理游戏状态,另一个类刚刚开始运行整个过程(使用main方法)。

对于纸牌游戏中的套装建模,更常见的方法是使用enum

代码语言:javascript
复制
enum Suit {
    Hearts,
    Clubs,
    Diamonds,
    Spades
}

switch语句中,当多个案例具有相同的主体时,可以将它们分组。所以,不是这样的:

开关(胜利者){案例0: team1++;中断;案例1: team2++;中断;案例2: team1++;中断;案例3: team2++;中断;}

您可以简化为:

代码语言:javascript
复制
switch (winner) {
    case 0:
    case 2:
        team1++;
        break;
    case 1:
    case 3:
        team2++;
        break;
}
票数 6
EN

Code Review用户

发布于 2015-05-22 23:18:24

  1. 诉讼字段和等级字段应该被宣布为私有的,不需要共享事物和处理无限多的州。私人最终整数;私人最终整数;公共卡(整数,整数){ this.rank =秩;this.suit =套装;}
  2. 如果套装只允许0,1,2,3值,为什么不在构造时验证它呢?公共卡( int秩,int套){if(!isValidSuit(套服)){抛出新的IllegalArgumentException(“无效的西服值”);} this.rank =秩;this.suit =this.rank;}现在您可以确定西装总是有一个有效值,并且在getSuitString方法中不需要错误消息。
  3. 您在Card类中的compareTo不是类型安全的,如果传递的参数不是Card,它将抛出一个IllegalCastExcpetion,您可以实现Comparable<Card>类卡实现Comparable{ @Override int compareTo(Card o) {.}}
  4. 尝试使用接口而不是具体类型。getWinningCard(List中心)
  5. 避免代码中的神奇数字,如4,15,52,并将它们提取为常量,并给出一些有用的名称。
  6. 实现equalshashCode方法,避免引用相等。//比较引用而不是相等,如果(playerCard == center.get(i)) { index = i;}
  7. 程序末尾的System.exit(0);是无用的,您最好删除它。
票数 5
EN

Code Review用户

发布于 2015-05-23 05:30:34

代码语言:javascript
复制
public boolean compareTo(int firstSuit, Card c2) {
    return suit == firstSuit && rank > c2.rank;
    }
}

众所周知,每个compareTo都将this与参数进行比较,并返回一个int。每一个compareTo,除了这个。当你没有名字的时候,这太糟糕了,但是即使是_000也会更好。

AFAIK它是关于制作技巧的,你需要一些像class TrickEvaluator这样的成员

代码语言:javascript
复制
@Nullable private final Suit trumphSuit;

以及类似的方法

代码语言:javascript
复制
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);
}
代码语言:javascript
复制
public void addCard(Card card) {

这应该是私人的,因为卡从来没有真正增加后,建设。

代码语言:javascript
复制
public Card dealCard() {

你不需要它。每个人一次得到13张牌,所以互相发一张牌是没有意义的。它可能是一个助手方法,但是应该是私有的。

实际上,我会使Deck不可变,并添加一个方法getHand(int)

代码语言:javascript
复制
public class BridgeConsole {

这节课太长了。您应该将不直接处理UI的所有内容提取到其他类中。

代码语言:javascript
复制
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,你摆脱了那个可怕的开关。

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/91529

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档