Wednesday, May 23, 2012

Java ...an unfinished poker game

Well, here is the source code...

package poker;

public class Card {

    public Card(Suit suit, Rank rank) {
        this.suit = suit;
        this.rank = rank;

    }
    public Card(short _suit, short _cardnumber)
    {
        switch (_suit) {
        case 1 :
            this.suit = Suit.CLUBS;
            break;
        case 2 :
            this.suit = Suit.DIAMONDS;
            break;
        case 3 :
            this.suit = Suit.HEARTS;
            break;
        case 4 :
            this.suit = Suit.SPADES;
            break;
        default :
            break;
        }

        switch (_cardnumber) {
        case 1 :
            this.rank = Rank.ACE;
            break;
        case 2 :
            this.rank = Rank.KING;
            break;
        case 3 :
            this.rank = Rank.QUEEN;
            break;
        case 4 :
            this.rank = Rank.JACK;
            break;
        case 5 :
            this.rank = Rank.TEN;
            break;
        case 6 :
            this.rank = Rank.NINE;
            break;
        case 7 :
            this.rank = Rank.EIGHT;
            break;
        case 8 :
            this.rank = Rank.SEVEN;
            break;
        case 9 :
            this.rank = Rank.SIX;
            break;
        case 10 :
            this.rank = Rank.FIVE;
            break;
        case 11 :
            this.rank = Rank.FOUR;
            break;
        case 12 :
            this.rank = Rank.THREE;
            break;
        case 13 :
            this.rank = Rank.TWO;
            break;
        default : break;
        }
    }

    @Override
    public String toString() {
        return rank.toString().toLowerCase() + " of " + suit.toString().toLowerCase();
    }
   
    @Override
    public int hashCode() {
       
        int _hash = 7; 
        _hash = _hash * 31 + suit.hashCode(); 
        _hash = _hash * 31 + rank.hashCode(); 
        return _hash;  
    }

    @Override
    public boolean equals (Object other) {
        if ((other == null) || (!(other instanceof Card))) return false;

        if (this == other) return true;
       
        if (getClass() != other.getClass()) return false;
       
        Card card = (Card) other;
        return  card.suit == this.suit &&
                card.rank == this.rank &&
                other.hashCode() == this.hashCode();   
    }

protected enum Suit {
        CLUBS("Clubs"), DIAMONDS("Diamonds"), HEARTS("Hearts"), SPADES("Spades");

        private String name;
        Suit(String name) { this.name = name; }
        public String getName() { return name; }
    }

    protected enum Rank {
        ACE("Ace"), KING("King"), QUEEN("Queen"), JACK("Jack"), TEN("Ten"),
        NINE("Nine"), EIGHT("Eight"), SEVEN("Seven"), SIX("Six"), FIVE("Five"),
        FOUR("Four"), THREE("Three"), TWO("Two");

        private String name;
        Rank(String name) { this.name = name; }
        public String getName() { return name; }
    }

    public Suit getSuit() {
        return this.suit;}

    public Rank getRank() {
        return this.rank;
    }   
    public static int RANKING_CARDS_PER_SUIT = 13;
    public static int SUIT_COUNT = 4;
    @SuppressWarnings("unused")
    private static boolean isJokerAvailable = false;

    private Suit suit;
    private Rank rank;

}

# The root logger is assigned priority level DEBUG and an appender named
# consoleAppender.
log4j.rootLogger=DEBUG,consoleAppender, fileAppender

# The appender's type specified as ConsoleAppender, i.e. log output to
# the Eclipse console. (Could have been FileAppender.)
#log4j.appender.consoleAppender=org.apache.log4j.ConsoleAppender

# Stdout
# The appender is assigned a layout SimpleLayout. SimpleLayout will
# include only priority level of the log statement and the log statement
# itself in the log output.
#log4j.appender.consoleAppender.layout=org.apache.log4j.SimpleLayout

# File
log4j.appender.fileAppenderAppender.file=poker_debug.log
log4j.appender.fileAppender.maxFileSize=1Mb

# Archive log files (one backup file here)
log4j.appender.fileAppender.MaxBackupIndex=1

log4j.appender.myAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.fileAppender.layout=org.apache.log4j.PatternLayout

log4j.appender.consoleAppender.layout.ConversionPattern=[%d{ISO8601}]%5p%6.6r[%t]%x - %C.%M(%F:%L) - %m%n
log4j.appender.fileAppender.layout.ConversionPattern=[%d{ISO8601}]%5p%6.6r[%t]%x - %C.%M(%F:%L) - %m%n

package poker;
import java.util.*;
import org.apache.log4j.BasicConfigurator;
public class Player {

public Player (String _name, Double _balance) {
    this.name = _name;
    this.balance = _balance;
}

public ArrayList<Card> getCardsHeld() {return CardsHeld;}
public void getCardFromDealer (Card _card) {CardsHeld.add(_card);}

public boolean equals (Object other) {
    if ((other == null) || (!(other instanceof Player))) return false;

    if (this == other) return true;
   
    if (getClass() != other.getClass()) return false;
   
    @SuppressWarnings("unused")
    Player _player = (Player) other;
    return  this.hashCode() == other.hashCode();   
}

public String toString() {
   
    String _cardsHeld = "";
    for (int i = 0; i < CardsHeld.size(); i++)         {_cardsHeld += CardsHeld.get(i).toString() + "; ";}
   
    return (name + " holds the following cards: " + _cardsHeld) ;
}

public int hashCode() {
    int _hash = 7;
    int _cpCount = this.name.codePointCount(0, this.name.length());
    int _codePointV = 0;
   
    for (_cpCount = 0; _cpCount < this.name.codePointCount(0, this.name.length()); _cpCount++) {
        _codePointV += this.name.codePointAt(_cpCount);
    }
    _hash = _hash * 31 + _codePointV; 
    return _hash;
}
private ArrayList<Card> CardsHeld = new ArrayList<Card>();

public String getName () {return name; }
public Double getBalance () {return balance;}
public boolean betAmount(Double _amountToBet) {
    if (_amountToBet <= balance) {
        balance -= _amountToBet;
        return true;}
   
    else return false;
}
public void addWinnings (Double _amountWon){
        balance += _amountWon;
}
public void setRanking (short _winningRank){
    this.winningRank = _winningRank;
}
public short getRanking () {return this.winningRank;}

public long getCurrentGameScore() {return this.scoreOfCurrentGame;}
public void setCurrentGameScore(long _currentScore) {
    this.scoreOfCurrentGame = _currentScore;
    if (_currentScore > this.highScore) this.highScore = _currentScore;}
   
public long getHighScore() {return this.highScore;}

private String name;
private Double balance;
private short winningRank;
private long scoreOfCurrentGame;
private long highScore;
//TODO: persist stats on text file
}

@echo off
set CLASSPATH=.
javac *.java
java -Dlog4j.debug=true Poker
pause

package poker;

import java.awt.Image;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import javax.imageio.ImageIO;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
public class Poker {

    /* "Magic numbers" to be replaced by parameters loaded from text file e.g. poker.init */
    public static final short MAX_CARDS_IN_DECK = 52;
    public static final short MAX_SUITS_IN_DECK = 4;
    public static final short MAX_RANK_IN_DECK = 13;
    public static final short MAX_PLAYERS_PER_TABLE = 5;
    public static final short MAX_GAMES = 1;
    //TODO:
    //1. getWinners() review and maybe use Map instead of Enums, including:
        //1a. Poker winning hands not being returned correctly.
        //1b. Poker winning hands being repeated e.g. Player One gets full house, and, Player One to Player Five (inclusive), get full house.
    //2. review code and clean up, test etc.
    //3. implement Joker, which can act as a wild card (Card.java and Poker.java) FIX.
    //4. UI, concurrent games and tables,  and, probability statistics (future).

    public static double amountOnTable;
    public static final String CURRENCY_SYMBOL = "€";

    public static void main(String[] args) {

    BasicConfigurator.configure();

    readIcons();

    boolean shuffled = true;
    getCards(shuffled);

    Player playerOne = new Player("Player One", 10000.00);
    playerOne.getCardFromDealer(getTopCard());
    playerOne.getCardFromDealer(getTopCard());
    if (playerOne.betAmount(100.00) == false) {System.out.println("WARNING: Player tried to bet " + CURRENCY_SYMBOL + "100.00, whilst the balance available is " + CURRENCY_SYMBOL + playerOne.getBalance());}


    Player playerTwo = new Player("Player Two", 10000.0);
    playerTwo.getCardFromDealer(getTopCard());
    playerTwo.getCardFromDealer(getTopCard());
    Double _amountforPlayerTwo = 10000.0;
    if (playerTwo.betAmount(_amountforPlayerTwo) == false) {System.out.println("WARNING: Player tried to bet " + CURRENCY_SYMBOL + _amountforPlayerTwo + ", whilst the balance available is " + CURRENCY_SYMBOL + playerTwo.getBalance());}

    Player playerThree = new Player("Player Three", 10000.0);
    playerThree.getCardFromDealer(getTopCard());
    playerThree.getCardFromDealer(getTopCard());
    if (playerThree.betAmount(100.00) == false) {System.out.println("WARNING: Player tried to bet " + CURRENCY_SYMBOL + "100.00, whilst the balance available is " + CURRENCY_SYMBOL + playerThree.getBalance());}

    Player playerFour = new Player("Player Four", 10000.0);
    playerFour.getCardFromDealer(getTopCard());
    playerFour.getCardFromDealer(getTopCard());
    if (playerFour.betAmount(100.00) == false) {System.out.println("WARNING: Player tried to bet " + CURRENCY_SYMBOL + "100.00, whilst the balance available is " + CURRENCY_SYMBOL + playerFour.getBalance());}

    Player playerFive = new Player("Player Five", 10000.0);
    playerFive.getCardFromDealer(getTopCard());
    playerFive.getCardFromDealer(getTopCard());
    if (playerFive.betAmount(100.00) == false) {System.out.println("WARNING: Player tried to bet " + CURRENCY_SYMBOL + "100.00, whilst the balance available is " + CURRENCY_SYMBOL + playerFive.getBalance());}

    for (int iBettingRounds = 0; iBettingRounds < 3; iBettingRounds++) {
        playerOne.getCardFromDealer(getTopCard());
        playerOne.betAmount(100.00);

        playerTwo.getCardFromDealer(getTopCard());
        playerTwo.betAmount(100.00);

        playerThree.getCardFromDealer(getTopCard());
        playerThree.betAmount(100.00);

        playerFour.getCardFromDealer(getTopCard());
        playerFour.betAmount(100.00);

        playerFive.getCardFromDealer(getTopCard());
        playerFive.betAmount(100.00);
    }

    System.out.println(playerOne);
    System.out.println(playerTwo);
    System.out.println(playerThree);
    System.out.println(playerFour);
    System.out.println(playerFive);

    System.out.println("Cards held by dealer:");
    for (int i = 0; i < deckOfCards.size(); i++) { System.out.println((i + 1) +"." + deckOfCards.get(i));}

    deckOfCards.trimToSize();

    ArrayList<Player> _players = new ArrayList<Player>();
    _players.add(playerOne);
    _players.add(playerTwo);
    _players.add(playerThree);
    _players.add(playerFour);
    _players.add(playerFive);
    System.out.println("And the winners are...");
    for (Player _p: getWinner(_players)) {
        System.out.println (_p + "Score: " + _p.getCurrentGameScore() + " High Score: " + _p.getHighScore());
    }

    }
    private static void getCards (boolean _shuffled) {
        short iCount = 0;
        for (short suit = 1; suit <= MAX_SUITS_IN_DECK; suit++){
            for (short rank = 1; rank <= MAX_RANK_IN_DECK; rank++) {
                deckOfCards.add(iCount, new Card(suit, rank));
                iCount++;
            }}

        if (_shuffled == true){Collections.shuffle(deckOfCards, new Random());}

    }

    private static Card getTopCard() {
        Card _cardRemoved = deckOfCards.get(1);
        deckOfCards.remove(1);
        return _cardRemoved;
    }

    private static void readIcons(){

        String _filename;

        //read icons
        Image _image = null;
        File _file = null;
        InputStream _is = null;
        for (int i = 1; i < MAX_CARDS_IN_DECK + 1; i++) {
        try {

            /* Security information: filenames should not be altered manually by an Administrator, and,
             should be available within the same directory where the source code runs. */

                if (i < 10) {_filename = "0" + Integer.toString(i);}
                else {_filename = Integer.toString(i);}

                String _temp = _filename;
                _filename = _temp + ".GIF";

                //TODO: Relative path might change when implementing?
                _filename = System.getProperty("user.dir") + "\\img\\" + _filename;

            _file = new File(_filename);

            //read from an input stream
            _is = new BufferedInputStream (new FileInputStream(_filename));

            _image = ImageIO.read(_is);
            if (_file.exists()) {
            CardIcons.add(_image);
            //_log.debug(_filename + " loaded.");
            }
        }
        catch (IOException e) { _log.debug(e.getMessage()); }
        }
    }

    private static byte[] countCardsByRank (ArrayList<Card> _cardsAtHand) {
        byte _cardsByRank[] = new byte[MAX_RANK_IN_DECK];
        for (Card _card : _cardsAtHand) {
       
            _cardsByRank[_card.getRank().ordinal()] += (byte) _card.getRank().ordinal();
        }
        return _cardsByRank;
    }
   
    //TODO: write ranking rules
    private static ArrayList<Player> getWinner(ArrayList<Player> _players) {

        ArrayList<Player> _winners = new ArrayList<Player>();
        /*TODO: FIX: getWinner() being filled with multiple instances of Players, not just "winners".

        /*TODO:    1. Player.setRanking(_ranking) for each of the players:
        Ranking
        for hand # - highest ranking wins

        _highCardPoints = High-card ranking scores                                                                Score
        Card.Rank.Suit.ACE                                                                                        +14
        Card.Rank.Suit.KING                                                                                        +13
        Card.Rank.Suit.QUEEN                                                                                    +12
        Card.Rank.Suit.JACK                                                                                        +11
        Card.Rank.Suit.TEN                                                                                        +10
        Card.Rank.Suit.NINE                                                                                        +9
        Card.Rank.Suit.EIGHT                                                                                    +8
        Card.Rank.Suit.SEVEN                                                                                    +7
        Card.Rank.Suit.SIX                                                                                        +6
        Card.Rank.Suit.FIVE                                                                                        +5
        Card.Rank.Suit.FOUR                                                                                        +4
        Card.Rank.Suit.THREE                                                                                    +3
        Card.Rank.Suit.TWO                                                                                        +2

        _handRanking = Scores by hand ranking
        ----------------------
        1.         Straight flush.  Five cards in sequence all of the same suit.                                    *1000000000
        2.         Four of a kind.  Four cards of the same rank i.e. two pairs.                                    *100000000
        3.        Full house.         Three cards of the same rank, and, a pair of cards with the same rank.            *10000000
        4.        Flush.             Five cards of the same suit.                                                    *1000000
        5.        Straight.         Five cards in sequence, not necessarily of the same suit.                        *100000
        6.         Three of a kind. Three cards of the same rank.                                                    *10000
        7.        Two pair.        Two pairs of cards, each having the same rank.  Higher ranks win.                *1000
        8.        One pair.        One pair of cards with the same rank.                                            *100
        9.      High card.        Cards in order of their rank.                                                     *10


        Higher cards get higher points.
        Further information at http://en.wikipedia.org/wiki/Poker_hands.
        */

        /*TODO: If two or more players have equal high ranking, then players get to split the pot, hence, add both players to the winning
                ArrayList and return the ArrayList.
        */

        int _suitCount = 0;
        int _rankCount = 0;
        ArrayList<Card> _cardsAtHand = new ArrayList<Card>();
        long _highScore = 0;

        //scores will be in the same order as _players
        long _handRanking[] = new long[_players.size()];
        int _highCardPoints[] = new int[_players.size()];
        long _totalScore[] = new long[_players.size()];

        for (Player _p : _players) {
            boolean _rankingFound = false;

            for (int iPlayer = 0; iPlayer < _players.size(); iPlayer++) {
            _cardsAtHand = _players.get(iPlayer).getCardsHeld();

            /* Straight flush */
            for (Card _card: _cardsAtHand) {

                _suitCount += _card.getSuit().ordinal();

                switch (_card.getRank()) {
                    case ACE     :    {_rankCount += Card.Rank.ACE.ordinal();
                                     _highCardPoints[iPlayer] += 14;
                                     break; }
                    case KING     :    {_rankCount += Card.Rank.KING.ordinal();
                                    _highCardPoints[iPlayer] += 13;
                                    break;}
                    case QUEEN    :    {_rankCount += Card.Rank.QUEEN.ordinal();
                                    _highCardPoints[iPlayer] +=12;
                                    break;}
                    case JACK    :    {_rankCount += Card.Rank.JACK.ordinal();
                                    _highCardPoints[iPlayer] += 11;
                                    break;}
                    case TEN    :    {_rankCount += Card.Rank.TEN.ordinal();
                                    _highCardPoints[iPlayer] += 10;
                                    break;}
                    case NINE    :    {_rankCount += Card.Rank.NINE.ordinal();
                                    _highCardPoints[iPlayer] += 9;
                                    break;}
                    case EIGHT    :    {_rankCount += Card.Rank.EIGHT.ordinal();
                                    _highCardPoints[iPlayer] += 8;
                                    break;}
                    case SEVEN  :     {_rankCount += Card.Rank.SEVEN.ordinal();
                                    _highCardPoints[iPlayer] += 7;
                                    break;}
                    case SIX     :    {_rankCount += Card.Rank.SIX.ordinal();
                                    _highCardPoints[iPlayer] += 6;
                                    break;}
                    case FIVE    :    {_rankCount += Card.Rank.FIVE.ordinal();
                                    _highCardPoints[iPlayer] += 5;
                                    break;}
                    case FOUR    :    {_rankCount += Card.Rank.FOUR.ordinal();
                                    _highCardPoints[iPlayer] += 4;
                                    break;}
                    case THREE    :    {_rankCount += Card.Rank.THREE.ordinal();
                                    _highCardPoints[iPlayer] += 3;
                                    break;}
                    case TWO    :    {_rankCount += Card.Rank.TWO.ordinal();
                                    _highCardPoints[iPlayer] += 2;
                                    break;}
                    default        :    break;
                }
            }
            /* all hands must be from the same suit, hence, the total points must be the squares of the Card.Suit.<RANK>.ordinal() values */
            //TODO: FIX - not working as expected.
            if (!(_suitCount == 0 || _suitCount == 5 || _suitCount == 10 || _suitCount == 15)) {
                _handRanking[iPlayer] = 0;
                _highCardPoints [iPlayer]= 0; }

                else if ( (_rankCount >= 10) && (_rankCount <=50) && ((_rankCount % 5) == 0) )    {
                    _rankingFound = true;
                    _handRanking[iPlayer] = 1000000000;
                    _winners.add(_p);

                    if (_highCardPoints[iPlayer] == 60)  _log.debug("Royal flush" + _p);
                    else _log.debug("Straight flush " + _p);}

            if (!_rankingFound) {
                /* 2. Four of a kind*/

                for (Card _card : _cardsAtHand) {
                    _rankCount += _card.getRank().ordinal();
                }

                if ((_rankCount > 0) && (_rankCount < 48) && (_rankCount % 4 == 0))  {
                    _rankingFound = true;
                    _handRanking[iPlayer] = 100000000;
                    _log.debug("Four of a kind " + _p);
                }}

            if (!_rankingFound) {
                /* 3. Full house */
                byte[] _cardsByRank = countCardsByRank(_cardsAtHand);
               
                boolean _foundThreeOfARank = false;
                boolean _foundPairOfARank = false;
                //TODO: FIX ArrayIndexOutOfBoundsException
                for (byte i : _cardsByRank) {
                    if (_cardsByRank[i]==3) _foundThreeOfARank = true;
                }
                for (byte i : _cardsByRank) {
                    if (_cardsByRank[i]==2) _foundPairOfARank = true;
                }
               
                if (_foundThreeOfARank && _foundPairOfARank) _rankingFound = true;
                _handRanking[iPlayer] = 10000000;
                _log.debug("Full house " + _p);
            }

            if (!_rankingFound) {
                /* 4. Flush */
            }

            if (!_rankingFound) {
                /* 5. Straight */
            }

            if (!_rankingFound) {
                /* 6. Three of a kind */
            }

            if (!_rankingFound) {
                /* 7. Two pair */
            }

            if (!_rankingFound) {
                /* 8. One pair */
            }

            if (!_rankingFound) {
                /* 9. High cards */
            }

            if (!_rankingFound) {
                /* dummy - TODO: delete*/
                _highScore = 0;

            }
        _totalScore[iPlayer] = _highCardPoints[iPlayer] * _handRanking[iPlayer];
        _p.setCurrentGameScore(_totalScore[iPlayer]);

        //read high scores
        for (Player _playersWhoScored: _players) {
            if (_highScore < _playersWhoScored.getCurrentGameScore()) {_highScore = _totalScore[iPlayer];}
            iPlayer++;
        }

        }}

        //set winners are...
        short _iPlayer = 0;
        for (Player _playersWhoScored: _players ) {
            if (_playersWhoScored.getCurrentGameScore() == _highScore) {_winners.add(_playersWhoScored);}
            _iPlayer++;
        }
        _winners.trimToSize();
        return _winners;
    }

   

    private static ArrayList<Image> CardIcons = new ArrayList<Image>();
    private static ArrayList<Card> deckOfCards = new ArrayList<Card>();
    private static final Logger _log = Logger.getLogger(Poker.class);


    /* References
     * ----------
     * Texas Hold'em rules are used throughout the game.
     * Information about poker at http://en.wikipedia.org/wiki/Poker.
     * List of poker hands at http://en.wikipedia.org/wiki/Poker_hands.
     * Rules for Texas Hold'Em at http://en.wikipedia.org/wiki/Texas_hold_'em.  This will be implemented at a later stage.
     * Steve Badger, How to Play Poker at http://www.playwinningpoker.com/articles/how-to-play-poker.
     * Graphics to be implemented at a later stage.
     */
}

ETC Business Planning - Importing Accessories From Indonesia (Draft) by Jon C.

You can help a brother pay University Fees...

You may credit IBAN MT64APSB77046002349520000853602 or send cash/cheque by post to Jonathan Camilleri, 33, L. Casolani street, Birkirkara BKR4535, Malta, Europa

No comments:

Post a Comment