1

I'm new to programming and I'm joining here to ask questions, contribute (when I have more knowledge under my belt), and basically just learn and figure out if programming is right for me.

I am currently learning Python through a course on Udemy and I'm working on a milestone project to create a Blackjack game. The only rule is for me to use Object Oriented Programming and to create classes for things like the Card and Deck.

I've watched some tutorials on OOP, but I still do not feel confident in implementing them, so I was hoping I could share what I've written and hopefully have a better understanding through interactions here.

To start, I created a plan to break the project down into smaller tasks as it was overwhelming to me. Here's what I planned:

  1. Create a deck with 52 cards

  2. Assign numerical values to each card (Ace can be 1 or 11)

  3. Shuffle the deck

  4. Dealer and player are handed 2 cards each as a start

  5. Player is asked if he/she wants to hit or stand

  6. Dealer has to hit until he reaches 17

  7. Compare "points" to see who has more

  8. At any point, if anyone exceeds 21, that person loses

I am currently stuck at trying to figure out the first part. I'm basically trying to create a list with all 52 cards in it using OOP and for loops, but I can't seem to get things right.

I'm sharing my code below which was written in Python 2. Any ideas how to proceed?

Thank you, Paul

Edit #1: Thank you everyone for the comments and feedback. I think I am getting a little closer now. Can someone please let me know if I am doing this right and how I can print the list I used to create my deck such that I am able to see each of the 52 cards in a list? I tried using the str method but it appears I'm doing it wrongly.

import random

rank = [2,3,4,5,6,7,8,9,10,'Jack','Queen','King','Ace']
suit = ['Diamonds','Clubs','Hearts','Spade']

class Card(object):

    def __init__(self,rank,suit):
        self.rank = rank
        self.suit = suit

    def __str__(self):
        return self.suit + self.rank

    def grab_suit(self):
        return self.suit

    def grab_rank(self):
        return self.rank

    def draw(self):
        print (self.suit + self.rank)

class Deck(object):
    def __init__(self):
        self.cards = []    
        for i in rank:
            for j in suit:
                self.cards.append(Card(i,j))

    def __str__(self):
        return self.cards()
paulnsn
  • 107
  • 2
  • 11
  • 2
    does python have pointers? – Snow Aug 10 '17 at 20:01
  • 4
    I think he meant pointers as in suggestions... – bergerg Aug 10 '17 at 20:02
  • 1
    No need to explicitly derive Card from object, change to `class Card()`. _new_ a card by calling Card like a function with parameter (other than self) so change `self.deck.append(Card)` to `self.deck.append(Card(i,j))` – Doug Coburn Aug 10 '17 at 20:04
  • 1
    `self.deck = self` don't do that... anyway it's pointless since you immediately do `self.deck = []`. – juanpa.arrivillaga Aug 10 '17 at 20:07
  • As a tip: This site operates much better in a Q&A style. it is fine if you would like assistance making this game, but it would be better formatted in separate questions. Most of these smaller questions I think you will find on here already. It's a lot easier for us to answer things rather than provide advice, and you will often be met with some negativity if you post broad questions such as this. Just a heads up :) – Easton Bornemeier Aug 10 '17 at 20:08
  • If the goal here is to learn the OOP way of thinking then I think this is the wrong assignment for this (or the wrong PL if you insist on the assignment). I also recommend you watch [this](https://www.youtube.com/watch?v=o9pEzgHorH0). – bergerg Aug 10 '17 at 20:08
  • @DougCoburn explicitely deriving form object is good form - at the very least it makes your code portable between Python 2 and Python 3. `class Card()` is perhps the *least* appealing option, which is uglier than the aesthetically pleasing `class Card:` but with none of the portability benefits of `class Card(object)` – juanpa.arrivillaga Aug 10 '17 at 20:08
  • Okay, here's a pointer: `0x88b33a0`. As for suggestions: append an instance of the `Card` class: `self.deck.append(create instance here)`. – ForceBru Aug 10 '17 at 20:09
  • 1
    @juanpa.arrivillaga Thanks for the correction. :) – Doug Coburn Aug 10 '17 at 20:11
  • @EastonBornemeir, thanks for the heads up! I plan to edit the question and I'll keep in mind to ask specific questions instead! – paulnsn Aug 10 '17 at 23:53
  • @juanpa.arrivillaga, thanks for the numerous comments. I never really understood why I had to pass an object when defining a class, but now I have a brief idea! – paulnsn Aug 10 '17 at 23:54

1 Answers1

0

Usually around here people like you to have a specific question that you're asking, rather than, "give me some pointers", so be prepared for complaints that this question is too broad. That said, I'll give you a couple pointers.

You've got suit and rank arrays defined outside of any class (also you've got their names flipped, but whatever). That's not OOP. I would put those inside the Deck class, since that's where they're used. Think of it this way: each Card doesn't need to know all the possible ranks and suits, it just needs to know its own rank and suit when it's created by the deck it belongs to.

I'm not sure what's going on with self.deck = self. What are you trying to do there? In the next line you've got self.deck = [], and you're going to fill it with Card objects. That sounds ok, however, it's not a good idea to name a local variable the same as the name of the class it belongs to. That's going to get confusing. I would suggest calling it cards, because it's going to be an array full of cards that belong to the deck. Your loops look ok, but right here: self.deck.append(Card) you're not creating the Card correctly. The card needs to know what rank and suit you want to assign to that particular card. I'll let you look into how to do that yourself. Good luck :)

Steve Archer
  • 641
  • 4
  • 10
  • 2
    Eh, I don't really agree that using module-level constants to contain `suits` and `ranks` is "not OOP". Normally, anyway, you would use `enums` to represent "suit" and "rank" as they are sort of a [canoncial example of enums](https://stackoverflow.com/a/42399384/5014455). That isn't really necessary for this assignment, where global lists holding `suit` and `rank` info seems fine. Also, this is a nitpick, but these are **not arrays** but *lists*. – juanpa.arrivillaga Aug 10 '17 at 20:20
  • To me, it's not a good idea because it binds the Card and Deck classes together. Say you wanted to add a Tarot Card Deck, and reuse your Card object. Good call on array vs list, I've been writing more JS than Python lately! – Steve Archer Aug 10 '17 at 20:33
  • But that doesn't change if `suit` and `rank` are in the module-level namespace or in the `Deck` namespace. – juanpa.arrivillaga Aug 10 '17 at 20:36
  • so if you did add a Tarot Card Deck, where would you recommend putting `suit=[swords, wands, coins, cups]`? – Steve Archer Aug 10 '17 at 20:41
  • Again, module-level: `tarot_suits = ['swords', ...]` But you could *also* have a reference to that inside the `Deck` class. My main point is that module-level constants are ok, as long as they are actually being used as constants. And I would probably just use `enums` in this case anyway, like I show in that linke where I implement a `Card` and `Deck` class. I would just have a `TarotSuit` enum as well. – juanpa.arrivillaga Aug 10 '17 at 21:28
  • I guess I just don't like the idea of the standard `Deck` having access to the `TarotDeck` values and vice versa. It also means having to keep straight which deck type is using which list, etc, which is less maintainable. If you can encapsulate data, even constants, shouldn't you? – Steve Archer Aug 10 '17 at 21:58
  • @SteveArcher, thank you for the feedback. You're right, I mixed up suit and rank! Can you please take a look at my updated code and let me know how I can next print the deck as a list, showing each of the 52 cards in it? Thank you – paulnsn Aug 10 '17 at 23:52