I'm trying to write a blackjack game for an online class I'm taking. I know that I'll have to introduce objects at some point, but right now I'm just trying to write the very basic code for operations within the object. I also have only chemistry as my background, absolutely zero computer science background.
What I'm trying to do is to pull the value text value from the first entry in the tuple, then assign it a numerical value so I can start to compare scores, once I get to the point of creating players. However, I get this error, and I don't fully know what it means...the code is also below. Still a noob here, just trying to learn!
27 def value_of_card():
--->28 x = deal[0]
29
30 print value_of_card()
TypeError: 'function' object has no attribute 'getitem'
import random
suits = ['spades', 'hearts', 'clubs', 'diamonds']
ranks = ['ace', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'Jack', 'Queen', 'King']
def deal():
deck = []
for suit in suits:
for rank in ranks:
deck.append((rank, suit))
random.shuffle(deck)
print deck
deal = deck[0]
print deal
for card in deck:
if deal in deck:
deck.remove(deal)
return deck
print deck
print deal[0]
print deal()
def value_of_card(deal):
return deal[0]
print value_of_card(deal)
Some issues:
You pass the function reference to value_of_card, instead of passing the value returned by that function.
Your deal function does not return a card, but the deck of remaining cards. You should not return deck, but return deal
The search (with for loop) for the card that you selected is not necessary: you took it from index 0, so just remove the card at index 0 (with pop(0))
Here is the corrected script:
import random
suits = ['spades', 'hearts', 'clubs', 'diamonds']
ranks = ['ace', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'Jack', 'Queen', 'King']
def deal():
deck = []
for suit in suits:
for rank in ranks:
deck.append((rank, suit))
random.shuffle(deck)
# you don't need to search for the card. It is at index 0
# grab, remove and return the card (not the deck) in one go:
return deck.pop(0)
card = deal() # remember the dealt card
print card
def value_of_card(deal):
return deal[0]
print value_of_card(card) # pass the remembered card
And here is how it could look if you made it more OOP:
import random
class Card:
def __init__(self, rank, suit):
self.rank = rank
self.suit = suit
def __repr__(self):
return self.rank + ' of ' + self.suit
class Deck:
def __init__(self):
suits = ['spades', 'hearts', 'clubs', 'diamonds']
ranks = ['ace', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'Jack', 'Queen', 'King']
self.__deck = [Card(rank, suit) for suit in suits for rank in ranks]
def shuffle(self):
random.shuffle(self.__deck)
def deal(self):
return self.__deck.pop()
# Create a deck of 52 cards
deck = Deck()
# Shuffle the deck
deck.shuffle()
# Pull a card from the deck
card = deck.deal()
# Show the card
print(card) # this calls the __repr__ method
# ..or only the rank:
print(card.rank)
You forgot to call your deal function in value_of_card function.
You should also change your functions names to be distinct, because now you have too many objects called deal which is really misleading and makes your code hard to read.
Related
I Have this code Written with Python. The logic of the Code is to shuffle a deck of Cards, deal one single hand to the player and after Evaluate the Highest rank of the Player's hand and return an appropriate message to the player like. (Ex: Your Hand : 5K 8H 2S 3D 9S
Your Rank : Flush)
I want to use Django framework to create an API that will return an HttpResponse to mimic this (Ex: Your Hand : 5K 8H 2S 3D 9S
Your Rank : Flush) as a Json Object.
I would like to know how would about writing API and which design consideration i should have in mind.
Which part of the code should go into the view to return the appropriate endpoint exemple : the hand of the player the shuffling of the deck, and the rank of the user.
from constants import Constant
class Card(Constant):
def __init__(self, suit, val):
# initialize the card object
self.suit = suit
self.value = val
# get the rank of the card by indexing the RANKS dictionary
self.rank = self.RANKS[val]
def get_rank(self):
# return the rank of the card
if self.rank:
return self.rank
else:
raise Exception('No rank')
def get_suit(self):
# return the suit of the card
if self.suit:
return self.suit
else:
raise Exception('No suit')
def __str__(self):
# return the string representation of the card
return f'{self.get_rank()}{self.get_suit()}'
import random
from card import Card
# class to represent a deck of cards
class Deck(Card):
def __init__(self):
# initialize the deck object
self.cards = []
self.build_deck()
# Create Our Deck of 52 cards
def build_deck(self):
# loop through each suit
for suit in self.SUITS:
for rank in self.RANKS:
self.get_deck().append(Card(suit, rank))
random.shuffle(self.get_deck())
# return the deck of cards
def get_deck(self):
return self.cards
# print the deck object as a string
def __str__(self):
return " ".join([str(card) for card in self.get_deck()])
# Shuffle the deck of cards
def shuffle(self):
for i in range(len(self.get_deck()) - 1, 0, -1):
# pick a random index between 0 and i (inclusive)
if i > 0:
j = random.randint(0, i)
# swap the cards at position i and j
self.get_deck()[i], self.get_deck()[
j] = self.get_deck()[j], self.get_deck()[i]
else:
# return an empty string if the deck is empty
raise Exception('No cards to shuffle')
return True
# draw a single card from the deck (the bottom card)
def deal(self):
if self.get_deck():
# return the last card in the deck
return self.get_deck().pop()
else:
# return an empty string if the deck is empty
raise Exception('No cards to deal')
from deck import Deck
# class to represent a hand of cards
class Hand(Deck):
def __init__(self):
# initialize the hand object
self.hand = []
def get_hand(self):
# return the hand
return self.hand
def __str__(self):
if self.get_hand():
# return the string representation of the hand
return ' '.join([str(card) for card in self.get_hand()])
else:
# raise an exception if the hand is empty
raise Exception('No cards in hand')
# Make the Hand Iterable
def __iter__(self):
if not self.get_hand():
# raise an exception if the hand is empty
raise StopIteration
else:
# return an iterator for the hand
return iter(self.get_hand())
def draw_cards(self, deck, num):
# draw cards from the deck and add them to the hand
for _ in range(num):
# draw a card from the deck
cards_in_deck = deck.deal()
if cards_in_deck:
# add the card to the hand
self.get_hand().append(cards_in_deck)
else:
# raise an exception if the
raise Exception('No cards to draw')
# return the string representation of the hand
return True
class HandRank:
#staticmethod
def is_cards_in_sequence(ranks):
sorted_ranks = sorted(ranks)
for i in range(len(sorted_ranks) - 1):
# check if the next card is one rank higher than the current card
if i == 0:
# check if the first card is an ace
if sorted_ranks[i] == 'A' and sorted_ranks[i + 1] == '10':
continue
if sorted_ranks[i] != (sorted_ranks[i + 1] - 1):
return False
return True
# function to return a count of each rank in the hand
#staticmethod
def get_counts(ranks):
ranks = []
for c in ranks:
if c in ranks:
# increment the count of the rank
ranks[c] += 1
else:
# add the rank to the dictionary
ranks[c] = 1
return ranks
# get the rank of the hand
def get_hand_rank(self, hand):
suits = [card.suit for card in hand] # get the suits of the cards
ranks = [card.rank for card in hand] # get the ranks of the cards
# check for Straight flush
if self.is_cards_in_sequence(ranks) and len(set(suits)) == 1:
return Constant.STRAIGHT_FLUSH
# check for four of a kind
elif self.get_counts(ranks) == 4:
return Constant.FOUR_OF_A_KIND
# check for full house
elif self.get_counts(ranks) == 3 and self.get_counts(ranks) == 2:
return Constant.FULL_HOUSE
# check for flush
elif len(set(suits)) == 1:
return Constant.FLUSH
# check for straight
elif self.is_cards_in_sequence(ranks):
return Constant.STRAIGHT
# check for three of a kind
elif self.get_counts(ranks) == 3:
return Constant.THREE_OF_A_KIND
# check for two pair
elif len(set(self.get_counts(ranks))) == 3:
return Constant.TWO_PAIR
# check for one pair
elif len(set(self.get_counts(ranks))) == 4:
return Constant.ONE_PAIR
#
else:
return Constant.HIGH_CARD
Exemple of the output:
Your Hand : 5K 8H 2S 3D 9S
Your Rank : Flush
How can i sort "cardsListObj" with suit and then rank?
I've done something like "print (cardsListObj.sort (key = card.getRank))" and it didn't work, i have "None".
Actually i did this on another code that is quite the same as this (in my opinion as a newbie) and that worked. (that code is about 300 lines that's why i didn't post it, here)
class card :
def __init__ (self, rank, suit) :
self.rank = rank # cards numbers
self.suit = suit # cards characters Diamonds, Clubs, Hearts, Spades
def getRank (self):
return self.rank
def getSuit (self):
return self.suit
def main():
cards = open (input ("file? "))
cardsListObj = []
for i in cards:
cardObj = card (i.split () [0], i.split () [1])
cardsListObj.append (cardObj)
Input file is a txt file with a number and a name of cards in each line separated by space.
Thanks in advance
if you want to sort your cards, you can create a function like this:
from operator import attrgetter
def sort_cards(cards): #cards is an list containing 'Cards' objects
"""Function sorting cards"""
return sorted(cards, key=attrgetter('suit', 'rank'))
deck = [
Cards(3, 'Diamonds'),
Cards(7, 'Clubs'),
Cards(5, 'Hearts'),
Cards(8, 'Diamonds'),
Cards(4, 'Spades'),
Cards(10, 'Clubs')
]
print(sort_cards(deck))
Output (you should define the method __repr__)
['7 of Clubs', '10 of Clubs', '3 of Diamonds', '8 of Diamonds', '5 of Hearts', '4 of Spades']
NB:
In my example, __repr__ is something like that:
class Card:
[...]
def __repr__(self):
return '%d of %s' % (self.rank, self.suit)
I have applied Logistic Regression on train set after splitting the data set into test and train sets, but I got the above error. I tried to work it out, and when i tried to print my response vector y_train in the console it prints integer values like 0 or 1. But when i wrote it into a file I found the values were float numbers like 0.0 and 1.0. If thats the problem, how can I over come it.
lenreg = LogisticRegression()
print y_train[0:10]
y_train.to_csv(path='ytard.csv')
lenreg.fit(X_train, y_train)
y_pred = lenreg.predict(X_test)
print metics.accuracy_score(y_test, y_pred)
StrackTrace is as follows,
Traceback (most recent call last):
File "/home/amey/prog/pd.py", line 82, in <module>
lenreg.fit(X_train, y_train)
File "/usr/lib/python2.7/dist-packages/sklearn/linear_model/logistic.py", line 1154, in fit
self.max_iter, self.tol, self.random_state)
File "/usr/lib/python2.7/dist-packages/sklearn/svm/base.py", line 885, in _fit_liblinear
" class: %r" % classes_[0])
ValueError: This solver needs samples of at least 2 classes in the data, but the data contains only one class: 0.0
Meanwhile I've gone across the link which was unanswered. Is there a solution.
The problem here is that your y_train vector, for whatever reason, only has zeros. It is actually not your fault, and its kind of a bug ( I think ). The classifier needs 2 classes or else it throws this error.
It makes sense. If your y_train vector only has zeros, ( ie only 1 class ), then the classifier doesn't really need to do any work, since all predictions should just be the one class.
In my opinion the classifier should still complete and just predict the one class ( all zeros in this case ) and then throw a warning, but it doesn't. It throws the error in stead.
A way to check for this condition is like this:
lenreg = LogisticRegression()
print y_train[0:10]
y_train.to_csv(path='ytard.csv')
if len(np.sum(y_train)) in [len(y_train),0]:
print "all one class"
#do something else
else:
#OK to proceed
lenreg.fit(X_train, y_train)
y_pred = lenreg.predict(X_test)
print metics.accuracy_score(y_test, y_pred)
TO overcome the problem more easily i would recommend just including more samples in you test set, like 100 or 1000 instead of 10.
I had the same problem using learning_curve:
train_sizes, train_scores, test_scores = learning_curve(estimator,
X, y, cv=cv, n_jobs=n_jobs, train_sizes=train_sizes,
scoring="f1", random_state=RANDOM_SEED, shuffle=True)
add the suffle parameter that will randomize the sets.
This doesn't prevent error from happening but it's a way to increase the chances to have both classes in subsets used by the function.
I found it to be because of only 1's or 0's wound up in my y_test since my sample size was really small. Try chaning your test_size value.
# python3
import numpy as np
from sklearn.svm import LinearSVC
def upgrade_to_work_with_single_class(SklearnPredictor):
class UpgradedPredictor(SklearnPredictor):
def __init__(self, *args, **kwargs):
self._single_class_label = None
super().__init__(*args, **kwargs)
#staticmethod
def _has_only_one_class(y):
return len(np.unique(y)) == 1
def _fitted_on_single_class(self):
return self._single_class_label is not None
def fit(self, X, y=None):
if self._has_only_one_class(y):
self._single_class_label = y[0]
else:
super().fit(X, y)
return self
def predict(self, X):
if self._fitted_on_single_class():
return np.full(X.shape[0], self._single_class_label)
else:
return super().predict(X)
return UpgradedPredictor
LinearSVC = upgrade_to_work_with_single_class(LinearSVC)
or hard-way (more right):
import numpy as np
from sklearn.svm import LinearSVC
from copy import deepcopy, copy
from functools import wraps
def copy_class(cls):
copy_cls = type(f'{cls.__name__}', cls.__bases__, dict(cls.__dict__))
for name, attr in cls.__dict__.items():
try:
hash(attr)
except TypeError:
# Assume lack of __hash__ implies mutability. This is NOT
# a bullet proof assumption but good in many cases.
setattr(copy_cls, name, deepcopy(attr))
return copy_cls
def upgrade_to_work_with_single_class(SklearnPredictor):
SklearnPredictor = copy_class(SklearnPredictor)
original_init = deepcopy(SklearnPredictor.__init__)
original_fit = deepcopy(SklearnPredictor.fit)
original_predict = deepcopy(SklearnPredictor.predict)
#staticmethod
def _has_only_one_class(y):
return len(np.unique(y)) == 1
def _fitted_on_single_class(self):
return self._single_class_label is not None
#wraps(SklearnPredictor.__init__)
def new_init(self, *args, **kwargs):
self._single_class_label = None
original_init(self, *args, **kwargs)
#wraps(SklearnPredictor.fit)
def new_fit(self, X, y=None):
if self._has_only_one_class(y):
self._single_class_label = y[0]
else:
original_fit(self, X, y)
return self
#wraps(SklearnPredictor.predict)
def new_predict(self, X):
if self._fitted_on_single_class():
return np.full(X.shape[0], self._single_class_label)
else:
return original_predict(self, X)
setattr(SklearnPredictor, '_has_only_one_class', _has_only_one_class)
setattr(SklearnPredictor, '_fitted_on_single_class', _fitted_on_single_class)
SklearnPredictor.__init__ = new_init
SklearnPredictor.fit = new_fit
SklearnPredictor.predict = new_predict
return SklearnPredictor
LinearSVC = upgrade_to_work_with_single_class(LinearSVC)
You can find the indexes of the first (or any) occurrence of each of the classes and concatenate them on top of the arrays and delete them from their original positions, that way there will be at least one instance of each class in the training set.
This error related to the dataset you are using, the dataset contains a class for example 1/benign, whereas it must contain two classes 1 and 0 or Benign and Attack.
So I posted this before but I didn't follow the community guidelines so I decided to post it again this time following the community guidelines. (I tried to delete my other question but it wouldn't let me)
Here is the minimal amount of code I could do to create the same problem:
class Object:
def __init__(self, *args, **kwargs):
for k, v in kwargs.iteritems():
setattr(self, k, v)
self.inventory = []
try: self.itemComponent.owner = self
except: self.itemComponent = None
class Item:
def drop(self):
for obj in objects:
if self.owner in obj.inventory:
objects.append(self.owner)
obj.inventory.remove(self.owner)
def monster_death(monster):
monster.name = 'Goblin Corpse'
for element in monster.inventory:
if element.itemComponent:
element.itemComponent.drop()
objects = []
#Create Goblin
monster = Object(name = 'Goblin')
#Populate Goblin's Equipment
monster.inventory = [
Object(name='Dagger', itemComponent=Item() ),
Object(name='Light Healing Potion', itemComponent=Item() ),
Object(name='Scroll of Chain Lightning', itemComponent=Item())
]
objects.append(monster)
print '=~In Monster Inventory~='
for item in monster.inventory:
print item.name
print
print '=~In World~='
for obj in objects:
print obj.name
print
print '***MONSTER DIES***'
print
monster_death(monster)
print '=~In Monster Inventory~='
print
for item in monster.inventory:
print item.name
print
print '=~In World~='
print
for obj in objects:
print obj.name
What happens is one of the items always stays in the monsters inventory...it seems almost random which item stays in but it is always the same item every time unless I remove or add more items to his inventory.
You're removing from the list that you are currently iterating through, that will affect the iteration.
If you need to process each item, then do that in the loop, and then clear the list afterwards
my_list = ['a', 'b', 'c']
my_list[:] = [] # clear the list without replacing it
First off I am getting this error
File "E:\New folder (7)\maingame.py", line 64, in play print self.introduction AttributeError: 'game' object has no attribute 'introduction'
I am not to sure as to what it means because I am pulling the self.introduction from the previous class..
I am also getting an
File "E:\New folder (7)\maingame.py", line 96, in <module>
game.play()
TypeError: play() takes exactly 2 arguments (1 given)
error, but can't for the life of me find what argument it is looking for, I simply want it to work.
from random import random
class place(object):
def __init__(self, title, description, events):
self.title = title
self.description = description
self.events = events
class event(object):
def __init__(self, probability, message, healthChange):
self.probability = probability
self.message = message
self.healthChange = healthChange
def process(self):
if random() < self.probability:
print self.message
return self.healthChange
return 0
class textadventure():
def __init__(self):
super(textadventure, self).__init__()
self.introduction = """
Welcome player, you are a lone traveler in space whom has set out to find glories beyond measure.
Unfortunately for you the dread pirate Roberts has attacked. You must defeat him.
"""
commandDeck = place('Command Deck', "You are now in the command center, here you can drive the ship and fire its weapons.",(
event(0.7, "The pirate ship fires at you! You take damage to your engines!", -10),
event(0.2, "One of the pirates manages to beam onto your ship! He shoots you before beaming away!",0),
))
engineRoom = place('Engine Room', "You are now in the main engine room here you can repair damage to the ship",(
event(0.7, "The pirate ship fires at you! You take damage to your engines!", -10),
))
restQuarters = place('Resting Quarters', "Here you can take a rest and heal your self",(
event(1.0, 'You are able to patch up your wounds and get back to the battle',0),
event(0.5, "The pirate ship fires at you! You take damage to your engines!", -10),
))
commandDeck.transitions = (engineRoom, restQuarters),
engineRoom.transitions = (commandDeck, restQuarters),
restQuarters.transitions = (commandDeck, engineRoom),
self.location = commandDeck
pirateHp = 50
class game(object, textadventure):
def __init__(self):
super(game, self).__init__()
self.health = 100
def location(self):
if self.location == commandDeck:
choice = raw_input('would you like to fire on the enemy ship?')
if choice == 'yes':
print 'You have hit the pirates!'
pirateHp -= 10
else: choice == 'no'
elif self.location == engineRoom:
choice = raw_input('Would you like to repair the engines?')
if choice == "yes":
event(1, "You repair what you can of the engines.", 10)
def __init__(self):
self.health = 100
def play(self, textadventure):
print textadventure.introduction
while True:
print (self.location.description)
for event in self.location.events:
self.health += event.process()
if self.health <= 0:
print ("Your ship has been destroyed!")
pause
exit(1)
print ('Your ships health is at %d percent' % self.health)
self._transition()
def _transition(self):
transitions = self.location.transitions
print ('you can go to: ')
for (index, transition) in enumerate(transitions):
print (index + 1, transition.title)
choice = int(raw_input('Choose one '))
if choice == 0:
exit(0)
else:
self.location = transitions[choice - 1]
def pirateShip(Object):
if pirateHp == 0:
print "You have defeated the pirates! Congradualations!"
pause
exit(1)
game = game()
game.play(game)
'game' object has no attribute 'introduction'
You should call the init of your super class when initializing game. In your current code, textadventure.init is never called which is why introduction is never added to textadventure.
Game should also not inherit from object (it does that through textadventure).
class game(textadventure):
def __init__(self):
super(game, self).__init__()
self.health = 100
def play(self):
print self.introduction
Should do the trick.
TypeError: play() takes exactly 2 arguments (1 given)
You never use your textadventure argument in play. Removing this should get things working.