Question

I've been trying to make a poker game bot for IRC, but I can't seem to get my head around dealing the cards.

I know this algorithm is quite inefficient, but it's the best I could come up with using my current Python skills. Any improvements are welcome!

players is a dictionary where the key is a player's nickname, and the value is the amount of money they have.

When the code is run, if there is only 1 player, it gives 5 cards, as it should. But if there are 2 players, it generates anywhere from 4 to 6 cards each. I haven't tested with more players yet.

Some of the variables initialised beforehand:

numberOfPlayers = 0 #The numerical value of the amount of players in the game
players = {} #The nickname of each player and the amount of money they have
bets = {} #How much each player has bet
decks = 1 #The number of decks in play
suits = ["C","D","H","S"] #All the possible suits (Clubs, Diamonds, Hearts, Spades)
ranks = ["2","3","4","5","4","6","7","8","9","J","Q","K","A"] #All the possible ranks (Excluding jokers)
cardsGiven = {} #The cards that have been dealt from the deck, and the amount of times they have been given. If one deck is in play, the max is 1, if two decks are in play, the max is 2 and so on...
hands = {} #Each players cards

The code:

def deal(channel, msgnick):
    try:
        s.send("PRIVMSG " + channel + " :Dealing...\n")
        for k, v in players.iteritems():
               for c in range(0, 5):
                suit = random.randrange(1, 4)
                rank = random.randrange(0,12)
                suit = suits[suit]
                rank = ranks[rank]
                card = rank + suit
                print(card)
                if card in cardsGiven:
                    if cardsGiven[card] < decks:
                        if c == 5:
                            hands[k] = hands[k] + card
                            cardsGiven[card] += 1
                        else:
                            hands[k] = hands[k] + card + ", "
                            cardsGiven[card] += 1
                    else:
                        c -= 1
                else:
                    if c == 5:
                        hands[k] = hands[k] + card
                        cardsGiven[card] = 1
                    else:
                        hands[k] = hands[k] + card + ", "
                        cardsGiven[card] = 1
            s.send("NOTICE " + k + " :Your hand: " + hands[k] + "\n")
    except Exception:
        excHandler(s, channel)

If any examples or further explanations are needed, please ask :)

Was it helpful?

Solution 2

I would use itertools.product to get the possible value of cards into a list, then shuffle that and take of 5 cards at a time for each player you want.

from itertools import product
from random import shuffle

suits = ["C","D","H","S"] 
ranks = ["2","3","4","5","4","6","7","8","9","J","Q","K","A"]

cards = list(r + s for r, s in product(ranks, suits))
shuffle(cards)

print cards[:5], cards[5:10] # change this into a suitable for loop to slice
['4D', 'KC', '5H', '9H', '7D'] ['2D', '4S', '8D', '8S', '4C']

And you could use the following recipe from itertools to just get the next 5 cards depending on how many players.

def grouper(n, iterable, fillvalue=None):
    from itertools import izip_longest
    "Collect data into fixed-length chunks or blocks"
    # grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

hand = grouper(5, cards) 
for i in xrange(5): # deal for 5 players...
    print next(hand) # each time we call this, we get another 5 cards

('4D', 'KC', '5H', '9H', '7D')
('2D', '4S', '8D', '8S', '4C')
('AD', '2H', '4S', 'KS', '9S')
('6H', 'AH', '4H', '5S', 'KD')
('6S', 'QD', '3C', 'QC', '8H')

OTHER TIPS

for loops

for c in range(0, 5):

...

    c -= 1

Unfortunately, that's not how for loops work in Python - decrementing c won't result in another go-around of the loop. for loops iterate over a set of items that is fixed before the loop starts (e.g. range(0,5) is a fixed range of 5 items that isn't modified during the loop).

If you want to do what you're doing, you'd need to use a while loop (which works via a variable and condition that can be modified during the loop):

c = 0
while c < 5:
    c += 1

    ...

    c -= 1

range() numbering

if c == 5:

This case would currently not be hit, because range(N) generates a number sequence that goes from 0 to N-1 - e.g. range(5) generates 0,1,2,3,4.

A simple way to use slicing to accomplish this could be:

num_players = 5
num_cards_per_player = 5
remaining_cards = list(range(100)) # Imagine a list backing a Deck object
num_cards_to_deal = num_players * num_cards_per_player
cards_to_deal, remaining_cards = (remaining_cards[0:num_cards_to_deal],
        remaining_cards[num_cards_to_deal:])
cards_for_each_player = [cards_to_deal[player_num::num_players] for
        player_num in range(num_players)]
cards_for_each_player
[[0, 5, 10, 15, 20], [1, 6, 11, 16, 21], [2, 7, 12, 17, 22], [3, 8, 13, 18, 23], [4, 9, 14, 19, 24]]

For a specific type of deck you could implement a Deck object and use the above code slightly modified for use in a method. The deck object will need to handle the case of not enough remaining cards :), which is likely specific to the game you are playing.

#! /usr/bin/python3.2

import random

players = ['Alice', 'Bob', 'Mallroy']
suits = ["C","D","H","S"]
ranks = ["2","3","4","5","4","6","7","8","9","J","Q","K","A"]
decks = 2
cards = ['{}{}'.format (s, r)
         for s in suits
         for r in ranks
         for d in range (decks) ]

random.shuffle (cards)
for player in players:
    print ('{}\'s hand is {}'.format (player, cards [:5] ) )
    cards = cards [5:]

Just use the Python deuces library, it's built specifically for this kind of use:

from deuces import Card
from deuces import Deck

# create deck and shuffle it
deck = Deck()
deck.shuffle()

# play a texas hold 'em game with two players
board = deck.draw(5)
player1_hand = deck.draw(2)
player2_hand = deck.draw(2)

# now see which hand won
from deuces import Evaluator
evaluator = Evaluator()
p1handscore = evaluator.evaluate(board, player1_hand)
p2handscore = evaluator.evaluate(board, player2_hand)
from random import randint

# This code below creates a deck
cards = []
for suit in ["diamond","club","heart","spade"]:
    for card in ['A','2','3','4','5','6','7','8','9','10','J','Q','K']:
        cards.append(card+' '+suit)
# To deal the cards we will take random numbers
for i in range(5):
    a = randint(0,len(cards)-1)
    print cards(a)
    del cards[a] # We will delete the card which drew

first we create a deck then we take a random number with randint then we a draw a card with the random number

I have a program to draw a flop and hand

def create_card():
    cards = []
    for suit in   [r'$\diamondsuit$',r'$\clubsuit$',r'$\heartsuit$',r'$\spadesuit$']:
        for card in  ['A','2','3','4','5','6','7','8','9','10','J','Q','K']:
            cards.append(card+suit)
    return cards

def create_board_and_hand():
    cards = create_card()
    board = []
    for i in [0,1,2,3,4]:
    a  = randint(0,len(cards)-1)
    board.append(cards[a])
    del cards[a]
    hand = []
    for i in [0,1]:
        a  = randint(0,len(cards)-1)
        hand.append(cards[a])
        del cards[a]
    return board,hand

board,hand = create_board_and_hand()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top