# Lower, Higher, or Same Card Game

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)
break
$$$$


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

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)
`