Updating the value of an attribute on an instance of a class - python

I was not sure how to word this problem I'm having and after 4 hours of searching I am left here to ask. So i will lay out my problem and hope for the best!
I have completed every step of this program and have gotten it to run, but my brain can not wrap around how to solve this problem.
Here is the instructions:
Match Coins: Create a coin toss game with two players.
Each player starts with 20 coins. Rules:
each player tosses their own coin
If the coins match,
Player1 gets Player2’s coin.
If not, the Player2 gets the coin from Player1.
Whoever has the most coins wins.
In main(), create a while loop that asks to user to continue play.
In each loop, report the results … coins matched?
Total coins for each player?
The loop should toss the coins at least once.
A ‘Coin’ class is needed. The class requires:
The methods __init__(), toss(), get_sideup(), get_amount(), set_amount()
The class needs the attributes ’__amount’, initialized to 20, and ’__sideup’
initialized to one of two values, ‘Heads’ or ‘Tails’.
‘toss()’ method : generates a random value of ‘0’ or ‘1’, assigning ‘Heads’ or ‘Tails’ accordingly.
‘get_sideup()’ method : returns the current value of __sideup.
‘set_amount()’ method : passes a +1 or -1 to change __amount, depending on the results of the toss.
‘get_amount()’ method : returns the current value of __amount.
I have most of this working but I can not figure out how to add coins to one instance and subract from the next.
(I put self.get_amount as filler in the function im having problems with)
Here is my code:
import random
class Coin (object):
def __init__ (self, __amount = 20, __sideup = "Heads"):
self.__amount = __amount
self.__sideup = __sideup
def toss (self):
val = random.randint(0,1)
if val == 0:
self.__sideup = "Heads"
else:
self.__sideup = "Tails"
def get_sideup (self):
return self.__sideup
def get_amount(self,):
return self.__amount
def set_amount (self, __amount):
self.get_amount
c1 = Coin()
c2 = Coin()
play = input ("Do you want to play? (Y/N): ")
while play == "Y" or "y":
c1.toss()
c2.toss()
if c1.get_sideup() == c2.get_sideup():
c1.set_amount(+1)
c2.set_amount(-1)
print("player 1 wins")
else:
c1.set_amount(-1)
c2.set_amount(+1)
print("player 2 wins")
print(" player1: " + str(c1.get_amount()) + " and player2: " + str(c2.get_amount()))
play = input("Do you want to play? (y/n): ")
Thank you to anyone who reaches out. If the answer to my question is on here please link it. I'm a beginner and not sure how to word my questions very well.

You just need to update the self.__amount property of your coin object by rebinding it to the sum of __amount and self.__amount in your coin's set_amount method.
def set_amount (self, __amount):
self.__amount = self.__amount + __amount
or a little more succinctly,
def set_amount (self, __amount):
self.__amount += __amount

Related

Python Blackjack Project Type Error: Chips.place_bet() missing 1 required positional argument

I am trying to write my first python project blackjack. I was advised to write the program with each class and its methods in a different file so that the code would be more manageable. I divided my code up into smaller files and used import statements.
When I run my code I get the following error message:
Chips.place_bet() missing 1 required positional argument. self.
I thought self was, pardon the pun, self explanatory. I do not need to put a value for self. I am wondering if this is an import issue.
I am trying to get my place_bet function to activate so that I can ask the user to input the number of chips for a bet. Can anyone advise me on how to do this?
My code is spread over these files:
blackjack.py
import random
from player import Player
from hand import Hand
from chips import Chips
from deck import Deck
from card import Card
# import helper_functions
# Blackjack/
# ├── app/
# │ ├── card.py
# │ ├── chips.py
# │ ├── deck.py
# │ ├── hand.py
# │ ├── player.py
# │ ├── main.py
# │ ├── helper_functions.py
# Gameplay and Outline of Project
# Welcome message and rules
print("Welcome to Blackjack! The rules for blackjack can be found here. https://www.youtube.com/watch?v=PljDuynF-j0")
print("The object of this blackjack game is to make it to 100 chips. You will start with 25 chips.")
# Establish player name
print("Please insert your player name: ")
player_name = input()
print('Please insert your player name ' + player_name)
print("Lets get started" + player_name + "please place your bet!")
# Place the bets BEFORE the cards are dealt. Pure risk.
place_bet()
# . Deal 2 cards to user and dealer
# . print a message explaining the total hand value of the user. ask player to hit/stay?
# . If the player busts print player busts. if the player is under 21 ask them again to hit or stay.
# . If stay, move on to dealers turn.
# . If the hand is less than 17 have him hit, if it is over 17 have the dealer stay.
# . If the dealer stays print the dealers hand total. IF the dealers hand total is greater than the player the dealer wins.
# . if the dealer busts print the message he busts and the player wins and the player gets the chips.
# 1. Ask dealer to hit/stay?
# 2. If hit, deal 2 cards
# 3. If broke or blackjack deliver message
# 4. If stay, compare hands
# 5. If users hand is closer to 21, (user wins)
# 6. If dealers hand is closer to 21, (user loses)
def main():
player = Player('strikeouts27', 500,)
dealer = Player()
player_chips = Chips()
dealer_chips = Chips()
cards = Card()
deck = Deck()
if __name__ == '__main__':
main()
card.py
class Card:
"""Card class"""
def __init__(self, rank, suit):
self.rank = rank
self.suit = suit
def __repr__(self):
return f'{self.__class__.__name__}(rank={self.rank}, suit={self.suit})'
class Chips:
"""Chip class manages chip balance"""
def __init__(self, balance):
self.balance = balance
self.bet = 0
def place_bet(self):
while True:
total = input(f'How much do you bet? (1-{self.balance}):\n> ')
# return True if a digit string. false otherwise. hover over the method for visual studio code to show you.
if not total.isdigit():
continue
total = int(total)
if total > self.balance:
print('You do not have enough')
continue
return total
def add_value(self, value):
"""Add value to chip total"""
self.balance += value
def deduct_value(self, value):
"""Deduct value from chip total"""
self.balance -= value
def display_chips(player, dealer):
print(f'player chips: ${player.chips.balance}')
print(f'dealer chips: ${dealer.chips.balance}')
# Displays player and dealer chip count
class.py
class Card:
#"""Card class"""
def __init__(self, rank, suit):
self.rank = rank
self.suit = suit
def __repr__(self):
return f'{self.__class__.__name__}(rank={self.rank}, suit={self.suit})'
deck.py
class Deck:
"""Deck class, represents 52 cards"""
def __init__(self):
self.ranks = [str(n) for n in range(2, 11)] + list('jqka')
self.suits = ["hearts", "diamonds", "clubs", "spades"]
self.cards = [Card(rank, suit)
for suit in self.suits for rank in self.ranks]
random.shuffle(self.cards)
# dunder method rewrites what pythons default method to show better information about itself.
def __repr__(self):
return f'{self.__class__.__name__}({self.cards})'
def __len__(self):
return len(self.cards)
def __getitem__(self, item):
return self.cards[item]
def shuffle(self):
"""shuffles deck of cards"""
random.shuffle(self.cards)
hand.py
class Hand:
"""Hand class to hold the cards for the player and the dealer"""
def __init__(self, cards=None):
self.cards = [] if cards is None else cards
self.value = 0
self.aces = 0
def add_to_hand(self, card):
"""Adds a cards to self.cards."""
self.cards.append(card)
def display_hand(self):
hashtable = {'hearts': 9829, 'diamonds': 9830,
'spades': 9824, 'clubs': 9827}
return [[i.rank, chr(hashtable.get(i.suit))] for i in self.cards]
def display_hand_two(player, dealer):
# Displays player and dealer hand
print(
f'players Hand: {player.hand.display_hand()} --> total {player.total}')
print(
f'dealer Hand: {dealer.hand.display_hand()} --> total {dealer.total}')
player.py
class Player:
"""Player class"""
def __init__(self, name, chips, hand):
self.name = name
self.chips = chips
self.hand = hand
#property
def total(self):
"""Returns the value of the cards. Face cards equal 10, aces can equal
11 or 1, this function picks best case"""
value = 0
aces_count = 0
# Each card is a tuple in a list:
cards = [card for card in self.hand.cards]
for card in cards:
if card.rank == 'a':
aces_count += 1
elif card.rank in 'kqj':
# Face cards are worth 10 points
value += 10
else:
# Numbered cards are worth their value.
value += int(card.rank)
# Add value of aces - 1 per ace
value += aces_count
for i in range(aces_count):
# If another 10 can be added,then do it!
if value + 10 <= 21:
value += 10
return value
#staticmethod
def get_move():
"""returns player choice to hit or stand"""
move = input('>>> (H)it, (S)tand ?:\n> ').lower()
return move
def main():
# Instantiate Deck
deck = Deck()
# shuffle deck
deck.shuffle()
# Instantiate player and dealer chips
player_chips = Chips(500)
dealer_chips = Chips(500)
while True:
# Instantiate player and dealer hand
player_hand = Hand()
dealer_hand = Hand()
# Instantiate player and dealer
player = Player('seraph', player_chips, player_hand)
dealer = Player('codecademy', dealer_chips, dealer_hand)
# Check if player has enough money
if player_chips.balance <= 0:
print('need more money')
# Then place bet
bet = player_chips.place_bet()
# player draws 2 cards
player.hand.add_to_hand(deck.cards.pop())
player.hand.add_to_hand(deck.cards.pop())
# Dealer draws cards
dealer.hand.add_to_hand(deck.cards.pop())
dealer.hand.add_to_hand(deck.cards.pop())
# display player ann dealers hand
display_hand(player, dealer)
# Begin game
while True:
if player.total > 21:
break
# Get the player's moves
player_move = player.get_move()
if player_move == 'h':
new_card = deck.cards.pop()
rank, suit = new_card.rank, new_card.suit
player.hand.add_to_hand(new_card)
print(f'You drew a {rank} of {suit}')
display_hand(player, dealer)
if player.total > 21:
print('You busted...')
# Busted
continue
if player_move == 's':
break
# Get the dealer's moves
if dealer.total <= 21 and not player.total > 21:
while dealer.total <= 17:
print('Dealer hits...')
new_card = deck.cards.pop()
dealer.hand.add_to_hand(new_card)
if dealer.total > 21:
break
if dealer.total > 21:
print('Dealer Busted - You win!')
display_hand(player, dealer)
player.chips.add_value(bet)
dealer.chips.deduct_value(bet)
display_chips(player, dealer)
elif player.total > 21 or player.total < dealer.total:
print('You lost!')
display_hand(player, dealer)
player.chips.deduct_value(bet)
dealer.chips.add_value(bet)
display_chips(player, dealer)
elif player.total == dealer.total:
print("It's a tie! Money is returned")
if __name__ == '__main__':
main()
Does anyone have advice for a rookie?
I have tried calling the function and have gotten an error. Nothing else to be honest.
A few issues:
The file class.py is redundant. It is not imported, and only defines a class that is already defined in card.py.
There are two main function definitions. One in blackjack.py and one in player.py. The first one defines a player 'strikeouts27', while the other defines 'seraph', 'codecademy'. The second one seems the more developed one, and uses more than what is in player.py, and so it should actually be moved into blackjack.py.
Related to the previous point: blackjack.py has code that executes outside of any function. This counters the pattern where you put the driver code in a function main. It is better to move all relevant driver code inside one main function that is placed in blackjack.py. But still, that code looks unfinished, and the code already present in main is much more developed. I think you only need the code in main (the larger one).
Related to the previous point: that code in blackhack.py calls a function place_bet which is not defined. There is a method with that name, but not a standalone function with that name. For calling the method you first need an instance of Chips, so like I mentioned in the previous bullet, I would suggest to just remove this code, including also the input that is made there. Maybe you just want to keep the introductory print statements that are made there, and move those into main.
random is used in deck.py, but it is imported in blackjack.py. It would make deck.py more self-contained, if you would move that import statement to the deck.py file.
display_hand_two should not be a method of the Hand class. It doesn't even expect a self argument of the type Hand. Instead this should be a standalone function in blackjack.py.
In main you have several calls like display_hand(player, dealer), but display_hand is not a standalone function, but a method. What you really wanted to do here, is call display_hand_two(player, dealer), and for that to work you must make display_hand_two a standalone function as mentioned in the previous bullet point.
If you implement all those changes, your code will run.

How to reduce the amount of lines needed for this logic?

I have a simple Python game where two players deal some damage to each other in turns until one player has 0 or less than 0 HP. I don't like how much I've repeated myself but I'm unsure how to fix this. I thought about using a list of players but then I'm unsure how to index the next player when it's their turn, without running into the list index out of range error.
If this kind of question is not allowed please let me know and I will remove it.
Below is my game logic to determine when a player has won. I may not have pasted in the exact code I have but it runs how it's expected locally.
def check_win_state(current_player):
if current_player.get_player_health() > 0:
return True
elif current_player.get_player_health() <= 0:
return False
def main():
player1 = player.Player("Me")
player2 = player.Player("You")
while True:
if check_win_state(player1):
take_turn(player1, player2)
else:
print(f"\n{player2.get_player_name()} ({player2.get_player_health()} HP) wins! {player1.get_player_name()} has {player1.get_player_health()} HP left.\n")
break
if check_win_state(player2):
take_turn(player2, player1)
else:
print(f"\n{player1.get_player_name()} ({player1.get_player_health()} HP) wins! {player2.get_player_name()} has {player2.get_player_health()} HP left.\n")
break
The easiest approach to reduce code duplication in situations like these is to use a secondary variable to hold the primary variable. Here, instead of having different code for player1 and player2, we instead have just one code, and use the variables current_player and opposing_player to hold player1 and player2, and swap with every iteration.
def main():
player1 = player.Player("Me")
player2 = player.Player("You")
current_player = player1
opposing_player = player2
while True:
if check_win_state(current_player):
take_turn(current_player, opposing_player)
else:
print(f"\n{opposing_player.get_player_name()} ({opposing_player.get_player_health()} HP) wins! {current_player.get_player_name()} has {current_player.get_player_health()} HP left.\n")
break
current_player, opposing_player = opposing_player, current_player
If you have more than two players, then a more extensible approach might be to have a list of players, and have an index rotate through the list with each iteration to specify which player is the 'current' one.
also, you can simplify check_win_state():
def check_win_state(current_player):
return current_player.get_player_health() > 0
because the check a > b returns a boolean anyway.
You can make the first function short using this logic:-
def check_win_state(current_player):
return current_player.get_player_health() > 0:
And now you can create another function to do the work of inside while loop
def work_in_while(pl, another_pl):
if check_win_state(pl):
take_turn(pl, another_pl)
else:
print(f"\n{another_pl.get_player_name()} ({another_pl.get_player_health()} HP) wins! {pl.get_player_name()} has {pl.get_player_health()} HP left.\n")
return "kill"
And use it like:-
while True:
if work_in_while(player1, player2) == "kill":
break
if work_in_while(player2, player1) == "kill":
break

How to give variable values from a function to another function?

Im making a "game" for practice. Its a basic guess game, but i wanted to make the game only with functions. This is my problem (for ex.):
function 1:
variablaA
#some other code
function 2:
variableB
variableC = varibleA + variableB
#some other code
I have tried too goole about objects and classes but im not sure i understand what im doing right now.
import random
import sys
min = 1
max = 99
guessed_number = random.randint(min, max)
class functions:
def __init__(game, difficulty, lifes):
game.difficulty = difficulty
game.lifes = lifes
def GameDiff(hardness):
#Setting game difficulty
print "Select difficulty : \n 1; Easy \n 2; Medium \n 3; Hard \n"
difficulty = raw_input()
if difficulty == "1":
print "Its just the beginning"
lifes = 15
elif difficulty == "2":
lifes = 10
elif difficulty == "3":
lifes = 5
else:
print "This isn't an option try again"
GameDiff(hardness)
def core(basic):
#The core of the game
print "I guessed a number..."
player_number = int(raw_input("Whats the number I thinking of?"))
constant = 1
GameTime = 1
while GameTime == constant:
if player_number < guessed_number:
print "Your number is smaller than my guessed number"
print "Try to duplicate your number (But maybe Im wrong)"
player_number = int(raw_input("Make your tip again\n"))
elif player_number > guessed_number:
print "Your number is bigger than my guessed number"
print "Try to half your number (But maybe Im wrong)"
player_number = int(raw_input("Make your tip again\n"))
else:
GameTime = 0
print "You guessed it! Congratulations"
def main(self):
#The whole game only with functions
functions.GameDiff()
functions.core()
Function = functions()
Function.main()
if you are defining function with parameters, you need to pass data(parameters) into a function when you call it
example:
def my_function(name):
print("my name is " + name)
my_function("Kevin")
in your case you define:
def GameDiff(hardness):
def core(basic):
which are expecting parameters
and when you are calling those funcitions, you are doing that on wrong way:
def main(self):
#The whole game only with functions
functions.GameDiff()
functions.core()
Function = functions()
you need to pass parameters
example:
functions.GameDiff(5)
functions.core(1)
Function = functions(1,5)
NOTE: good practice will be to use self instead of game
def __init__(self, difficulty, lifes):
self.difficulty = difficulty
self.lifes = lifes
they are just two different kinds of class elements:
Elements outside the init method are static elements; they belong
to the class. They're shared by all instances.
Elements inside the init method are elements of the
object (self); they don't belong to the class.Variables created inside init (and all other method functions) and prefaced with self. belong to the object instance.

How to take away health points when using a class?

I'm working on a game in python and I can't figure out how to take away health once attack function has taken place. I can run the program and the attack function works fine, it shows a random integer between 1 and 50 but doesn't actually take away health from castlehealth = 100
Underneath print("You attacked for " + str(self.attack)) I left the next line blank because I don't know what to type in, I tried a lot of different things and just can't get the attack to take away from castlehealth.
Here is my code:
import os
import time
from random import randint
class GameActions:
def __init__(self):
castlehealth = 100
self.castlehealth = castlehealth
def health(self):
print("Castle health is: " + str(self.castlehealth))
print()
def attack(self):
attack = randint(0, 50)
self.attack = attack
print("You attacked for " + str(self.attack))
def game():
while True:
game_actions = GameActions()
print("What do you want to do?")
print()
print("attack, view hp")
ans = input()
if ans == "hp":
game_actions.health()
if ans == "attack":
game_actions.attack()
You want the following:
self.castlehealth -= attack
Try something like self.castlehealth -= attack. I also fixed some potential indentation issues for you.
Your full code sample could look this this:
import os
import time
from random import randint
class GameActions:
def __init__(self):
castlehealth = 100
self.castlehealth = castlehealth
def health(self):
print("Castle health is: " + str(self.castlehealth))
print()
def attack(self):
attack = randint(0, 50)
self.attack = attack
print("You attacked for " + str(self.attack))
self.castlehealth -= attack
def game():
while True:
game_actions = GameActions()
print("What do you want to do?")
print()
print("attack, view hp")
ans = input()
if ans == "hp":
game_actions.health()
if ans == "attack":
game_actions.attack()
Explanation: self.castlehealth is an instance variable of your GameActions class. The function GameActions.attack() creates a new attack variable as a random integer and then subtracts that value from the instance variable self.castlehealth of the GameActions class. Now self.castlehealth will be the updated value. Consider also tracking the various attacks and resulting healths in a data structure, since every time you have a new attack self.castlehealth and self.attack will change values and you will lose the ability to access the previous values.

updating score in card game

I am a total beginner with python.
I need help updating the score of a card game.
The scoring works as follows:
Player A or B has a pair: score += 1
Player A asks Player B (vice versa) for a card and that player has it: score += 1
Player B doesn't have it, Player A has to draw a card. If there is pair after draw: score += 2
I have the logic down but I don't really know how to connect it together.
I tried manually adding the scores in my functions, but it get's messy and complicated :(
I assume I would have to make a new function for the score and call them in my other functions?
I would appreciate the guidance,
Thank-you!
Here is some code to get you started:
class Player:
def hasPair(self):
haveIt = False
#write logic here to see if you have it
return haveIt
def hasCard(self,card):
haveIt = False
#write logic here to see if this player has the card
return haveIt
def drawCard(self):
#write logic here
pass
def ask(self,player,card):
return player.hasCard(card)
def increment_score(self,by=1):
self.score += by
def updateScores(a,b,card):
if a.hasPair(): a.increment_score()
if b.hasPair(): b.increment_score()
if a.ask(b,card):
a.increment_score()
else:
a.drawCard()
if a.hasPair(): a.increment_score(2)
if b.ask(a,card):
b.increment_score()
else:
b.drawCard()
if b.hasPair(): b.increment_score(2)

Categories

Resources