-1

I copied a card game code online to Python and I'm trying to recreate the popular card game of War.

import random

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

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

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

  def build(self):
    for s in ["Spades", "Clubs", "Diamonds", "Hearts"]:
      for v in {'2' : 0, '3' : 1, '4' : 2, '5' : 3, '6' : 4, '7' : 5, '8' : 6, '9' : 7 , '10' : 8, 'Jack' : 9, 'Queen' : 10, 'King' : 11, 'Ace' : 12}:
        self.cards.append(Card(s,v))

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

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

class Player:
  def __init__(self, name):
    self.name = name
    self.hand = []

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

  def showHand(self):
    for card in self.hand:
      print(self.name, "drew a ", card.show() , "!")

deck = Deck()
deck.shuffle()
peter = Player('Peter')
peter.draw(deck)
jessica = Player('Jessica')
jessica.draw(deck)
peter.showHand()
jessica.showHand()

In the Player.show_hand() method I want to print (name object) draws a (value of suit). However, instead, it prints the suit of value first, and then it says Player draws a None !. It kind of goes like this:

9 of Clubs
Peter drew a None!

It's mostly a simple error, but I want it so that the suit of value gets printed alongside the player, like this:

Peter drew a 9 of Clubs!

This is the method that results in a runtime error:

def showHand(self):
    for card in self.hand:
      print(self.name, "drew a ", card.show() , "!")
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • 4
    The `show()` method needs to return the string, not print it. – Barmar Dec 01 '20 at 02:35
  • Does this answer your question? [How is returning the output of a function different from printing it?](https://stackoverflow.com/questions/750136/how-is-returning-the-output-of-a-function-different-from-printing-it) – Pranav Hosangadi Dec 01 '20 at 02:47
  • I know I am touting my own answer here, but the `__str__()` dunder is the most Pythonic solution to this :) – Tim Dec 01 '20 at 02:49

1 Answers1

0

Your function Card.show(), prints and returns None.

I would implement a string dunder for the Card class as shown here. Then I would simply format print the Card class down below in the Player.showHand() function which will call the Card.__str__() dunder automatically.

import random

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

  # this decides what string to return when using this class as a string.
  def __str__(self):
      return "{} of {}".format(self.value, self.suit)

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

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

  def build(self):
    for s in ["Spades", "Clubs", "Diamonds", "Hearts"]:
      for v in {'2' : 0, '3' : 1, '4' : 2, '5' : 3, '6' : 4, '7' : 5, '8' : 6, '9' : 7 , '10' : 8, 'Jack' : 9, 'Queen' : 10, 'King' : 11, 'Ace' : 12}:
        self.cards.append(Card(s,v))

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

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

class Player:
  def __init__(self, name):
    self.name = name
    self.hand = []

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

  def showHand(self):
    for card in self.hand:
      # This line was changed:
      print(f"{self.name} drew a {card}!")

deck = Deck()
deck.shuffle()
peter = Player('Peter')
peter.draw(deck)
jessica = Player('Jessica')
jessica.draw(deck)
peter.showHand()
jessica.showHand()

Execution:

[ttucker@zim stackoverflow]$ python war.py 
Peter drew a 10 of Clubs!
Jessica drew a 10 of Hearts
Tim
  • 2,139
  • 13
  • 18