Python Forum
I need help understanding a program structure using classes
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
I need help understanding a program structure using classes
#1
Hello, I've introduced classes in one of my project for the first time and now i can't seem to understand what goes where anymore... I'm trying to build a poker game and I've created a player class

class Player:

    hand = []
    playershand = []
    playersgrade = []

    dealer = False
    smallblind = False
    bigblind = False
    
    def __init__(self, number, chips):
        self.number = number
        self.chips = chips

    def bet(self):
        print("Bet")
    
    

    def besthands(self, pair, triple, quadruple, checksetinplayershand, checkstraightinplayershand, checkflushinplayershand):
        sets = checksetinplayershand(hand, flop, turn, river, a, pair, doublepair, triplepair, triple, doubletriple, quadruple)
        straights = checkstraightinplayershand( hand, flop, turn, river)
        flush = checkflushinplayershand(hand, flop, turn, river) 
      
        print(sets)
        print(straights)
        print(flush)
        print()



        if straightinplayershandandriver == True and flushinplayershandandriver == True:
            grade = 'Royal straight flush'
            grade.append(max(tgrade))
            return grade
        elif quadruple == True:
            max(sets)
            return listofquadruple
        
    #not finished...


    def raisestakes(self):
        pass
    def call(self):
        pass
    def check(self):
        pass
    def fold(self):
        pass
    def quit(self):
        pass
    def showstats(self):
        pass
    
class me(Player):
    pass
    
and here's my main program

import random
import time
import sys
from classes import *
from straightfunction import *
from pairfunction import *
from flushfunction import *

deck = [['1','H'], ['2','H'], ['3','H'], ['4','H'], ['5','H'],
        ['6','H'], ['7','H'], ['8','H'], ['9','H'], ['10','H'],
        ['11','H'], ['12','H'], ['13','H'],
        ['1','D'], ['2','D'], ['3','D'], ['4','D'], ['5','D'],
        ['6','D'], ['7','D'], ['8','D'], ['9','D'], ['10','D'],
        ['11','D'], ['12','D'], ['13','D'],
        ['1','C'], ['2','C'], ['3','C'], ['4','C'], ['5','C'],
        ['6','C'], ['7','C'], ['8','C'], ['9','C'], ['10','C'],
        ['11','C'], ['12','C'], ['13','C'],
        ['1','S'], ['2','S'], ['3','S'], ['4','S'], ['5','S'],
        ['6','S'], ['7','S'], ['8','S'], ['9','S'], ['10','S'],
        ['11','S'], ['12','S'], ['13','S']]


card = []
hand = []
flop = []
turn = []
river = []
cardsdrawn = []

playersgrade = []

def pickacard(deck):
    card = deck[0]
    deck.remove(deck[0])
    return card

def pickplayershand(deck):
    card = pickacard(deck)
    deck.remove(deck[0])
    hand.append(card)
    card = pickacard(deck)
    deck.remove(deck[0])
    hand.append(card)
    return hand

def pickflop(deck, flop):
    for i in range(3):
        flop.append(deck[0])
        cardsdrawn.append(deck[0])
        deck.remove(deck[0])
    return flop

def pickturn(deck, turn):
    turn.append(deck[0])
    cardsdrawn.append(deck[0])
    deck.remove(deck[0])
    return turn

def pickriver(deck,river):
    river.append(deck[0])
    cardsdrawn.append(deck[0])
    deck.remove(deck[0])
    return river


random.shuffle(deck)

print(pickplayershand(deck))
print(pickflop(deck,flop))
print(pickturn(deck,turn))
print(pickriver(deck, river))
playershand= hand+flop+turn+river
print(playershand)

player1 = Player(1, 250)

player1.besthands(pair, triple, quadruple, checksetinplayershand, checkstraightinplayershand, checkflushinplayershand)
And here's my error

Error:
Traceback (most recent call last): File "/usr/lib/python3.8/idlelib/run.py", line 559, in runcode exec(code, self.locals) File "/home/fook/Documents/pygame/Poker Practice/Poker.py", line 77, in <module> player1.besthands(pair, triple, quadruple, checksetinplayershand, checkstraightinplayershand, checkflushinplayershand) File "/home/fook/Documents/pygame/Poker Practice/classes.py", line 33, in besthands sets = checksetinplayershandandriver(hand, flop, turn, river, a, pair, doublepair, triplepair, triple, doubletriple, quadruple) NameError: name 'hand' is not defined
Now... I know the hand =[ ] in the player class is empty and i tried putting the pickacard function in the class, but then it created another set of problems that i think have the same root as this one: " I'm calling a function in my class that has a function inside, which i give in the arguments, that has variables outside my class...
This clearly shows that i don't know what I'm doing. I've been on the net to see what needs to be where, but I only find basic stuff with general explanation about basic stuff, like car class with drive functions so I think i need someone who can help me make sense of of functions inside functions.

Keep in mind this is my first program ever
Reply
#2
We can't run your code becausestraightfunction,pairfunctionandflushfunctionare missing but I can help you understand why the variablehandis throwing the error that you're getting.
Variables defined in a class before the__init__method are called "class variables". They are called that because they are shared by every instance of that class. In the code below I show you how to set a class variable but more importantly, why you shouldn't try to use them the way that you are. The reason for this is becausePlayer.handis the same for bothplayer_oneandplayer_two.
class Player :
	hand = []
	def __init__ (self, number, chips) :
		self.number = number
		self.chips = chips

player_one = Player (7, 11)
player_two = Player (7, 13)

Player.hand = [['1', 'H'],['2', 'D'],['3', 'C'],['4', 'S']]

print (f'Hand for player one is {one.hand}.')
print (f'Hand for player two is {two.hand}.')
Reply
#3
(Dec-24-2021, 02:02 AM)BashBedlam Wrote: We can't run your code becausestraightfunction,pairfunctionandflushfunctionare missing but I can help you understand why the variablehandis throwing the error that you're getting.
Variables defined in a class before the__init__method are called "class variables". They are called that because they are shared by every instance of that class. In the code below I show you how to set a class variable but more importantly, why you shouldn't try to use them the way that you are. The reason for this is becausePlayer.handis the same for bothplayer_oneandplayer_two.
class Player :
	hand = []
	def __init__ (self, number, chips) :
		self.number = number
		self.chips = chips

player_one = Player (7, 11)
player_two = Player (7, 13)

Player.hand = [['1', 'H'],['2', 'D'],['3', 'C'],['4', 'S']]

print (f'Hand for player one is {one.hand}.')
print (f'Hand for player two is {two.hand}.')

Thanks for answering back. I really appreciate it. So i put them in the constructor? But what about the flop? Do i put the flop, turn and river as class variables and change it at every turn, because I can't pass variable as a argument in a function called inside a function inside a class?
Reply
#4
I think you should make a Card class and a Hand class. The Card class knows how to do things like print its name and sort itself among a list of cards. The Hand class would know how to identify pairs and flushes. Mine is incomplete but should give some idea of how this could be done. The Player would be delt a hand, place bets and acquire or pay out chips.
import collections
import random

class Card():
    """A playing card that has a rank and suit"""
    # These are class variables.  They are associated with the class, not instances of the class
    suit_names = ["Clubs", "Diamonds", "Hearts", "Spades"]
    rank_names = ["", "", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"]
    short_rank_names = ["", "", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]
    rank_range = range(2, 15)

    def __init__(self, rank, suit):
        # These are instance variables.  Each instance has their own rank an suit
        self.rank = rank
        self.suit = suit

    def __lt__(self, other):
        """For sorting and comparing by rank"""
        return self.rank < other.rank  # self.rank is my rank.  other.rank is the rank of another card

    def __gt__(self, other):
        """For sorting and comparing by rank"""
        return self.rank > other.rank

    def __eq__(self, other):
        """For sorting and comparing by rank"""
        return self.rank == other.rank

    def name(self):
        """Get long name for card"""
        return f"{self.rank_names[self.rank]} {self.suit}"

    def __repr__(self):
        """Get short name for card"""
        return f"{self.short_rank_names[self.rank]}{self.suit[0]}"

class Hand():
    """A list of cards"""
    def __init__(self, cards=None):
        self.cards = [] if cards is None else cards

    def ranks(self):
        """Get list of card ranks and their count.  Use to identify pairs, 3 of a kind etc"""
        def sort_key(counter):
            """Sorting key function for (rank, count) tuples"""
            return (counter[1], counter[0])

        items = list(collections.Counter([card.rank for card in self.cards]).items())
        items.sort(key=sort_key, reverse=True)
        return items

    def suit(self, suit):
        """Get list of cards in specified suit"""
        ranks = [card.rank for card in self.cards if card.suit == suit]
        ranks.sort()
        return ranks

    def suits(self):
        """Get dictionary of cards grouped by suit.  Use to identify flushes"""
        return {suit:self.suit(suit) for suit in Card.suit_names}

    def __repr__(self):
        """Print cards in hand"""
        return ", ".join([str(card) for card in self.cards])


class Deck():
    """Deck of cards"""
    def __init__(self, shuffle=False):
        self.cards = [Card(rank, suit) for rank in Card.rank_range for suit in Card.suit_names]
        if shuffle:
            random.shuffle(self.cards)

    def __len__(self):
        """Return number of cards in deck"""
        return len(self.cards)

    def deal(self, count):
        """Deal count cards from top of deck"""
        cards = self.cards[:count]
        self.cards = self.cards[count:]
        return cards

deck = Deck(True)
hands = [Hand(deck.deal(5)) for _ in range(2)]
for hand in hands:
    print("Hand", hand)
    print("Ranks", hand.ranks())
    print("Suits", hand.suits())
Output:
Hand 4C, 2D, 10D, 2S, 7D Ranks [(2, 2), (10, 1), (7, 1), (4, 1)] Suits {'Clubs': [4], 'Diamonds': [2, 7, 10], 'Hearts': [], 'Spades': [2]} Hand QS, 8H, 5D, 6C, AS Ranks [(14, 1), (12, 1), (8, 1), (6, 1), (5, 1)] Suits {'Clubs': [6], 'Diamonds': [5], 'Hearts': [8], 'Spades': [12, 14]}
BashBedlam likes this post
Reply
#5
Yeah, but how can a class be a variable for another class? i think it would be too steep a step for me in my learning curve. I mean i can't even make this one class work...
Reply
#6
(Dec-24-2021, 05:05 AM)CompleteNewb Wrote: I can't pass variable as a argument in a function called inside a function inside a class?
Why not?
class Function_Test :
	def __init__ (self):
		pass

	def show (self, text) :
		print (text)

	def say_this (self, text) :
		self.show (text)

tester = Function_Test ()
tester.say_this ('This text was sent to a function from a function inside a class instance.')
Reply
#7
(Dec-24-2021, 08:09 PM)BashBedlam Wrote:
(Dec-24-2021, 05:05 AM)CompleteNewb Wrote: I can't pass variable as a argument in a function called inside a function inside a class?
Why not?
class Function_Test :
	def __init__ (self):
		pass

	def show (self, text) :
		print (text)

	def say_this (self, text) :
		self.show (text)

tester = Function_Test ()
tester.say_this ('This text was sent to a function from a function inside a class instance.')

Yeah, but what i can't do this

class Function_Test :
	def __init__ (self):
		pass
        
	def say_this (self, text) :
		self.show (text)
   	
def show (text):
    print (text)
    
tester = Function_Test ()
tester.say_this ('This text was sent to a function from a function inside a class instance.')
So if i want to check the highest hand one of my class player has, i need to put the function to check if a hand has a pair(because I need to check if it has a pair, a straight or a flush) inside my player class, right?

class Player:
Reply
#8
(Dec-24-2021, 08:09 PM)BashBedlam Wrote:
(Dec-24-2021, 05:05 AM)CompleteNewb Wrote: I can't pass variable as a argument in a function called inside a function inside a class?
Why not?
class Function_Test :
	def __init__ (self):
		pass

	def show (self, text) :
		print (text)

	def say_this (self, text) :
		self.show (text)

tester = Function_Test ()
tester.say_this ('This text was sent to a function from a function inside a class instance.')

Yeah, but i can't do this

class Function_Test :
	def __init__ (self):
		pass
        
	def say_this (self, text) :
		self.show (text)
   	
def show (text):
    print (text)
    
tester = Function_Test ()
tester.say_this ('This text was sent to a function from a function inside a class instance.')
So if i want to check the highest hand one of my class player has, i need to put the function to check if a hand has a pair inside my player class, right? (because i need to check if there's a pair, a straight and a flush)

I can't do something like this:

class Player:
    def __init__(self, hand):
        self.hand = hand
    def checkhand(self, checkforpair, checkforstraight, checkforflush):
        pair = checkforpair(hand, flop)
        print(pair)

flop = [ 'a', 'b', 'c']

def checkforpair(hand, flop):
    ....
Reply
#9
I guess I was thinking of something more like this:
class Player :
	def __init__ (self, hand)
		self.hand = hand

	def checkforpair (self) :
		# look for pair in self.hand
		return False

	def checkforstraight (self):
		# look for straight in self.hand
		return False

	def checkforflush (self) :
		# return True if flush was found in self.hand
		return False

	def checkhand (self) :
		if self.checkforpair () :
			return 'pair'
		elif self.checkforstraight () :
			return 'straight'
		elif self.checkforflush () :
			return 'flush'
Reply
#10
(Dec-25-2021, 02:33 AM)BashBedlam Wrote: I guess I was thinking of something more like this:
class Player :
	def __init__ (self, hand)
		self.hand = hand

	def checkforpair (self) :
		# look for pair in self.hand
		return False

	def checkforstraight (self):
		# look for straight in self.hand
		return False

	def checkforflush (self) :
		# return True if flush was found in self.hand
		return False

	def checkhand (self) :
		if self.checkforpair () :
			return 'pair'
		elif self.checkforstraight () :
			return 'straight'
		elif self.checkforflush () :
			return 'flush'

So for it to work, everything needs to be inside the player class? Problem is I have a lot of functions? Is there a way to put them in a module and call it in my class file? Like ...

import checkhandfunctions



class Player :
	flop = [ ] 

    def __init__ (self, hand)
		self.hand = hand
and in my module...

    def checkforpair (self) :
		# look for pair in self.hand
		return False

	def checkforstraight (self):
		# look for straight in self.hand
		return False

	def checkforflush (self) :
		# return True if flush was found in self.hand
		return False

	def checkhand (self) :
		if self.checkforpair () :
			return 'pair'
		elif self.checkforstraight () :
			return 'straight'
		elif self.checkforflush () :
			return 'flush'
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Understanding Python classes PythonNewbee 3 1,195 Nov-10-2022, 11:07 PM
Last Post: deanhystad
  Understanding Python super() for classes OmegaRed94 1 1,843 Jun-09-2021, 09:02 AM
Last Post: buran
  Understanding program blocks newbieAuggie2019 2 1,985 Oct-02-2019, 06:22 PM
Last Post: newbieAuggie2019
  help with understanding a program prompt drasil 5 2,976 Feb-14-2019, 05:54 PM
Last Post: ichabod801
  Help, not understanding how classes work... Peter_EU 1 2,335 Jan-20-2018, 06:07 PM
Last Post: wavic
  Using classes? Can I just use classes to structure code? muteboy 5 5,080 Nov-01-2017, 04:20 PM
Last Post: metulburr
  I need help understanding how to use and run this program! Thanks in advance! tc1chosen 6 4,818 Sep-01-2017, 01:56 PM
Last Post: tc1chosen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020