Attribute Error Blackjack Python [closed] - python

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I have to modify this program from my text book to use bets but I cant even get the original program to run. This is the program as it appears in the book except each class are on different pages. I'm not sure if I need to even type out all these classes because my professor said take the blackjack program and modify it to accept bets but it imports deck and card so I'm not sure. I typed them out just in case because I figured it wouldn't do much harm maybe I am wrong.
class Card(object):
RANKS=(1,2,3,4,5,6,7,8,9,10,11,12,13)
SUITS=('Spades','Diamonds','Hearts','Clubs')
def _init_(self,rank,suit):
self.rank=rank
self.suit=suit
def _str_(self):
if self.rank==1:
rank='Ace'
elif self.rank==11:
rank='Jack'
elif self.rank==12:
rank='Queen'
elif self.rank==13:
rank='King'
else:
rank=self.rank
return str(rank)+ ' of ' + self.suit
import random
class Deck(Card,object):
def _init_(self):
self._cards=[]
for suit in Card.SUITS:
for rank in Card.RANKS:
c=Card(rank,suit)
self._cards.append(c)
def shuffle(self):
random.shuffle(self._cards)
def deal(self):
if len(self)==0:
return None
else:
return self._cards.pop(0)
def _len_(self):
return len(self._cards)
def _str_(self):
result=''
for c in self._cards:
result= result+str(c)+'\n'
return result
class Player(Deck,object):
def _init_(self, cards):
self._cards= cards
def _str_(self):
result=",".join(map(str,self._cards))
results += "\n " + str(self.getPoints()) + " points"
return result
def hit(self,card):
self._cards.append(card)
def getPoints(self):
count=0
for card in self._cards:
if card.rank>9:
count+=10
elif card.rank==1:
count+=11
else:
count+=card.rank
for card in self._cards:
if count <=21:
break
elif card.rank==1:
count -= 10
return count
def hasBlackjack(self):
return len(self._cards)==2 and self.getpoints()==21
class Dealer(Player,object):
def _init_(self,cards):
Player._init_(self,cards)
self._showOneCard= True
def _str_(self):
if self._showOneCard:
return str(self._cards[0])
else:
return Player._str_(self)
def hit(self,deck):
self._showOneCard= False
while self.getPoints() <17:
self.Cards.append(deck.deal())
class Blackjack(Player, object):
def _init_(self):
self._deck = Deck()
self._deck.shuffle()
self._player = Player([self._deck.deal(),
self._deck.deal()])
self._dealer = Dealer([self._deck.deal(),
self._deck.deal()])
def play(self):
print ("Player:\n", self._player)
print ("Dealer:\n", self._dealer)
while True:
choice = input("Do you want to hit? [y/n]: ")
if choice in ("Y","y"):
self._player.hit(self._deck.deal())
points = self._player.getPoints()
print ("Player:\n", self._player)
if points >= 21:
break
else:
break
playerPoints = self._player.getPoints()
if playerPoints> 21:
print ("You bust and lose")
else:
self._dealer.hit(self._deck)
print ("Dealer:\n", self._dealer)
dealerPoints=self._dealer.getpoints()
if dealerPoints >21:
print ("Dealer busts you win")
elif dealerPoints>playerPoints:
print ("Dealer wins")
elif dealerPoints<playerPoints and playerPoints <= 21:
print ("You win")
elif dealerPoints == playerPoints:
if self._player.hasBlackjack() and not self._dealer.hasBlackjack():
print ("You win")
elif not self._player.hasBlackjack() and self._dealer.hasBlackjack():
print ("Dealer wins")
else:
print ("There is a tie")
Blackjack().play()
I get
Traceback (most recent call last):
File "C:\Users\Schuler\bj.py", line 151, in <module>
Blackjack().play()
File "C:\Users\Schuler\bj.py", line 117, in play
print ("Player:\n", self._player)
AttributeError: 'Blackjack' object has no attribute '_player'
I copied everything straight from the book and I can't figure out what is wrong.
_____Edit_____
So It was pointed out I forgot double underscores so I fixed that. Then I ran if like 10 more times and found small spelling mistakes it runs now.

It looks like you left out the double underscores on some of your method definitions. It's __init__, not _init_. Same goes for __str__, __len__, and other special class methods.
These special method names have to be written exactly otherwise they won't work. For instance, if you have a method named __init__ then the code in that method will get run automatically when you instantiate an object of that type. Because you typed it wrong the method never ran and your code gave the error.
A simple illustration of how __init__ works:
class Player(object):
def __init__(self):
print 'new player object'
Player() # __init__() called automatically and prints 'new player object'

Related

Attribute error from an object that isn't called upon [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I am working on a Mastermind game in python, and one of my classes is called the Game class. This runs a 'setup' of the game as such (like finding the player count, player names etc.). However, one of my methods which checks the name inputted against a player list previously defined/stored in a separate class is bringing up an AttributeError when I try to append the name to a new list created in my Game class. This is what my Game class currently looks like:
class WorldOfMastermind:
"""WOM class - Runs whole game, takes results from other classes and stores them (namely players and their scores)"""
def __init__(self):
self.__playerList = []
self.__playerDetails = dict()
def run(self):
"""Run method - holds the menu screen - allows for the user to add player, show scores, play game or quit"""
cpuNames = ComputerPlayer.addDetails(self)
self.__playerList.extend((cpuNames))
start = input('What would you like to do?\n (r) register a new user\n (s) show the score board\n (p) play a game\n (q) quit\n')
if start == 'r':
tempName = HumanPlayer.addDetails(self)
for i in self.__playerList:
if i == tempName:
print('')
print('Sorry, that name already exists')
print('')
self.run()
self.__playerList.append(tempName)
self.__playerDetails[tempName] = [0, 0, float(0)]
print('Welcome,', tempName + '!')
print('')
self.run()
elif start == 's':
self.printScoreBoard()
elif start == 'p':
print('Let\'s play the game of Mastermind!')
Game.startPrep(self, self.__playerList)
elif start == 'q':
print('Thank you for playing the World of Mastermind!')
exit()
else:
print('\nSorry, that is an invalid input')
print('')
self.run()
def printScoreBoard(self):
""" Print the scoreboard by iterating through the dictionary """
print('=====================================')
print('Name Score Games Average ')
print('=====================================')
for i in self.__playerDetails:
print('{:<15} '.format(i), '{:>5}'.format(self.__playerDetails[i][0]), '{:>5}'.format(self.__playerDetails[i][1]), '{:>7}'.format(self.__playerDetails[i][2]))
print('=====================================\n')
self.run()
class Game:
"""Begin the initialization of the game and return results to WOM class"""
def __init__(self, playerCount):
self.__playerCount = playerCount
self.__playingList = []
def startPrep(self, playerList):
"""Prepares the game"""
Game.getPlayerCount(self)
Game.getPlayerNames(self, playerList)
def getPlayerCount(self):
"""Gathers the number of players"""
while True:
try:
self.__playerCount = int(input('How many players (2-4)?'))
except ValueError:
print('Only numbers allowed')
else:
if self.__playerCount < 2 or self.__playerCount > 4:
print('Player count must be between 2-4 inclusive')
else:
break
def getPlayerNames(self, playerList):
"""Gathers names of players and puts them into a list"""
while True:
if self.__playerCount == 2:
while True:
player1 = input('What is the name of player #1?')
if player1 in playerList:
print('successful')
self.__playingList.append(player1)
break
else:
print('Invalid username')
while True:
player2 = input('What is the name of player #2?')
if player2 in playerList:
if player2 not in self.__playingList:
print('successful')
self.__playingList.append(player2)
break
else:
print(player2, 'is already in the game.')
else:
print('Invalid username')
break
Where I feel the error is coming from is in the calling of the getPlayerNames method. As it takes a parameter (the player list from another class), this is purely to check that the name inputted is actually in the game, and if so it prints 'successful' (which it does) but when trying to append the inputted name into the new 'playingList' it brings up the error. I'm not sure why this is as the append line doesn't have any need to reference attributes from another class. Any advice would be appreciated thanks!
Your code works for me, formatted as below.. If I run the following, it asks for the player count and makes sure the names you give are in the eligible player list.
class Game:
"""Begin the initialization of the game and return results to WOM class"""
def __init__(self, playerCount=0):
self.__playerCount = playerCount
self.__playingList = []
def startPrep(self, eligible):
"""Prepares the game"""
self.getPlayerCount()
self.getPlayerNames(eligible)
def getPlayerCount(self):
"""Gathers the number of players"""
while True:
try:
self.__playerCount = int(input('How many players (2-4)?'))
except ValueError:
print('Only numbers allowed')
else:
if self.__playerCount < 2 or self.__playerCount > 4:
print('Player count must be between 2-4 inclusive')
else:
break
def getPlayerNames(self, playerList):
"""Gathers names of players and puts them into a list"""
for i in range(self.__playerCount):
while True:
s = 'What is the name of player #%d? '%(i+1)
player = input(s)
if player in playerList:
print('successful')
self.__playingList.append(player)
break
else:
print('Invalid username')
g = Game()
g.startPrep(['bob','bill'])

Why changing a function argument reflects to the main value that is I passed to that function?

I have tried to create a BLACKJACK game using python (actually I'm learning python). Currently I have not setup bet command (that is written in my Account class). I only takes name from my Account class.
I have a main file : blackjack.py
and two classes in files : deckofcards.py, account.py
I am only accessing name from account class, so I wont be putting that long mess here.
blackjack.py :
from account import Account
player = Account('kalaLokia')
cards = DeckOfCards()
play = False
playershand = []
dealershand = []
action = ''
blackjack = False
def showCards(items, name):
'''
Shows {name}'s cards and hand value
'''
print(f"{name}'s hand: ")
print(f"\t{' - '.join(items)}")
print(f"Hand value: {cards.handValue(items)}")
def bust(hand):
'''
Whether a someone has busted or not
'''
if(cards.handValue(hand) > 21):
return True
return False
def dealersMove():
'''
Dealers move: executes when player calls "stand"
Dealer perform hit until he gets bust, wins or his hand value becomes >= 17
When hand value is >17 and players has greater value, dealer loses ;-)
'''
global blackjack
if(cards.handValue(dealershand) == 21):
print('Dealer got a BLACKJACK')
print('Dealer WINS')
return
elif(blackjack):
print(f'{player.name} got a BLACKJACK')
print(f'{player.name} WINS')
blackjack=False
return
while(not bust(dealershand)):
if(cards.handValue(dealershand) > cards.handValue(playershand)):
print('Dealer WINS')
showCards(dealershand, 'Dealer')
break
elif(cards.handValue(dealershand) == cards.handValue(playershand)):
print("It's a TIE!!\n Dealer WINS")
break
elif(cards.handValue(dealershand) > 17):
print(f'Dealer loses\n{player.name} has WON.')
print(f'{cards.handValue(playershand)} > {cards.handValue(dealershand)}')
break
dealershand.append(cards.hit())
else:
print(f'Dealer busts! \n{player.name} has WON the game.')
def start():
'''
The actiona that can be performed
'''
global blackjack
if(cards.handValue(playershand) == 21):
blackjack = True
dealersMove()
return
while(not bust(playershand)):
action = input(
f"{player.name}'s turn: Do you want to hit or stand ? ").lower()
if(action == 'hit'):
playershand.append(cards.hit())
showCards(playershand, player.name)
elif(action == 'stand'):
dealersMove()
break
else:
print('Please enter a valid action !')
else:
print(f'{player.name} has been BUSTED')
if __name__ == "__main__":
print(f'Hello {player.name}, Welcome to BlackJack Game')
# Tell game rules here, may be
response = input('Do you want to start the game (Y/n)? ').lower()
if(response != 'y'):
play = False
print('You have been exited the game')
else:
play = True
# Ask for bet amount later
while(play):
cards = DeckOfCards()
cards.shuffle()
print('Cards on the table is now shuffled')
playershand = list(cards.initiate())
dealershand = list(cards.initiate())
print(
f"{player.name}'s hand:\n {playershand[0]} - {playershand[1]}\nHand value: {cards.handValue(playershand)}\n")
print(f"Dealer's hand:\n {dealershand[0]} - ?\n")
start()
if(input('Do you want to play again (Y/n)?').lower() != 'y'):
print('The End')
play = False
deckofcards.py :
import random
class DeckOfCards():
'''
All talks here is about cards
'''
cards = {'A':11,'K':10,'Q':10,'J':10,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9,'10':10}
def __init__(self):
'''
Initialize deck of cards
'''
self.deck = list(self.cards.keys())*4
def shuffle(self):
'''
Simply shuffles the deck of cards
'''
return random.shuffle(self.deck)
def handValue(self, hand):
'''
Calculates and returns the hand value, expecting a string value to be feeded.
'''
result = 0
for element in hand:
result = result + self.cards[element]
while('A' in hand and result > 21):
if(hand[0]=='A'):
result = result - 10
# Somehow this hand.pop is poping out from main value itself. Why ???
hand.pop(0)
if(hand == []):
break
return result
def hit(self):
'''
Pop out and returns the last card in the deck
'''
return self.deck.pop()
def initiate(self):
'''
Pop out 2 cards from the deck and return as a tuple
'''
return (self.deck.pop(), self.deck.pop() )
Issue:
When I have an ACE in my hand and my hand value is greater than 21, the while condition executes in the handValue function (which is in DeckofCards class) as it is. Problem is, after that while condition executes, playershand (declared in main file) I just passed to this handValue function gets empty. That is the hand.pop(0) actually seems popping out value from main object playershand itself (It seems me so).
When I press a hit after that, I get a single new card, all other cards are got popped out. I don't understand why it is so.
On hit(user enter hit) : actually I am passing playershand (cards on the player hand, it's a list) to function showCards (which is also in the main file) where it takes it as argument items and pass it to handValue function in the class DeckOfCards.
So why is it happening? even though I am passing playershand as an argument to other functions, how pop() function affecting playershand which has only access to hand object in the handValue class ?
I have my complete code in github repo to test out, the files in folder blackjack

calling function several times

I have another problem with my text game. I have written a function that generates a random mob depending on the roll.
def random_mob():
roll = twenty_sided_die.roll()
if roll <= 5 :
return Zombie()
elif roll <= 10:
return Ghul()
elif roll <= 15:
return Skeleton()
elif roll <= 19:
return Ghost()
else:
return Slime()
mob = random_mob()
Than I have a function called encounter:
def encounter():
for command, action in hero.COMMANDS.items():
print("Press {} to {}".format(command, action[0]))
while True:
command = input("~~~~~~~Press key to continue~~~~~~~")
if command not in hero.COMMANDS:
print("Not a valid command")
continue
print("You are fighting " + mob.name)
print("")
time.sleep(1)
break
while True:
if command:
hero.COMMANDS[command][1]()
PlayerAttack()
time.sleep(1)
if mob.hp > 0:
MonsterAttack()
time.sleep(1)
if hero.hp <= 0:
print("++++++You were killed++++++")
break
time.sleep(1)
else:
continue
When calling the function, random monster is being generated,fight and rolls begins. After each successful roll, monster looses its HP.
After the function ends I would like to call next encounter in the way that again a random mob is being generated and the fight starts over
Problem I have, that if I call encounter() again, it generates the same monster, with HP from previos fight, and the function ends after one roll.
How to deal with it?
You are not initializing hit points for the monster. Maybe mob should be an array, where you append/push new monster by encounter() method/function. Then, if during the fight the monster is killed you remove/pop it. For example (the monster to fight next is on top of the stack in this example, if the stack is empty fight is over):
#begin game
mob = []
...
# add monster object to the stack
mob.push(random_mob())
...
if mob.hp > 0:
#do fighting
else:
# remove monster object from the stack
mob.pop()
First, I think you've to learn how Python works and how variables manage their scope inside packages, classes and functions.
You should also learn more about general programming with objects to get started on a good foundation. You can find lots of tutorials on the web.
As said in the comments, your main problem is that your variable mob is never modified!
Here's an example of a factory that can randomly generate monsters when you call the function encounter():
from random import randint
class Zombie(object):
pass
class Ghul(object):
pass
class Skeleton(object):
pass
class Ghost(object):
pass
class Slime(object):
pass
class MobFactory(object):
# create() function will return a mob depending of roll value
#staticmethod
def create(roll):
if roll <= 5:
return Zombie()
elif roll <= 10:
return Ghul()
elif roll <= 15:
return Skeleton()
elif roll <= 19:
return Ghost()
else:
return Slime()
def encounter():
roll = randint(1, 20)
mob = MobFactory.create(roll)
print(mob.__class__)
if __name__ == '__main__':
# Here I simulate multiple call of encounter()
for _ in range(0, 3):
encounter()
I hope it will help you.

How to use dictionary in class? it shows the dict is not defined [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I do define the dictionary, but it keeps sayingt that the dictionary "ROOMS" is not defined.
First I thought it was because the dict was outside the class, but when I put it in the class, it still shows the same information.
Then I want to know how to refer to a dictionary in class?
Thanks to the first answer, I have already tried self.ROOMS and it worked. But what if I have many dicts, do I have to put them all in method init?? But it is recommended in "Learn python the hard way" that we'd better not put so much under init
code is attached here,and unrelated part has been minimized.
from sys import exit
from random import randint
class Game(object):
def __init__ (self, start):
self.quips = ['You died.you kinda suck at this.', 'Nice job, you died...jackass.',
"Such a luser.",
'I have a small puppy that\'s bettr at this.']
self.start = start
def play (self):
next = self.start
while True:
print "\n--------"
room = ROOMS[next]
next = room()
def death(self):
print self.quips[randint(0,len(quips)-1)]
exit(1)
def central_corridor(self):
action = raw_input(">")
if action == "shoot!":
return 'death'
elif action == "dodge!":
return 'death'
elif action == "tell a joke":
return 'laser_weapon_armory'
else :
print "DOES NOT COMPUTE!"
return 'central_corridor'
def laser_weapon_armory(self):
code = "%d%d%d" %(randint(1,9), randint(1,9), randint(1,9))
guess = raw_input("[keypad]>")
guesses = 0
while guess != code and guesses < 10:
print "BZZZZEDDD!"
guesses += 1
guess = raw_input("[keypad]>")
if guess == code:
return 'the_bridge'
else:
return 'death'
def the_bridge(self):
action = raw_input("> ")
if action == "throw the bomb":
return 'death'
elif action == "slowly place the bomb":
return 'escape_pod'
else:
print "DOES NOT COMPUTE!"
return "the_bridge"
def escape_pod(self):
good_pod = randint(1,5)
guess = raw_input("[pod#]> ")
if int(guess) != good_pod:
return 'death'
else:
exit(0)
ROOMS = {
'death' : death,
'central_corridor' : central_corridor,
'laser_weapon_armory' : laser_weapon_armory,
'the_bridge' : the_bridge,
'escape_pod' : escape_pod
}
a_game = Game("central_corridor")
a_game.play()
You can move the definition of ROOMS into the __init__ method of your class and refer to it later as self.ROOMS and also prepend self. to the function names ....
class Game(object):
def __init__ (self, start):
self.quips = ['You died.you kinda suck at this.', 'Nice job, you died...jackass.',
"Such a luser.",
'I have a small puppy that\'s bettr at this.']
self.start = start
self.ROOMS = {
'death' : self.death,
'central_corridor' : self.central_corridor,
'laser_weapon_armory' : self.laser_weapon_armory,
'the_bridge' : self.the_bridge,
'escape_pod' : self.escape_pod
}
def play (self):
next = self.start
while True:
print "\n--------"
room = self.ROOMS[next]
next = room()

Simple 1 vs 1 Fight Simulation [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I'm trying to write a simple program that defines two imaginary fighters with only a name and amount of health.
Right now this is what I have written:
import random
def main():
pass
if __name__ == '__main__':
main()
hpRed = 20
hpBlu = 20
def attack():
damage = random.randrange(1,3)
return hpRed - damage
return hpBlue - damage
def fighterRed(name, hpRed):
print(str(name) + " has " + str(hpRed) + " health left.")
def fighterBlue(name, hpBlu):
print(str(name) + " has " + str(hpBlu) + " health left.")
def battle():
fighterRed("Branden",hpRed)
fighterBlue("Alex",hpBlu)
while ((hpRed > 0) and (hpBlu > 0) is True):
attack()
else:
print("The battle is over!")
if (hpRed > 0):
return "Red Player is victorious!"
else:
return "Blue Player is victorious!"
battle()
So far I constantly receive the error "hpRed referenced before assignment". What can I change to get it to properly pass on the value of hpRed and hpBlu?
There were a couple of errors:
You were using two different names: hpBlue and hpBlu
You were returning two values instead of changing the values of the variables you defined.
Your printing functions were just executing 1 time. (Added inside the while so it prints each iteration)
Code:
import random
hpRed = 20
hpBlu = 20
def attack():
global hpRed, hpBlu
damage = random.randrange(1,3)
hpRed = hpRed - damage
hpBlu = hpBlu - damage
def fighterRed(name, hpRed):
print(str(name) + " has " + str(hpRed) + " health left.")
def fighterBlue(name, hpBlu):
print(str(name) + " has " + str(hpBlu) + " health left.")
def battle():
while (((hpRed > 0) and (hpBlu > 0)) is True):
fighterRed("Branden",hpRed)
fighterBlue("Alex",hpBlu)
attack()
else:
print("The battle is over!")
if (hpRed > 0):
return "Red Player is victorious!"
else:
return "Blue Player is victorious!"
battle()
You're not actually making any changes to either player's hp; look at your attack() function and start checking your variables.
The hpRed and hpBlue (which is misspelled in at least one place by the way) variables are defined at the module ("global") level. The names inside the functions are function-local names, which cannot see global variables unless they are explicitly assigned to globals. That would look like this:
def attack():
global hpRed, hpBlue
# rest of your function
While you could do this simply with globals, it's not very good practice. I recommend passing the value into any functions that need it, or putting it in a class so that methods of the class can operate on it.
def attack(hpr, hpb):
# calculate damage, then...
return (hpr - damage, hpb - damage)
You may notice that I changed your return statement. What you'd written wouldn't work the way you wanted it to: once you return, you can't return again from the same method call (that behavior would be more like a generator). If you want to return both the new red HP and the new blue HP, return a tuple containing them both.
This code has some other problems as well-- you're never actually changing the global variables, for instance, and you'll save yourself some headache if you put a print call inside the while loop so you can see how the hp changes.

Categories