Техасский холдем в Java


Я был программистом в течение 12 лет, в основном ERP-систем и развитие С и я ищу, чтобы сделать карьеру/специальности изменения в Java. Я читал ее бесчисленное количество раз, если вы хотите выучить новый язык, вы должны написать код, потом пиши немного больше кода, а затем, наконец, писать код. Поэтому я написал некоторый код!

Я люблю покер, поэтому я написал небольшой техасский холдем программы. Вот обзор того, что он делает:

  1. Запрашивает у пользователя количество игроков
  2. Создать колоду карт
  3. Перетасовать
  4. Вырезать палубу
  5. Игроки интернет-карты
  6. Сжигает карту
  7. Предложения на флопе
  8. Сжигает карту
  9. Предложения на очередь
  10. Сжигает карту
  11. Реки сделок
  12. Печатает колоды в консоли, чтобы показать случайные карты был использован
  13. Печать 'доска'
  14. Печать расходных карт
  15. Принтеры карт игроков
  16. Вычисляет значение каждой руки игроков (Роял Флеш, фул хаус и т. д...)

Есть 6 .Java-файлов (см. Ниже ссылки). Я использовал интерфейс, создал свой собственный компараторы, даже внедрили несколько try и catch блоки (хотя я все еще учусь, как использовать их должным образом).

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class TexasHoldEm {

    public static void main(String[] args) throws Exception {
        // variables
        Deck holdemDeck = new Deck();
        int numPlayers = 0;
        int cardCounter = 0;
        int burnCounter = 0;
        int boardCounter = 0;
        Board board = new Board();

        // initializations      
        numPlayers = getNumberOfPlayers();
        Player[] player = new Player[numPlayers];

        /* 3 shuffles just like in real life. */
        for(int i=0;i<3;i++){
            holdemDeck.shuffle();
        }

        // Cut Deck
        holdemDeck.cutDeck();

        // Initialize players
        for (int i=0;i<numPlayers;i++){
            player[i] = new Player();
        }

        // Main processing
        // Deal hole cards to players
        for (int i=0;i<2;i++){
            for (int j=0;j<numPlayers;j++){
                player[j].setCard(holdemDeck.getCard(cardCounter++), i);
            }
        }

        // Start dealing board

        // Burn one card before flop
        board.setBurnCard(holdemDeck.getCard(cardCounter++), burnCounter++);

        // deal flop
        for (int i=0; i<3;i++){
            board.setBoardCard(holdemDeck.getCard(cardCounter++), boardCounter++);
        }

        // Burn one card before turn
        board.setBurnCard(holdemDeck.getCard(cardCounter++), burnCounter++);

        // deal turn
        board.setBoardCard(holdemDeck.getCard(cardCounter++), boardCounter++);

        // Burn one card before river
        board.setBurnCard(holdemDeck.getCard(cardCounter++), burnCounter++);

        // deal river
        board.setBoardCard(holdemDeck.getCard(cardCounter++), boardCounter++);

        //------------------------
        // end dealing board
        //------------------------

        System.out.println("The hand is complete...\n");

        // print deck
        holdemDeck.printDeck();

        //print board
        board.printBoard();

        // print player cards
        System.out.println("The player cards are the following:\n");
        for (int i=0;i<numPlayers;i++){
            player[i].printPlayerCards(i);
        }

        // print burn cards
        board.printBurnCards();

        //------------------------
        // Begin hand comparison
        //------------------------
        for (int i=0;i<numPlayers;i++){
            HandEval handToEval = new HandEval();

            // populate with player cards           
            for (int j=0;j<player[i].holeCardsSize();j++){
                handToEval.addCard(player[i].getCard(j),j);
            }

            //populate with board cards
            for (int j=player[i].holeCardsSize();j<(player[i].holeCardsSize()+board.boardSize());j++){
                handToEval.addCard(board.getBoardCard(j-player[i].holeCardsSize()),j);
            }

            System.out.println("Player " + (i+1) + " hand value: " + handToEval.evaluateHand());    
        }
    }

    protected static int getNumberOfPlayers() throws Exception{
        int intPlayers = 0;
        String userInput = "";

        // Get number of players from user.
        System.out.println("Enter number of players (1-9):");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        try { 
               userInput = br.readLine(); 
            } catch (IOException ioe) { 
               System.out.println("Error: IO error trying to read input!"); 
               System.exit(1); 
            }

        // convert user input to an integer
        try {
           intPlayers = Integer.parseInt(userInput);
            } catch (NumberFormatException nfe) {
               System.out.println("Error: Input provided is not a valid Integer!"); 
               System.exit(1); 
            }

        if ((intPlayers<1) || (intPlayers>9)){
            throw new Exception("Error: Number of players must be an integer between 1 and 9");
        }       

        return intPlayers;
    }
}

Player.java

public class Player {
    private Card[] holeCards = new Card[2];

    //constructor
    public Player(){
    }

    public Player(Card card1, Card card2){
        holeCards[0] = card1;
        holeCards[1] = card2;
    }

    //methods
    protected void setCard(Card card, int cardNum){
        holeCards[cardNum] = card;
    }

    protected Card getCard(int cardNum){
        return holeCards[cardNum];
    }

    protected int holeCardsSize(){
        return holeCards.length;
    }

    protected void printPlayerCards(int playerNumber){
        System.out.println("Player " + (playerNumber+1) + " hole cards:");
        for (int i=0;i<2;i++){
            System.out.println(holeCards[i].printCard());
        }
        System.out.println("\n");
    }
}

HandEval.java

import java.util.Arrays;

public class HandEval { 
    private Card[] availableCards = new Card[7];

    private final static short ONE = 1;
    private final static short TWO = 2;
    private final static short THREE = 3;
    private final static short FOUR = 4;

    // Constructor
    public HandEval(){
    }

    //methods
    protected void addCard(Card card, int i){
        availableCards[i] = card;
    }

    protected Card getCard(int i){
        return availableCards[i];
    }

    protected int numCards(){
        return availableCards.length;
    }

    protected void sortByRank(){
        Arrays.sort(availableCards, new rankComparator());
    }

    protected void sortBySuit(){
        Arrays.sort(availableCards, new suitComparator());
    }

    protected void sortBySuitThenRank(){
        Arrays.sort(availableCards, new suitComparator());
        Arrays.sort(availableCards, new rankComparator());
    }

    protected void sortByRankThenSuit(){
        Arrays.sort(availableCards, new rankComparator());
        Arrays.sort(availableCards, new suitComparator());
    }

    protected String evaluateHand(){
        String handResult = new String();
        short[] rankCounter = new short[13];
        short[] suitCounter = new short[4];

        // initializations
        for (int i=0;i<rankCounter.length;i++){
            rankCounter[i] =0;
        }

        for (int i=4;i<suitCounter.length;i++){
            suitCounter[i] = 0;
        }

        // Loop through sorted cards and total ranks
        for(int i=0; i<availableCards.length;i++){
            rankCounter[ availableCards[i].getRank() ]++;
            suitCounter[ availableCards[i].getSuit() ]++;
        }

        //sort cards for evaluation
        this.sortByRankThenSuit();

        // hands are already sorted by rank and suit for royal and straight flush checks.       
        // check for royal flush
        handResult = evaluateRoyal(rankCounter, suitCounter);

        // check for straight flush
        if (handResult == null || handResult.length() == 0){
            handResult = evaluateStraightFlush(rankCounter, suitCounter);
        }

        // check for four of a kind
        if (handResult == null || handResult.length() == 0){
            handResult = evaluateFourOfAKind(rankCounter);
        }

        // check for full house
        if (handResult == null || handResult.length() == 0){
            handResult = evaluateFullHouse(rankCounter);
        }

        // check for flush
        if (handResult == null || handResult.length() == 0){
            handResult = evaluateFlush(rankCounter, suitCounter);
        }

        // check for straight
        if (handResult == null || handResult.length() == 0){
            // re-sort by rank, up to this point we had sorted by rank and suit
            // but a straight is suit independent.
            this.sortByRank();
            handResult = evaluateStraight(rankCounter);
        }

        // check for three of a kind
        if (handResult == null || handResult.length() == 0){
            handResult = evaluateThreeOfAKind(rankCounter);
        }

        // check for two pair
        if (handResult == null || handResult.length() == 0){
            handResult = evaluateTwoPair(rankCounter);
        }

        // check for one pair
        if (handResult == null || handResult.length() == 0){
            handResult = evaluateOnePair(rankCounter);
        }

        // check for highCard
        if (handResult == null || handResult.length() == 0){
            handResult = evaluateHighCard(rankCounter);
        }


        return handResult;
    }

    private String evaluateRoyal(short[] rankCounter, short[] suitCounter){
        String result = "";

        // Check for Royal Flush (10 - Ace of the same suit).
        // check if there are 5 of one suit, if not royal is impossible     
        if ((rankCounter[9] >= 1 &&       /* 10 */
                rankCounter[10] >= 1 &&   /* Jack */
                rankCounter[11] >= 1 &&  /* Queen */
                rankCounter[12] >= 1 &&  /* King */
                rankCounter[0] >= 1)    /* Ace */
                && (suitCounter[0] > 4 || suitCounter[1] > 4 ||
                        suitCounter[2] > 4 || suitCounter[3] > 4)){

            // min. requirements for a royal flush have been met, 
            // now loop through records for an ace and check subsequent cards. 
            // Loop through the aces first since they are the first card to 
            // appear in the sorted array of 7 cards. 
            royalSearch:
                for (int i=0;i<3;i++){
                    // Check if first card is the ace.
                    // Ace must be in position 0, 1 or 2
                    if (availableCards[i].getRank() == 0){
                        // because the ace could be the first card in the array
                        // but the remaining 4 cards could start at position 1,
                        // 2 or 3 loop through checking each possibility.
                        for (int j=1;j<4-i;j++){
                            if ((availableCards[i+j].getRank() == 9 && 
                                    availableCards[i+j+1].getRank() == 10 &&
                                    availableCards[i+j+2].getRank() == 11 &&
                                    availableCards[i+j+3].getRank() == 12) 
                                    &&
                                    (availableCards[i].getSuit() == availableCards[i+j].getSuit() &&
                                    availableCards[i].getSuit() == availableCards[i+j+1].getSuit() &&
                                    availableCards[i].getSuit() == availableCards[i+j+2].getSuit() &&
                                    availableCards[i].getSuit() == availableCards[i+j+3].getSuit())){
                                        // Found royal flush, break and return.
                                        result = "Royal Flush!! Suit: " + Card.suitAsString(availableCards[i].getSuit());
                                        break royalSearch;              
                            }
                        }
                    }               
                }
        }       
        return result;
    }

    // Straight flush is 5 consecutive cards of the same suit.
    private String evaluateStraightFlush(short[] rankCounter, short[] suitCounter){
        String result = "";

        if (suitCounter[0] > 4 || suitCounter[1] > 4 ||
                suitCounter[2] > 4 || suitCounter[3] > 4){

            // min. requirements for a straight flush have been met.
            // Loop through available cards looking for 5 consecutive cards of the same suit,
            // start in reverse to get the highest value straight flush
            for (int i=availableCards.length-1;i>3;i--){
                if ((availableCards[i].getRank()-ONE == availableCards[i-ONE].getRank() && 
                        availableCards[i].getRank()-TWO == availableCards[i-TWO].getRank() &&
                        availableCards[i].getRank()-THREE == availableCards[i-THREE].getRank() &&
                        availableCards[i].getRank()-FOUR == availableCards[i-FOUR].getRank()) 
                        &&
                        (availableCards[i].getSuit() == availableCards[i-ONE].getSuit() &&
                        availableCards[i].getSuit() == availableCards[i-TWO].getSuit() &&
                        availableCards[i].getSuit() == availableCards[i-THREE].getSuit() &&
                        availableCards[i].getSuit() == availableCards[i-FOUR].getSuit())){
                            // Found royal flush, break and return.
                            result = "Straight Flush!! " + Card.rankAsString(availableCards[i].getRank()) + " high of " + Card.suitAsString(availableCards[i].getSuit());
                            break;
                }
            }
        }
        return result;
    }

    // Four of a kind is 4 cards with the same rank: 2-2-2-2, 3-3-3-3, etc...
    private String evaluateFourOfAKind(short[] rankCounter){
        String result = "";

        for (int i=0;i<rankCounter.length;i++){
            if (rankCounter[i] == FOUR){
                result = "Four of a Kind, " + Card.rankAsString(i) +"'s";
                break;
            }
        }   
        return result;
    }

    // Full house is having 3 of a kind of one rank, and two of a kind of 
    // a second rank.  EX: J-J-J-3-3
    private String evaluateFullHouse(short[] rankCounter){
        String result = "";
        short threeOfKindRank = -1;
        short twoOfKindRank = -1;

        for (int i=rankCounter.length;i>0;i--){
            if ((threeOfKindRank < (short)0) || (twoOfKindRank < (short)0)){
                if ((rankCounter[i-ONE]) > 2){
                    threeOfKindRank = (short) (i-ONE);                  
                }
                else if ((rankCounter[i-ONE]) > 1){
                    twoOfKindRank = (short)(i-ONE);
                }
            }
            else
            {
                break;
            }
        }

        if ((threeOfKindRank >= (short)0) && (twoOfKindRank >= (short)0)){
            result = "Full House: " + Card.rankAsString(threeOfKindRank) + "'s full of " + Card.rankAsString(twoOfKindRank) + "'s";
        }

        return result;
    }

    // Flush is 5 cards of the same suit.
    private String evaluateFlush(short[] rankCounter, short[] suitCounter){
        String result = "";

        // verify at least 1 suit has 5 cards or more.
        if (suitCounter[0] > 4 || suitCounter[1] > 4 ||
                suitCounter[2] > 4 || suitCounter[3] > 4){

            for (int i=availableCards.length-1;i>3;i--){
                if (availableCards[i].getSuit() == availableCards[i-ONE].getSuit() &&
                        availableCards[i].getSuit() == availableCards[i-TWO].getSuit() &&
                        availableCards[i].getSuit() == availableCards[i-THREE].getSuit() &&
                        availableCards[i].getSuit() == availableCards[i-FOUR].getSuit()){
                            // Found royal flush, break and return.
                            result = "Flush!! " + Card.rankAsString(availableCards[i].getRank()) + " high of " + Card.suitAsString(availableCards[i].getSuit());
                            break;
                }
            }           
        }


        return result;
    }

    // Straight is 5 consecutive cards, regardless of suit.
    private String evaluateStraight(short[] rankCounter){
        String result = "";

        // loop through rank array to check for 5 consecutive
        // index with a value greater than zero
        for (int i=rankCounter.length;i>4;i--){
            if ((rankCounter[i-1] > 0) &&
                    (rankCounter[i-2] > 0) &&
                    (rankCounter[i-3] > 0) &&
                    (rankCounter[i-4] > 0) &&
                    (rankCounter[i-5] > 0)){
                        result = "Straight " + Card.rankAsString(i-1) + " high";
                        break;
            }
        }
        return result;
    }

    // Three of a kind is 3 cards of the same rank.
    private String evaluateThreeOfAKind(short[] rankCounter){
        String result = "";

        // loop through rank array to check for 5 consecutive
        // index with a value greater than zero
        for (int i=rankCounter.length;i>0;i--){
            if (rankCounter[i-1] > 2){
                        result = "Three of a Kind " + Card.rankAsString(i-1) + "'s";
                        break;
            }
        }
        return result;
    }

    // Two pair is having 2 cards of the same rank, and two
    // different cards of the same rank.  EX: 3-3-7-7-A
    private String evaluateTwoPair(short[] rankCounter){
        String result = "";
        short firstPairRank = -1;
        short secondPairRank = -1;

        for (int i=rankCounter.length;i>0;i--){
            if ((firstPairRank < (short)0) || (secondPairRank < (short)0)){             
                if (((rankCounter[i-ONE]) > 1) && (firstPairRank < (short)0)){
                    firstPairRank = (short) (i-ONE);                    
                }
                else if ((rankCounter[i-ONE]) > 1){
                    secondPairRank = (short)(i-ONE);
                }
            }
            else
            {
                // two pair found, break loop.
                break;
            }
        }

        // populate output
        if ((firstPairRank >= (short)0) && (secondPairRank >= (short)0)){
            if (secondPairRank == (short)0){
                // Aces serve as top rank but are at the bottom of the rank array
                // swap places so aces show first as highest pair
                result = "Two Pair: " + Card.rankAsString(secondPairRank) + "'s and " + Card.rankAsString(firstPairRank) + "'s";
            }
            else
            {
                result = "Two Pair: " + Card.rankAsString(firstPairRank) + "'s and " + Card.rankAsString(secondPairRank) + "'s";
            }           
        }

        return result;
    }

    // One is is two cards of the same rank.
    private String evaluateOnePair(short[] rankCounter){
        String result = "";

        for (int i=rankCounter.length;i>0;i--){
            if((rankCounter[i-ONE]) > 1){
                result = "One Pair: " + Card.rankAsString(i-ONE) + "'s";    
                break;
            }
        }
        return result;
    }

    // high card is the highest card out of the 7 possible cards to be used.
    private String evaluateHighCard(short[] rankCounter){
        String result = "";

        for (int i=rankCounter.length;i>0;i--){
            if((rankCounter[i-ONE]) > 0){
                result = "High Card: " + Card.rankAsString(i-ONE);
                break;
            }
        }
        return result;
    }

}

Deck.java

import java.util.Random;

public class Deck{
    private Card[] cards = new Card[52];

    //Constructor
    public Deck(){
        int i = 0;
        for (short j=0; j<4; j++){
            for (short k=0; k<13;k++){
                cards[i++] = new Card(k, j);    
            }
        }
    }

    // Print entire deck in order
    protected void printDeck(){
        for(int i=0; i<cards.length;i++){
            System.out.println(i+1 + ": " + cards[i].printCard());
        }
        System.out.println("\n");
    }

    // Find card in deck in a linear fashion
    // Use this method if deck is shuffled/random
    protected int findCard(Card card){
        for (int i=0;i<52;i++){
            if (Card.sameCard(cards[i], card)){
                return i;
            }
        }
        return -1;
    }

    //return specified card from deck
    protected Card getCard(int cardNum){
        return cards[cardNum];
    }

    protected void shuffle(){
        int length = cards.length;
        Random random = new Random();
        //random.nextInt();
        for (int i=0;i<length;i++){
            int change = i + random.nextInt(length-i);
            swapCards(i, change);
        }
    }

    protected void cutDeck(){
        Deck tempDeck = new Deck();
        Random random = new Random();
        int cutNum = random.nextInt(52);
        for (int i=0;i<cutNum;i++){
            tempDeck.cards[i] = this.cards[52-cutNum+i];            
        }
        for (int j=0;j<52-cutNum;j++){
            tempDeck.cards[j+cutNum] = this.cards[j];           
        }
        this.cards = tempDeck.cards;
    }

    // Swap cards in array to 'shuffle' the deck.
    private void swapCards(int i, int change){      
        Card temp = cards[i];
        cards[i] = cards[change];
        cards[change] = temp;
    }
}

Card.java

import java.util.*;

public class Card{
    private short rank, suit;

    private static String[] ranks = {"Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"};
    private static String[] suits = {"Diamonds", "Clubs", "Hearts", "Spades"};

    //Constructor
    public Card(short rank, short suit){
        this.rank = rank;
        this.suit = suit;
    }

    // Getter and Setters
    public short getSuit(){
        return suit;
    }

    public short getRank(){
        return rank;
    }

    protected void setSuit(short suit){
        this.suit = suit;
    }

    protected void setRank(short rank){
        this.rank = rank;
    }

    // methods
    public static String rankAsString(int __rank){
        return ranks[__rank];
    }

    public static String suitAsString(int __suit){
        return suits[__suit];
    }

    public @Override String toString(){
        return rank + " of " + suit;
    }

    // Print card to string
    protected String printCard(){
        return ranks[rank] + " of " + suits[suit];
    }

    // Determine if two cards are the same (Ace of Diamonds == Ace of Diamonds)
    public static boolean sameCard(Card card1, Card card2){
        return (card1.rank == card2.rank && card1.suit == card2.suit);
    }   

}

class rankComparator implements Comparator<Object>{
    public int compare(Object card1, Object card2) throws ClassCastException{
        // verify two Card objects are passed in
        if (!((card1 instanceof Card) && (card2 instanceof Card))){
            throw new ClassCastException("A Card object was expeected.  Parameter 1 class: " + card1.getClass() 
                    + " Parameter 2 class: " + card2.getClass());
        }

        short rank1 = ((Card)card1).getRank();
        short rank2 = ((Card)card2).getRank();

        return rank1 - rank2;
    }
}

class suitComparator implements Comparator<Object>{
    public int compare(Object card1, Object card2) throws ClassCastException{
        // verify two Card objects are passed in
        if (!((card1 instanceof Card) && (card2 instanceof Card))){
            throw new ClassCastException("A Card object was expeected.  Parameter 1 class: " + card1.getClass() 
                    + " Parameter 2 class: " + card2.getClass());
        }

        short suit1 = ((Card)card1).getSuit();
        short suit2 = ((Card)card2).getSuit();

        return suit1 - suit2;
    }
}

Board.java

public class Board {
    private Card[] board = new Card[5];
    private Card[] burnCards = new Card[3];

    //constructor
    public Board(){
    }

    //methods
    protected void setBoardCard(Card card, int cardNum){
        this.board[cardNum] = card;
    }

    protected Card getBoardCard(int cardNum){
        return this.board[cardNum];
    }

    protected void setBurnCard(Card card, int cardNum){
        this.burnCards[cardNum] = card;
    }

    protected Card getBurnCard(int cardNum){
        return this.burnCards[cardNum];
    }

    protected int boardSize(){
        return board.length;
    }

    protected void printBoard(){
        System.out.println("The board contains the following cards:");
        for(int i =0; i<board.length;i++){
            System.out.println(i+1 + ": " + getBoardCard(i).printCard());
        }
        System.out.println("\n");
    }

    protected void printBurnCards(){
        System.out.println("The burn cards are:");
        for(int i =0; i<burnCards.length;i++){
            System.out.println(i+1 + ": " + getBurnCard(i).printCard());
        }
        System.out.println("\n");
    }

}


15294
22
задан 22 марта 2011 в 01:03 Источник Поделиться
Комментарии
2 ответа

Начнем с самых элементарных, карта класс.


import java.util.*;

За исключением периода развития, это обычай явно импортировать только необходимые классы, а не использовать шаблоны.


public class Card{
private short rank, suit;

Это, безусловно, правильный выбор для хранения ранга и масти, короткоес, так как это скорее всего самый быстрый и наиболее эффективный способ, но если вы хотите узнать специфику Java вы можете посмотреть в перечисления.


protected void setSuit(short suit){
this.suit = suit;
}

protected void setRank(short rank){
this.rank = rank;
}


Карты ИМХО являются ярким примером для неизменяемых объектов. Нет смысла нужно менять ранг и масть карты, так что я бы падение сеттеров.


public static String rankAsString(int __rank){
return ranks[__rank];
}

public static String suitAsString(int __suit){
return suits[__suit];
}


Это очень необычно, чтобы использовать подчеркивания в именах переменных в Java, особенно два в качестве префикса. Я бы просто назвать параметры ранг и костюм с класса (статических) методов и методов экземпляра нет, так что нет никакой путаницы с полями.

Может быть стоит задуматься, если эти на самом деле должны быть методами класса и не должны быть методами экземпляра. Если у вас есть другие классы, которые нужно преобразовать короткое в соответствующие имена независимо от карта класса, тогда было бы ок. Но в вашем случае я бы сказал, что это не так, и попытаться скрыть тот факт, что костюмы и ряды реализуются как короткиес как можно больше.


public @Override String toString(){
return rank + " of " + suit;
}

// Print card to string
protected String printCard(){
return ranks[rank] + " of " + suits[suit];
}


Java-сообщества разделен на вопрос, если метод toString() метод должен быть переопределен чисто для отладки причинам, или если он должен быть использован в "бизнес-логики". В этой "простой" я не думаю, что нужно различать два использует, так что я бы падение printCard() и использовать только метод toString().

Кстати, это традиция аннотации перед методом модификаторов.


public static boolean sameCard(Card card1, Card card2){
return (card1.rank == card2.rank && card1.suit == card2.suit);
}

Вместо того, чтобы реализовать свой собственный метод это, вероятно, хорошая идея, чтобы переопределить метод Equals() (или по крайней мере сделать это метод экземпляра). Если вы делаете карту незыблемы, как я предлагал раньше, это упрощает реализацию для сравнения ссылок, чтобы увидеть, если они одинаковы, потому что вы должны иметь только один экземпляр каждой карты.

@Override public boolean equals(Object that) {
return this == that;
}

(Хотя это может быть безопаснее, чтобы сравнить достоинства и масти, как падают обратно.)


Редактировать 1:

Сначала краткое отступление по поводу перечислений. Перечисления имеют порядковый номер и метод compareto метод, позволяющий сортировать их. Вы также можете назначить их свойства и создать свой собственный порядок, основанные на них.

Официальный язык руководство есть примеры для костюма и ранга enumations и для продления перечислений своими свойствами с использованием планеты в качестве примера: http://download.oracle.com/javase/1.5.0/docs/guide/language/enums.html

Когда/если я доберусь до силы рейтинге (я не смотрел на него) я, возможно, смогу дать некоторые предложения придется реализовать с помощью перечисления.


Далее идет компараторС. Я не имею много опыта с ними, поэтому я могу только дать некоторые общие рекомендации:


  • Занятия всегда должны начинаться с прописной буквы в Java.

  • Вы должны продлить их от компаратора вместо компаратора, так как вам нужно только сравнить карты друг с другом, а не с любыми другими объектами.
  • В то время как это хорошо, лишняя тренировка, вы можете пропустить иску компаратора, потому что не было необходимости в покере в целом (и Техасского Холдема в частности). Они никогда не имеют того, в рейтинге руку, как правило, нужна только в некоторых "мета" контекстах (например, случайным образом определяющие положение кнопки), что в настоящее время не применяются к вашей программе. Однако, если вы держите его, тогда вам необходимо правильный порядок костюмы, ведь официальный рейтинг (от низшего к высшему) "клубы", "ромбы", "сердечки" и "Пиковая дама".


  • Далее, является правление. Во-первых, я хочу сказать, что я не уверен, если я хотел бы использовать класс, как это в реальном мире приложение покер. Однако с верхней части моей головы я не могу думать о другой способ сделать это и на практике это прекрасно.

    Единственное что я бы изменил, это вместо явного задания каждой карточки индекса с setBoardCard(карта, инт cardNum), я бы дал совет класса отслеживать индекс внутри себя и просто использовать addBoardCard(карта), потому что вы не сможете "вернуться" и изменение карты (так же для расходных карт).


    Правка 2:

    Что касается костюмов сортировка: Ок, что имеет смысл. Я не смотрел на оценки силы еще. Однако, что больше в случае группирования, сортировки, поэтому, возможно, есть другой (лучше?) способ сделать это. Мне придется думать об этом.


    Отслеживание индексов: вы, безусловно, можете использовать коллекции (или, точнее Список) для этого (и это было бы более "Java-подобном", но в вашем случае, когда у вас есть фиксированное максимальное количество карт на борту массивы в порядке. Я бы что-то вроде:

    public class Board { //abbreviated

    private Card[] board = new Card[5];
    private Card[] burnCards = new Card[3];

    private int boardIndex = 0;
    private int burnCardIndex = 0;

    //methods
    protected void addBoardCard(Card card){
    this.board[boardIndex++] = card;
    }

    protected void addBurnCard(Card card){
    this.burnCards[burnCardIndex++] = card;
    }
    }


    Следующая колода:

    Сначала я предлагаю создать только один случайный объект статически, а не создавать для каждого вызова перемешать и cutDeck.

    Очень проблематичным является создание новой временной палубе объект для резки палубе. Это может пойти не так, очень быстро, потому что он содержит ненужный второй набор карт и, если есть ошибка, вы легко получите дубликат карты. Вместо того, чтобы просто использовать новый массив. Также вы можете использовать системы.arraycopy для упрощения копирования из одного массива в другой.

    Редактировать 3:

    Создание новой колоды не только создать новый массив, он создает в заполненный массив с новыми картами, которые вы не нуждаетесь. Просто массив достаточно:

    protected void cutDeck(){
    Card[] temp = new Card[52];
    Random random = new Random();
    int cutNum = random.nextInt(52);

    System.arraycopy(this.cards, 0, temp, 52-cutNum, cutNum);
    System.arraycopy(this.cards, cutNum, temp, 0, 52-cutNum);

    this.cards = temp;
    }


    Редактирование 4:

    Существует не так много, чтобы сказать об игрока , за исключением, я бы убрал визитная карточка и просто использовать конструктор, чтобы назначить карты игроку для того, чтобы сделать объект неизменяемым. Или хотя бы реализовать addCard способ как в доску.


    Основной класс:

    В getNumberOfPlayers свои ошибки справляюсь кое в чем противоречивы. С одной стороны вы пишете в систему.из (системы.подстраховатьсябы, наверное, лучше) и с другой стороны вы бросаете исключение.

    За исключение IOException я бы не поймать его здесь, но за пределами getNumberOfPlayers. В больших проектах это может иметь смысл, чтобы "обернуть" его в свой собственный класс исключений для этого:

    try { 
    userInput = br.readLine();
    } catch (IOException ioe) {
    throw new HoldemIOException(ioe);
    }

    Оба поймали NumberFormatException и неверный выбор должен бросать же (или смежной) пользовательские исключения. Не просто бросить простой исключение, потому что это бессмысленно для других, которые должны его поймать. Пример:

    try {
    intPlayers = Integer.parseInt(userInput);
    } catch (NumberFormatException nfe) {
    throw new HoldemUserException("Error: Not an integer entered for number of players", nfe);
    }

    if ((intPlayers<1) || (intPlayers>9)){
    throw new HoldemUserException("Error: Number of players must be an integer between 1 and 9");
    }

    Обратите внимание, что в результате исключительной ситуации IOException и NumberFormatException, передаются в качестве аргумента новое исключение на случай, если они понадобятся в дальнейшем.

    Как HoldemIOException и HoldemUserException может быть расширен от базовой HoldemException , который, в свою очередь, расширяет исключение. Простой "пустой" выдвижение таких как

    class HoldemException extends Exception {}

    для всех трех случаев будет достаточно.

    Также вы никогда не должны позволять исключение (особенно с собственной кинули) просто выпадают на конце никак не обрабатывается. Перехватывать все исключения вы знаете в разумное место, в вашем случае на getNumberOfPlayers:

    do {
    try {
    numPlayers = getNumberOfPlayers();
    } catch (HoldemUserException e) {
    System.out.println(e.getMessage());
    // "Only" a user error, keep trying
    } catch (HoldemIOException e) {
    System.err.println("Error: IO error trying to read input!");
    System.exit(1);
    }
    } while (numPlayers = 0);

    Я только добавил делать, пока петля, чтобы показать, как обрабатывать два типа исключений по-разному. Было бы разумно, чтобы добавить правильный способ для пользователя, чтобы выйти из петли.


    Раздача карт:

    Здесь у нас есть еще один счетчик (cardCounter) на пути к "позиции" колоды. Опять же было бы лучше иметь на палубе класса карты. Вы должны рассмотреть вопрос о выполнении палубе в качестве фактического "стек" или "очередь" - это не имеет значения, что, так как вы не добавления каких-либо элементов. Java обеспечивает очереди интерфейсу вы могли бы использовать.

    Думая об этом, вы могли бы также использовать один и тот же интерфейс для игрока и доски (хотя вы должны были бы отделить сжечь карты в свой собственный объект в этом случае). Что бы упростить дело для игрока.добавить(палубы.удалить());, доска.добавить(палубы.удалить()); и burnCards.добавить(палубы.удалить()).


    Редактировать 5:

    ОК, скорее всего окончательного редактирования.

    Я начал смотреть на оценки силы и я не думаю, что смогу много писать об этом. Вы реализовали это в очень процедурный способ, основанный на текущей карте объекты и если ваша цель сделать это в более Ява, как вы, вероятно, нужно переписать карточку объекта и создания соответствующего "силы" объект (скорее всего на основе набора), а затем снова написать характеристику на основе этого.

    Оценка покер-это очень сложная тема, особенно если учесть 5 карт из 7. Как это должно быть реализовано, будет зависеть от того, если вы хотите, чтобы сосредоточиться на "хорошей практике программирования на Java" или "скорость". Если вы действительно заинтересованы в расширении этого, то вы, вероятно, следует сначала почитать по теме - есть несколько вопросов, на переполнение стека об этом, и, наверное, бесчисленное количество статей на веб - и затем повторно отправить новый вопрос, сосредоточив внимание на оценке силы. Я буду рад посмотреть на что-нибудь - если у меня есть время.

    Просто одна конкретная вещь: какие константы в одну, две, три и четыре? Даже для процедурного подхода, казалось бы, совершенно неуместны и не должны, скорее всего, будет заменен на соответствующий цикл, в котором они используются.


    И наконец, получайте удовольствие и удачи в ваших дальнейших приключениях в Java!

    38
    ответ дан 22 марта 2011 в 05:03 Источник Поделиться

    Разделение класса texasholdem и со всеми его логике (количество игроков, счетчики, ...) от того, как вы его не инициализируете.

    Ваша главная поедет в TexasHoldemProgram класс, который инстанцирует texasholdem в класс, и задает, например, количество игроков в качестве вклада в основной.

    Эта практика называется модель-представление-контроллер шаблон. Разделяя логику игры от взаимодействия с ним, позже вы можете повторно использовать класс с совершенно другой интерфейс. Вы, вероятно, следует применить это в других частях кода, но я не досконально просматриваю все.

    В остальном ваша реализация выглядит довольно хорошо структурирован, но я могу обновить этот ответ, если я найду другие вещи, которые стоит отметить, что не упоминалось в других ответов. Удачи использованием Java!

    3
    ответ дан 23 марта 2011 в 01:03 Источник Поделиться