7
\$\begingroup\$

This is my second script in my first language so I'm trying to get oriented and better foundations. I noticed in the while loop I got really messy but I couldn't google my way to a better solution that I could understand. With that, I'd appreciate any feedback that makes my code more "pythonic" or clean.

import random

def card_deck():
    card_faces = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King', 'Ace']
    card_suits = ['♠', '♦', '♥', '♣']
    deck = []
    for i in card_suits:
        for j in card_faces:
            deck.append(j + ' ' +  i)
    return deck

def card_draw(deck):
    random.shuffle(deck)
    deck = deck.pop()
    return deck

def card_value(card):
    card = str(card)
    if card[0] == 'J':
        return 10
    elif card[0] == 'Q':
        return 12
    elif card[0] == 'K':
        return 13
    elif card[0] == 'A':
        return 14
    else:
        card = int(card[0:2])
        return card

correct_guesses = 0
deck = card_deck()
card = card_draw(deck)


while True:
    card_points = card_value(card)
    if not deck:
        print("You've done it! You've won with", correct_guesses, "correct guesses!")
        break
    next_card = card_draw(deck)
    next_card_points = card_value(next_card)
    print("\nYou're card is: ", card)
    user_guess = input('\n(H)igher, (L)ower, or (S)ame?:\t')
    user_guess = user_guess.lower()
    if user_guess not in ('h', 'l', 's'):
        break
    if card_points < next_card_points and user_guess == 'h':
        print("Correct!")
        correct_guesses += 1
        card = next_card
        continue
    elif card_points > next_card_points and user_guess == 'l':
        print("Correct!")
        correct_guesses += 1
        card = next_card
        continue
    elif card_points == next_card_points and user_guess == 's':
        print("Correct!")
        correct_guesses += 1
        card = next_card
        continue
    else:
        print('You lose the next card was ', next_card)
        print('You had', correct_guesses, 'correct guesses.')
        break
```
\$\endgroup\$
3
\$\begingroup\$

I may have went overboard on the Python-ification, but this is a refactoring of the current solution.

What I did was create a Card class which contained the suit and value of the card. To get the value, I added all items to an array and then got the index of the card's value from the array's offset, which allowed card_value to be removed.

There was lots of duplication when displaying that the user got the correct answer. I made this a function and was able to minimize the method's body by using an iterator which contained the current card and the previous card (thus avoiding having to set the previous card to the current card and then get the next card.)

Here is a rewritten version: (comments to follow)

import random
import itertools

card_faces = [
    '2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King',
    'Ace'
]


class Card:
    """
  Defines a Card with a suit and face, and allows retrieving the points of the card
  """

    def __init__(self, face_suit):
        self.face = face_suit[0]
        self.suit = face_suit[1]

    def getPoints(self):
        return card_faces.index(self.face) + 2

    def __str__(self):
        return self.face + ' ' + self.suit

    def __gt__(self, other):
        return self.getPoints() > other.getPoints()

    def __lt__(self, other):
        return self.getPoints() < other.getPoints()

    def __eq__(self, other):
        return self.getPoints() == other.getPoints()


def generate_card_deck():
    """
    Creates a shuffled list of cards as [(c0, c1), (c1, c2), ...]
    """
    card_suits = ['♠', '♦', '♥', '♣']
    deck = list(map(Card, itertools.product(card_faces, card_suits)))
    random.shuffle(deck)
    return deck


def user_guessed_correctly():
    """
  Congratulates the user if they have a correct guess, and increments
  the counter
  """
    print("Correct!")
    global correct_guesses
    correct_guesses += 1


def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = itertools.tee(iterable)
    next(b, None)
    return zip(a, b)


correct_guesses = 0
deck = pairwise(generate_card_deck())

while True:
    card, next_card = next(deck, (None, None))
    if not card:
        print("You've done it! You've won with", correct_guesses,
              "correct guesses!")
        break

    print("Your card is: ", card)
    user_guess = input('(H)igher, (L)ower, or (S)ame?:\t').lower()
    if user_guess not in ('h', 'l', 's'):
        break

    if (card < next_card and user_guess == 'h') or (
            card > next_card and user_guess == 'l') or (card == next_card
                                                        and user_guess == 's'):
        user_guessed_correctly()
    else:
        print('You lose: the next card was ', next_card)
        print('You had', correct_guesses, 'correct guesses.')
        break

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Really well done. Thank you for the feedback, I'm going to refer back to your example as I press on. Thank you! \$\endgroup\$ – Dk Kd Dec 1 '19 at 16:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.