0

I'm relatively knew to Python, but I decided to create a high low card game using classes. Ive got the classes all setup and everything, but the only issue I'm having is when I try to see if the card from the playerHand is bigger or smaller than the one from nextCard. playerHand and nextCard are both tied to classes, and the error that I am getting is: TypeError: '>' not supported between instances of 'Person' and 'NextCard'.

There 100% is a better way to do this, but this is what I've got so far:

import random

class Card(object):
    def __init__(self, suit, value):
        self.suit = suit
        self.value = value

    def show(self):
        print ("{} of {}".format(self.value, self.suit))

class Deck(object):
    def __init__(self):
        self.cards = []
        self.build()

    def build(self):
        for suit in ["Spades", "Clubs", "Diamonds", "Hearts"]:
            for value in ["Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"]:
                self.cards.append(Card(suit, value))

    def show(self):
        for card in self.cards:
            card.show()

    def shuffle(self):
        for n in range(len(self.cards)-1,0,-1):
            r = random.randint(0, n)
            self.cards[n], self.cards[r] = self.cards[r], self.cards[n]

    def drawCard(self):
        return self.cards.pop()

class Person(object):
    def __init__(self):
        self.hand = []

    def draw(self, deck):
        self.hand.append(deck.drawCard())
        return self

    def show(self):
        for card in self.hand:
            card.show()

class NextCard(object):
    def __init__(self):
        self.nextcard = []

    def draw(self, deck):
        self.nextcard.append(deck.drawCard())
        return self

    def show(self):
        for card1 in self.nextcard:
            card1.show()



deck = Deck()
deck.shuffle()

human = Person()
playerHand = human.draw(deck)

newcard = NextCard()
nextCard = newcard.draw(deck)



play = input("Do you want to play High/Low? Y or N? ")
while play.lower()== "y":
    card = playerHand
    print("The current card is: ", str(card.show()))
    guess = input("Guess H for high or L for low." )
    if guess.lower()=="h":
        if card > nextCard:
            print("Congratulations! You guessed correctly! The next card was ", card)
            play = input("Play again? Y or N? ")

        if card < nextCard:
            print("You lost! The next card was ", nextCard)
            play = input("Play again? Y or N? ")

    if guess.lower()=="l":
        if card > nextCard:
            print("You lost! The next card was ", nextCard)
            play = input("Play again? Y or N? ")

        if card < nextCard:
            print("Congratulations! You guessed correctly! The next card was ", nextCard)
else:
    print("The game is over.")

Any solutions or workarounds to the compare between classes problem would be much appreciated. This was coded in python 3.

relayyyyy
  • 25
  • 4
  • Do your classes have the value of the card? Then you could do `if card.value > nextcard.value` (or through a getter-function etc.) You can also make your classes comparable, like [this](https://stackoverflow.com/questions/1061283/lt-instead-of-cmp) – Jeppe Jun 03 '20 at 13:52
  • i got a deck class which has all of the card suits and values in it but also a separate card class which just combines the two variables from the deck class – relayyyyy Jun 03 '20 at 14:08
  • 1
    I think you need to share more information then. It is impossible to help you, if we can't reproduce your problem. Try creating a minimal reproducible code-snippet. E.g. your problem can be boiled down to `card < nextCard` throwing the exception you mention. – Jeppe Jun 03 '20 at 14:11
  • 3
    Your question is about using classes and there is not one class here... How can we help? Please provide a [mre]. At least show what are `playerHand` and `nextCard`. BTW, you should follow PEP-8's `names_with_under_scores` rather than the Java-like `CamelCase`. So it should be `player_hand` and `next_card` – Tomerikoo Jun 03 '20 at 14:16
  • From the error message `playerHand` must be an instance of class `Person`, so the statement `card = playerHand` makes no sense. It's impossible to help you further without seeimg the class definitions (and possibly more of the other logic in your program). – martineau Jun 03 '20 at 14:19
  • ok i pasted the whole file in the question above. feel free to rip it to shreds and tell me how i screwed up. the NextCard and Person class are the same but output different cards so I figured that it could be used as a 'next card' varaible for the program to compare it to the card in the playerHand. thanks – relayyyyy Jun 03 '20 at 19:06
  • `human.draw(deck)` returns `self` which is a `Person`, so `playerhand` is of type `Person`. You should ensure that `card` and `nextCard` are both of type `Card`. Then you can compare them with `card.value > nextCard.value`. I would consider not having a class for `NextCard` - can't you store the next card by calling `deck.drawCard()`? Or if you need a way to represent used cards, I would call it e.g. `Pile` and implement the logic of persisting cards there. – Jeppe Jun 04 '20 at 19:33

2 Answers2

0

Are these playerHand and nextCard classes ?

To compare two classes with < operator you need to do operator overloading.

But that is advance level python

In here the fault is maybe that you are not creating object of classes

you are only aliasing the class playerHand

to make a object of it do

card = playerHand()

But it won't fix the problem (probably)

please give me a inner look of the class (edit your question in brief)

omar
  • 190
  • 1
  • 10
0

Now consider how the big boys do it

add a < and > operator over-loader in your classes that you are trying to compare

for < add a __lt__() method in your class

for > add a __gt__() method in your class

those __lt__() and __gt__() will do the overloading of operator

** (overloading means programming operators for custom use) **

In your code you need to add them in class Card and class Person

class Card(object):
    def __init__(self, suit, value):
        self.suit = suit
        self.value = value

    def __gt__(self, comparing_card):
        # result is gonna be a boolean value
        # the ace jack qween king will need some comparing basis
        # work on it
        result = self.value > comparing_card.value
        return result

    def __lt__(self, comparing_card):
        result = self.value < comparing_card.value
        return result

    def show(self):
        print ("{} of {}".format(self.value, self.suit))

and another class

class Person(object):
    def __init__(self):
        self.hand = []

    def __gt__(self, comparing_obj):
        # result is gonna be a boolean value
        result = self.hand[-1] > comparing_obj.nextcard[-1]
        return result

     def __lt__(self, comparing_obj):
        # result is gonna be a boolean value
        result = self.hand[-1] < comparing_obj.nextcard[-1]
        return result

    def draw(self, deck):
        self.hand.append(deck.drawCard())
        return self

    def show(self):
        for card in self.hand:
            card.show()

And this is the last fragment where you compare your class

    # here we need oparator overloading
    # this initially means '> sign' will call card.__gt__(nextCard)
    # > sign will call card's ___gt__ method and pass nextCard as a parameter
    # ___gt__(nextCard) returns a boolean value that we feed to the if statement down there

    if card > nextCard:
        # in here the print shows the class node
        print("Congratulations! You guessed correctly! The next card was ", card)
        #  change card to card.show()
        play = input("Play again? Y or N? ")

well this is a very deep topic (if its hard to comprehend) and intermediate python stuff. you can try some online stuff to know about it briefly.

try this geeks for geeks tutorial:

https://www.geeksforgeeks.org/operator-overloading-in-python/

omar
  • 190
  • 1
  • 10