HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMajor

Texas Hold'em in Java

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
holdjavatexas

Problem

I have been a programmer for 12 years, mainly ERP software and C development and
am looking to make a career/specialty change to Java. I've read it countless
times if you want to learn a new language you need to write code, then write
some more code and then finally write more code. So I've written some code!

I love Poker, so I have written a small Texas Hold'em program. Here is the overview of what it does:

  • Asks the user for the number of players



  • Create a deck of cards



  • Shuffle



  • Cut the deck



  • Deal players hole cards



  • Burns a card



  • Deals flop



  • Burns a card



  • Deals turn



  • Burns a card



  • Deals river



  • Prints the deck to console to show random deck was used



  • Prints the 'board'



  • Prints burn cards



  • Printers players cards



  • Evaluates the value of each players hand (Royal flush, full house, etc...)



There are 6 .java files (see below for links). I used an interface, created my own comparators, even implemented some try/catch blocks (although I'm still learning how to use these properly).

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;i9)){
            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){

Solution

Let's start with the most basic, the Card class.

import java.util.*;


Except during development, it's custom to explicitly import only the classes you need instead of using wildcards.

public class Card{
    private short rank, suit;


It's is most certainly a valid choice to store rank and suit as shorts, since it's most likely the fastest and most efficient way, but if you want to learn the specifics of Java you may want to look into enumerations.

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

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


IMHO cards are a prime example for immutable objects. There is no reason to need to change the rank or the suit of a card, so I would drop the setters.

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

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


It's very unusual to use underlines in variable names in Java, especially two as a prefix. I would simple name the parameters rank and suit especially since these are class (static) methods and not instance methods, so there is no confusion with the fields.

It may be worth thinking about, if these actually need to be class methods and shouldn't be instance methods. If you have other classes which need to convert short into the corresponding names independently from the Card class, then it would be ok. But in your case I would say it's not the case, and one should try and hide the fact that suits and ranks are implemented as shorts as much as possible.

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

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


The Java community is split over the question, if the toString() method should be overridden purely for debugging reasons, or if it should be used in the "business logic". In this "simple" application I don't think you need to distinguish between the two uses, so I would drop printCard() and only use toString().

BTW, it's custom to have annotations before the method modifiers.

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


Instead of implementing your own method it's probably a good idea to override equals() (or at least make this an instance method). If you make Card immutable as I suggested before, it simplifies the implementation to comparing the references, to see if they are the same, because you should only have one instance of each possible card.

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


(Although it may be safer to compare rank and suit as a fall back.)

EDIT 1:

First a quick digression about Enumerations. The Enums have an ordinal number and a compareTo method, allowing you to sort them. You also can assign them properties and create your own order based on those.

The offical language guide has examples for suit and rank enumations and for extending enumerations with your own properties using planets as an example: http://download.oracle.com/javase/1.5.0/docs/guide/language/enums.html

When/if I get to the hand ranking (I haven't looked at it yet) I may be able to give some suggestions have to implement it with enums.

Next are the Comparators. I don't have much experience with them, so I can only give some general suggestions:

  • Classes should always start with a capital letter in Java.



  • You should extend them from Comparator instead of Comparator, since you only need to compare cards with each other and not with any other objects.



  • While it is good extra practice, you may want to skip the suit comparator, because it's not really needed in Poker in general (and Texas Hold'em specifically). Suits never have an order in hand ranking usually only needed in some "meta" contexts (such as randomly determinating the position of the button), that currently don't apply to your program. However if you do keep it, then you should correct the order of the suits, because the official ranking is (from lowest to highest) "Clubs", "Diamonds", "Hearts" and "Spades".



Next up, is the Board. First off, I'd like to say, that I'm nor sure if I'd use a Board class like this in a real world Poker application. However off the top of my head I can't think of a different way to do it and for practice this is perfectly fine.

The only thing I would change is instead of explicitly setting each card by index with setBoardCard(Card card, int cardNum), I would let the Board class track the index internally itself and just use addBoardCard(Card card), because you shouldn't be able to "go back" and change the board cards (ditto for the burn cards).

EDIT 2:

Regarding sorting suits: Ok, that makes sense. I haven't looked at hand evaluation yet. However that is more a case of grouping that sorting, so maybe there is a different (bette

Code Snippets

import java.util.*;
public class Card{
    private short rank, suit;
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];
}
public @Override String toString(){
    return rank + " of " + suit;
}

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

Context

StackExchange Code Review Q#1382, answer score: 38

Revisions (0)

No revisions yet.