# Poker Odds Calculation with Monte Carlo

I have created an Odds Calculator in Java. The program gives me the odds, but I want to make sure that they are correct. Maybe someone can tell me a calculator I can compare my results with or knows another way to check if the odds are correct? With the calculator you can set your own hand plus the cards on the table. Also I want to optimize the MonteCarlo class so that it's as fast and efficient as possible. I have removed the init method otherwise the post contains to many characters, How to optimize the MonteCarlo class?

MonteCarlo.java

public class MonteCarlo {

Game game=new Game();
private long numberOfLoops=0L;
private long currentLoop = 0L;
private boolean running = false;
private Random prng = new Random();
private String knownCards;

public MonteCarlo(String knownCards, long numberOfLoops, int numberOfPlayers) {
/*
* Parse initial game options from command line.
*/
if (numberOfPlayers < Constants.MIN_NUMBER_OF_PLAYERS) {
numberOfPlayers = Constants.MIN_NUMBER_OF_PLAYERS;
}
if (numberOfPlayers > Constants.MAX_NUMBER_OF_PLAYERS) {
numberOfPlayers = Constants.MAX_NUMBER_OF_PLAYERS;
}

if (numberOfLoops < Constants.MIN_NUMBER_OF_LOOPS) {
numberOfLoops = Constants.MIN_NUMBER_OF_LOOPS;
}
if (numberOfLoops > Constants.MAX_NUMBER_OF_LOOPS) {
numberOfLoops = Constants.MAX_NUMBER_OF_LOOPS;
}

/*
* Initialize the table with players and cards.
*/
init(numberOfPlayers);

this.knownCards = knownCards;
this.numberOfLoops = numberOfLoops;
}

/* Evaluate one pair */
public HandStrength evaluateOnePair(Card[] hand) {
HandStrength result = new HandStrength();
result.fifthKicker = 0;
result.fourthKicker = 0;
result.thirdKicker = 0;
result.secondKicker = 0;
result.firstKicker = 0;
result.onePair = 0;
result.twoPair = 0;
result.threeOfKind = 0;
result.straight = 0;
result.flush = 0;
result.fullHouse = 0;
result.fourOfKind = 0;
result.straightFlush = 0;

if (hand[0].kind == hand[1].kind && hand[0].kind != hand[2].kind && hand[0].kind != hand[3].kind && hand[0].kind != hand[4].kind) {
result.onePair = hand[0].kind;
result.firstKicker = hand[2].kind;
result.secondKicker = hand[3].kind;
result.thirdKicker = hand[4].kind;
}

if (hand[1].kind == hand[2].kind && hand[1].kind != hand[0].kind && hand[1].kind != hand[3].kind && hand[1].kind != hand[4].kind) {
result.onePair = hand[1].kind;
result.firstKicker = hand[0].kind;
result.secondKicker = hand[3].kind;
result.thirdKicker = hand[4].kind;
}

if (hand[2].kind == hand[3].kind && hand[2].kind != hand[0].kind && hand[2].kind != hand[1].kind && hand[2].kind != hand[4].kind) {
result.onePair = hand[2].kind;
result.firstKicker = hand[0].kind;
result.secondKicker = hand[1].kind;
result.thirdKicker = hand[4].kind;
}

if (hand[3].kind == hand[4].kind && hand[3].kind != hand[0].kind && hand[3].kind != hand[1].kind && hand[3].kind != hand[2].kind) {
result.onePair = hand[3].kind;
result.firstKicker = hand[0].kind;
result.secondKicker = hand[1].kind;
result.thirdKicker = hand[2].kind;
}

return (result);
}

/* Evaluate two pair */
public HandStrength evaluateTwoPair(Card[] hand) {
HandStrength result = new HandStrength();
result.fifthKicker = 0;
result.fourthKicker = 0;
result.thirdKicker = 0;
result.secondKicker = 0;
result.firstKicker = 0;
result.onePair = 0;
result.twoPair = 0;
result.threeOfKind = 0;
result.straight = 0;
result.flush = 0;
result.fullHouse = 0;
result.fourOfKind = 0;
result.straightFlush = 0;

if (hand[0].kind == hand[1].kind && hand[2].kind == hand[3].kind && hand[0].kind != hand[2].kind && hand[0].kind != hand[4].kind && hand[2].kind != hand[4].kind) {
result.twoPair = hand[0].kind;
result.onePair = hand[2].kind;
result.firstKicker = hand[4].kind;
}

if (hand[0].kind == hand[1].kind && hand[3].kind == hand[4].kind && hand[0].kind != hand[3].kind && hand[0].kind != hand[2].kind && hand[3].kind != hand[2].kind) {
result.twoPair = hand[0].kind;
result.onePair = hand[3].kind;
result.firstKicker = hand[2].kind;
}

if (hand[1].kind == hand[2].kind && hand[3].kind == hand[4].kind && hand[1].kind != hand[3].kind && hand[1].kind != hand[0].kind && hand[3].kind != hand[0].kind) {
result.twoPair = hand[1].kind;
result.onePair = hand[3].kind;
result.firstKicker = hand[0].kind;
}

return (result);
}

/* Evaluate three of a kind */
private HandStrength evaluateThreeOfKind(Card[] hand) {
HandStrength result = new HandStrength();
result.fifthKicker = 0;
result.fourthKicker = 0;
result.thirdKicker = 0;
result.secondKicker = 0;
result.firstKicker = 0;
result.onePair = 0;
result.twoPair = 0;
result.threeOfKind = 0;
result.straight = 0;
result.flush = 0;
result.fullHouse = 0;
result.fourOfKind = 0;
result.straightFlush = 0;

if (hand[0].kind == hand[1].kind && hand[0].kind == hand[2].kind && hand[0].kind != hand[3].kind && hand[0].kind != hand[4].kind && hand[3].kind != hand[4].kind) {
result.threeOfKind = hand[0].kind;
result.firstKicker = hand[3].kind;
result.secondKicker = hand[4].kind;
}

if (hand[1].kind == hand[2].kind && hand[1].kind == hand[3].kind && hand[1].kind != hand[0].kind && hand[1].kind != hand[4].kind && hand[0].kind != hand[4].kind) {
result.threeOfKind = hand[1].kind;
result.firstKicker = hand[0].kind;
result.secondKicker = hand[4].kind;
}

if (hand[2].kind == hand[3].kind && hand[2].kind == hand[4].kind && hand[2].kind != hand[0].kind && hand[2].kind != hand[1].kind && hand[0].kind != hand[1].kind) {
result.threeOfKind = hand[2].kind;
result.firstKicker = hand[0].kind;
result.secondKicker = hand[1].kind;
}

return (result);
}

/* Evaluate straight */
private HandStrength evaluateStraight(Card[] hand) {
HandStrength result = new HandStrength();
int i;
int found = 0;

result.fifthKicker = 0;
result.fourthKicker = 0;
result.thirdKicker = 0;
result.secondKicker = 0;
result.firstKicker = 0;
result.onePair = 0;
result.twoPair = 0;
result.threeOfKind = 0;
result.straight = 0;
result.flush = 0;
result.fullHouse = 0;
result.fourOfKind = 0;
result.straightFlush = 0;

found = 1;
for (i = 0; i < Constants.NUMBER_OF_EVALUATION_HAND_CARDS - 1; i++) {
if (hand[i].kind - hand[i + 1].kind != 1) {
found = 0;
break;
}
}
if (found == 1) {
result.straight = hand[0].kind;
}

found = 1;
if (hand[0].kind != Constants.CARD_KIND_ACE || hand[1].kind != Constants.CARD_KIND_FIVE) {
found = 0;
}
for (i = 1; i < Constants.NUMBER_OF_EVALUATION_HAND_CARDS - 1; i++) {
if (hand[i].kind - hand[i + 1].kind != 1) {
found = 0;
break;
}
}
if (found == 1) {
result.straight = hand[1].kind;
}

return (result);
}

/* Evaluate flush */
private HandStrength evaluateFlush(Card[] hand) {
HandStrength result = new HandStrength();
int i;
int found = 0;

result.fifthKicker = 0;
result.fourthKicker = 0;
result.thirdKicker = 0;
result.secondKicker = 0;
result.firstKicker = 0;
result.onePair = 0;
result.twoPair = 0;
result.threeOfKind = 0;
result.straight = 0;
result.flush = 0;
result.fullHouse = 0;
result.fourOfKind = 0;
result.straightFlush = 0;

found = 1;
for (i = 1; i < Constants.NUMBER_OF_EVALUATION_HAND_CARDS; i++) {
if (hand[0].suit != hand[i].suit) {
found = 0;
break;
}
}
if (found == 1) {
result.flush = 1;
result.firstKicker = hand[0].kind;
result.secondKicker = hand[1].kind;
result.thirdKicker = hand[2].kind;
result.fourthKicker = hand[3].kind;
result.fifthKicker = hand[4].kind;
}

return (result);
}

/* Evaluate fullhouse */
private HandStrength evaluateFullHouse(Card[] hand) {
HandStrength result = new HandStrength();
result.fifthKicker = 0;
result.fourthKicker = 0;
result.thirdKicker = 0;
result.secondKicker = 0;
result.firstKicker = 0;
result.onePair = 0;
result.twoPair = 0;
result.threeOfKind = 0;
result.straight = 0;
result.flush = 0;
result.fullHouse = 0;
result.fourOfKind = 0;
result.straightFlush = 0;

if (hand[0].kind == hand[1].kind && hand[0].kind == hand[2].kind && hand[3].kind == hand[4].kind && hand[0].kind != hand[3].kind) {
result.threeOfKind = hand[0].kind;
result.twoPair = hand[3].kind;
result.fullHouse = 1;
}

if (hand[2].kind == hand[3].kind && hand[2].kind == hand[4].kind && hand[0].kind == hand[1].kind && hand[0].kind != hand[2].kind) {
result.threeOfKind = hand[2].kind;
result.twoPair = hand[0].kind;
result.fullHouse = 1;
}

return (result);
}

/* Evaluate four of a kind */
private HandStrength evaluateFourOfKind(Card[] hand) {
HandStrength result = new HandStrength();
result.fifthKicker = 0;
result.fourthKicker = 0;
result.thirdKicker = 0;
result.secondKicker = 0;
result.firstKicker = 0;
result.onePair = 0;
result.twoPair = 0;
result.threeOfKind = 0;
result.straight = 0;
result.flush = 0;
result.fullHouse = 0;
result.fourOfKind = 0;
result.straightFlush = 0;

if (hand[0].kind == hand[1].kind && hand[0].kind == hand[2].kind && hand[0].kind == hand[3].kind && hand[0].kind != hand[4].kind) {
result.onePair = hand[0].kind;
result.twoPair = hand[0].kind;
result.firstKicker = hand[4].kind;
result.fourOfKind = 1;
}

if (hand[1].kind == hand[2].kind && hand[1].kind == hand[3].kind && hand[1].kind == hand[4].kind && hand[1].kind != hand[0].kind) {
result.onePair = hand[1].kind;
result.twoPair = hand[1].kind;
result.firstKicker = hand[0].kind;
result.fourOfKind = 1;
}

return (result);

}

/* Evaluate straight flush */
private HandStrength evaluateStraightFlush(Card[] hand) {
HandStrength result = new HandStrength();
HandStrength straight;
HandStrength flush;

straight = evaluateStraight(hand);
flush = evaluateFlush(hand);
if (straight.straight == 1 && flush.flush == 1) {
result.flush = flush.flush;
result.straight = straight.straight;
result.straightFlush = 1;
}

return (result);
}

/* Evaluate kicker */
private HandStrength evaluateKickers(Card[] hand) {
HandStrength result = new HandStrength();
result.fifthKicker = 0;
result.fourthKicker = 0;
result.thirdKicker = 0;
result.secondKicker = 0;
result.firstKicker = 0;
result.onePair = 0;
result.twoPair = 0;
result.threeOfKind = 0;
result.straight = 0;
result.flush = 0;
result.fullHouse = 0;
result.fourOfKind = 0;
result.straightFlush = 0;

/*
* Check for hand without combination.
*/
result.firstKicker = hand[0].kind;
result.secondKicker = hand[1].kind;
result.thirdKicker = hand[2].kind;
result.fourthKicker = hand[3].kind;
result.fifthKicker = hand[4].kind;

return (result);
}

/* Evaluate hand */
public long evaluateHand(Card[] hand) {
long result = 0L;
HandStrength strength;

strength = evaluateOnePair(hand);
result |= strength.getValue();

strength = evaluateTwoPair(hand);
result |= strength.getValue();

strength = evaluateThreeOfKind(hand);
result |= strength.getValue();

strength = evaluateStraight(hand);
result |= strength.getValue();

strength = evaluateFlush(hand);
result |= strength.getValue();

strength = evaluateFullHouse(hand);
result |= strength.getValue();

strength = evaluateFourOfKind(hand);
result |= strength.getValue();

strength = evaluateStraightFlush(hand);
result |= strength.getValue();

if (result == 0L) {
strength = evaluateKickers(hand);
result |= strength.getValue();
}

return (result);
}

private void formFiveCardsHand(Card[] hand, int index, Player player, Board board) {

final int[][] combinations = { { 0, 0, 1, 1, 1, 1, 1 }, { 0, 1, 0, 1, 1, 1, 1 }, { 0, 1, 1, 0, 1, 1, 1 }, { 0, 1, 1, 1, 0, 1, 1 }, { 0, 1, 1, 1, 1, 0, 1 }, { 0, 1, 1, 1, 1, 1, 0 }, { 1, 0, 0, 1, 1, 1, 1 }, { 1, 0, 1, 0, 1, 1, 1 }, { 1, 0, 1, 1, 0, 1, 1 }, { 1, 0, 1, 1, 1, 0, 1 }, { 1, 0, 1, 1, 1, 1, 0 }, { 1, 1, 0, 0, 1, 1, 1 }, { 1, 1, 0, 1, 0, 1, 1 }, { 1, 1, 0, 1, 1, 0, 1 }, { 1, 1, 0, 1, 1, 1, 0 }, { 1, 1, 1, 0, 0, 1, 1 }, { 1, 1, 1, 0, 1, 0, 1 }, { 1, 1, 1, 0, 1, 1, 0 }, { 1, 1, 1, 1, 0, 0, 1 }, { 1, 1, 1, 1, 0, 1, 0 }, { 1, 1, 1, 1, 1, 0, 0 } };

Card[] allCards = new Card[Constants.NUMBER_OF_KNOWN_CARDS];

allCards[0] = player.hand[0];
allCards[1] = player.hand[1];
allCards[2] = board.flop[0];
allCards[3] = board.flop[1];
allCards[4] = board.flop[2];
allCards[5] = board.turn;
allCards[6] = board.river;

if (index < 0 || index >= Constants.NUMBER_OF_POSSIBLE_HANDS_FOR_EVALUATION) {
// TODO Exception handling!
return;
}

for (int i = 0, j = 0; i < Constants.NUMBER_OF_KNOWN_CARDS; i++) {
if (combinations[index][i] == 1) {
hand[j] = allCards[i];
j++;
}
}

}

int i;
int done = 0;
Card swap;

while (done == 0) {
done = 1;
for (i = 0; i < Constants.NUMBER_OF_EVALUATION_HAND_CARDS - 1; i++) {
if (hand[i].kind < hand[i + 1].kind) {
swap = hand[i];
hand[i] = hand[i + 1];
hand[i + 1] = swap;
done = 0;
}
}
}
}

int i;
int done = 0;
Card swap;

while (done == 0) {
done = 1;
for (i = 0; i < Constants.NUMBER_OF_EVALUATION_HAND_CARDS - 1; i++) {
if (((hand[i].kind == Constants.CARD_KIND_ACE) ? Constants.CARD_KIND_WEAK_ACE : hand[i].kind) < ((hand[i + 1].kind == Constants.CARD_KIND_ACE) ? Constants.CARD_KIND_WEAK_ACE : hand[i + 1].kind)) {
swap = hand[i];
hand[i] = hand[i + 1];
hand[i + 1] = swap;
done = 0;
}
}
}
}

public void calculatePlayersHandScore() {
/*
* Calculate hand score.
*/

for (int i = 0; i < game.numberOfPlayers; i++) {
Card[] hand = new Card[Constants.NUMBER_OF_EVALUATION_HAND_CARDS];

for (int j = 0; j < Constants.NUMBER_OF_POSSIBLE_HANDS_FOR_EVALUATION; j++) {
long score = 0L;

game.players[i].handScore = 0L;

formFiveCardsHand(hand, j, game.players[i], game.board);

score = evaluateHand(hand);
if (score > game.players[i].handScore) {
game.players[i].handScore = score;
}

score = evaluateHand(hand);
if (score > game.players[i].handScore) {
game.players[i].handScore = score;
}
}
}
}

private void updateWinsCounter() {
int howManyBest = 0;
int bestScoreIndex = 0;

/*
* Find index of the player with the best score.
*/
for (int i = 0; i < game.numberOfPlayers; i++) {
if (game.players[i].handScore > game.players[bestScoreIndex].handScore) {
bestScoreIndex = i;
}
}

/*
* Find how many players have the best score.
*/
for (int i = 0; i < game.numberOfPlayers; i++) {
if (game.players[i].handScore == game.players[bestScoreIndex].handScore) {
howManyBest++;
}
}

/*
* Update wins or ties counters.
*/
if (howManyBest == 1) {
game.players[bestScoreIndex].winsCounter++;
} else if (howManyBest > 1) {
for (int i = 0; i < game.numberOfPlayers; i++) {
if (game.players[i].handScore == game.players[bestScoreIndex].handScore) {
game.players[i].tiesCounter++;
}
}
}
}

synchronized public double willWinIn() {
return ((double) 100.0 * game.players[Constants.HUMAN_PLAYER_INDEX].winsCounter / (double) currentLoop);
}

private void fillKnownCards() {
int playerCardsDeckIndex = 2 * Constants.HUMAN_PLAYER_INDEX;
int tableCardsDeckIndex = 2 * game.numberOfPlayers;

for (int i = 0; i < knownCards.length(); i += 2) {
Card card = new Card();
card.known = true;

switch (knownCards.charAt(i)) {
case '2':
card.kind = Constants.CARD_KIND_TWO;
break;
case '3':
card.kind = Constants.CARD_KIND_THREE;
break;
case '4':
card.kind = Constants.CARD_KIND_FOUR;
break;
case '5':
card.kind = Constants.CARD_KIND_FIVE;
break;
case '6':
card.kind = Constants.CARD_KIND_SIX;
break;
case '7':
card.kind = Constants.CARD_KIND_SEVEN;
break;
case '8':
card.kind = Constants.CARD_KIND_EIGHT;
break;
case '9':
card.kind = Constants.CARD_KIND_NINE;
break;
case 'T':
card.kind = Constants.CARD_KIND_TEN;
break;
case 'J':
card.kind = Constants.CARD_KIND_JACK;
break;
case 'Q':
card.kind = Constants.CARD_KIND_QUEEN;
break;
case 'K':
card.kind = Constants.CARD_KIND_KING;
break;
case 'A':
card.kind = Constants.CARD_KIND_ACE;
break;
}

switch (knownCards.charAt(i + 1)) {
case 'C':
card.suit = Constants.CARD_SUIT_CLUBS;
break;
case 'D':
card.suit = Constants.CARD_SUIT_DIAMONDS;
break;
case 'H':
card.suit = Constants.CARD_SUIT_HEARTS;
break;
case 'S':
break;
}

int j;
for (j = 0; j < Constants.NUMBER_OF_CARDS; j++) {
if (game.deck.cards[j].suit == card.suit && game.deck.cards[j].kind == card.kind) {
break;
}
}

/*
* Put known cards on their places.
*/
if (i == 0) {
game.deck.cards[j] = game.deck.cards[playerCardsDeckIndex + 0];
game.deck.cards[playerCardsDeckIndex + 0] = card;
} else if (i == 2) {
game.deck.cards[j] = game.deck.cards[playerCardsDeckIndex + 1];
game.deck.cards[playerCardsDeckIndex + 1] = card;
} else if (i == 4) {
game.deck.cards[j] = game.deck.cards[tableCardsDeckIndex + 0];
game.deck.cards[tableCardsDeckIndex + 0] = card;
} else if (i == 6) {
game.deck.cards[j] = game.deck.cards[tableCardsDeckIndex + 1];
game.deck.cards[tableCardsDeckIndex + 1] = card;
} else if (i == 8) {
game.deck.cards[j] = game.deck.cards[tableCardsDeckIndex + 2];
game.deck.cards[tableCardsDeckIndex + 2] = card;
} else if (i == 10) {
game.deck.cards[j] = game.deck.cards[tableCardsDeckIndex + 3];
game.deck.cards[tableCardsDeckIndex + 3] = card;
} else if (i == 12) {
game.deck.cards[j] = game.deck.cards[tableCardsDeckIndex + 4];
game.deck.cards[tableCardsDeckIndex + 4] = card;
}
}
}

private void shuffle() {
int N = Constants.NUMBER_OF_CARDS;
for (int i = 0; i < N; i++) {
// choose index uniformly in [i, N-1]
int r = i + (int) (Math.random() * (N - i));
Card swap = game.deck.cards[r];
game.deck.cards[r] = game.deck.cards[i];
game.deck.cards[i] = swap;
}
}

private void deal() {

int j = 0;
for (int i = 0; i < game.numberOfPlayers; i++) {
game.players[i].hand[0] = game.deck.cards[j];
j++;
game.players[i].hand[1] = game.deck.cards[j];
j++;
}

game.board.flop[0] = game.deck.cards[j];
j++;
game.board.flop[1] = game.deck.cards[j];
j++;
game.board.flop[2] = game.deck.cards[j];
j++;
game.board.turn = game.deck.cards[j];
j++;
game.board.river = game.deck.cards[j];
j++;
}

public double start() {
final int SLEEP_FOR_MS = 10;

double result = 0.0;

running = true;

for (currentLoop = 1L; currentLoop <= numberOfLoops; currentLoop++) {

//allPlayersRegular();

// TODO Player type is not used yet.
// definePlayers(l % game.numberOfPlayers);

shuffle();
fillKnownCards();
deal();

calculatePlayersHandScore();

updateWinsCounter();

try {
} catch (InterruptedException exception) {
}

if (running == false) {
result = (double) 100.0 * (game.players[Constants.HUMAN_PLAYER_INDEX].winsCounter + game.players[Constants.HUMAN_PLAYER_INDEX].tiesCounter) / (double) currentLoop;

return (result);
}
}

result = (double) 100.0 * (game.players[Constants.HUMAN_PLAYER_INDEX].winsCounter + game.players[Constants.HUMAN_PLAYER_INDEX].tiesCounter) / (double) numberOfLoops;

return (result);
}

}

• Exactly, I'm simulating a bunch of hands and determine how often the human player wins. I would love to show how I call this class but I reached the maximum amount of chars for my post, so I will explain it to you. I first create an MonteCarlo object then call start() and then call willWinIn() - Edit: I see the comment was deleted, but maybe it's helpful for other users too. May 12, 2015 at 8:26
• Sybren, I figured it out after I saw that certain cards were known.
– JS1
May 12, 2015 at 9:05

## The shuffle

Right now you shuffle the full deck (with an incorrect version of Fisher Yates shuffle btw), and then you call fillKnownCards() which looks through the entire deck searching for particular cards to swap to the front. Instead of doing that, why not just call fillKnownCards() once to begin with, and then every time you shuffle, you only shuffle the rest of the cards? For example if there are 2 known cards, then shuffle only the last 50 cards each time.

One thing that needs to be changed if you did that is you would need to change your dealing order to deal to the player first, then to the table, then to the other players. This is because your known cards are only the player's cards and the table cards. But since the dealing order doesn't affect the simulation, it's fine to make this change.

## Lots of useless lines

        HandStrength result = new HandStrength();
result.fifthKicker = 0;
result.fourthKicker = 0;
result.thirdKicker = 0;
result.secondKicker = 0;
...


All of the result.field = 0 lines are useless because all the fields should already be set to 0 by the default constructor (although you haven't showed that code, but I'm assuming).

## fillKnownCards() card parsing

I don't know why there is all this card parsing code here. Don't you already have a Card constructor that takes a string argument? If not, you should move all this code to the Card class and create a new constructor for it. Make the constructor take either two characters or a single string.

## Ranking hands

Your hand ranking algorithm is slow. You sort the cards twice and rank the hands completely each time even though the Ace low sorting should only ever be needed to find a wheel straight.

I recently answered a poker ranking question so I'll just refer you to what I recommended in the other review. Essentially, you could encode each hand's score into a single long. The code to do that would be both faster and smaller than your current ranking code.

• I edited the shuffle method, can you take a look if it's correct? I will look your remark on fillKnownCards(). About the dealing: the player picks his own cards and he selects the cards on the board. He doesn't know anything about the cards of the other players. The result lines can be safely removed indeed. Card takes a rank which is an int and a suit also an `int'. I will look at the ranking hands part too. Although the code can be optimized, do you think the logic is okay, and I get the right results? May 12, 2015 at 11:05
• @Sybren The new shuffle looks good but actually you should not edit your code in the question after receiving answers. Please see what you may and may not do after receiving answers. I gave this a little more thought and actually you don't need to shuffle the whole deck. You only need to shuffle/randomize the first N*2 + 3 cards, where N is the number of players. I doubt that will make much of a difference in terms of the speed of your program though.
– JS1
May 12, 2015 at 18:07
• It would be better to add the new shuffle code as a seperate block but I reached the max amount of chars. May 12, 2015 at 18:28
• @Sybren I suggest that after you finish one complete pass at reworking your code, you can post a new question with the new code asking for a new code review. I'm sure the new code will be much shorter so you might be able to fit more into your question. Also if you have a GitHub account (or something similar), you can post a link to your full code in your question.
– JS1
May 12, 2015 at 18:36