I am trying to create an attribute 'score' and 'learn' in my code.
I am getting these error:
AttributeError: 'HumanPlayer' object has no attribute 'score' and
'learn'.
See some parts of the codes below:
#Create random player class
class RandomPlayer:
def __init__(self):
Player.__init__(self)
def move(self):
self.move = RandomPlayer
#use imported random function
RandomPlayer = random.randint(1,3)
#Computer choice is either rock, paper, or scissors
if RandomPlayerMove == ("Rock"):
print("The computer choses ROCK")
elif RandomPlayerMove == ("Paper"):
print("The computer choses PAPER")
else:
print("The computer choses SCISSORS")
#return value
return RandomPlayer
#Create human player class
class HumanPlayer:
def __init__(self):
Player.__init__(self)
def move(self):
while True:
HumanPlayer = input("'Rock', 'Paper', or 'Scissors' ")
#Detect invalid entry
if HumanPlayer.lower() not in moves:
print('Please choose Paper, Rock or Scissors: ')
else:
break
return HumanPlayer
class Game:
def __init__(self, HumanPlayer, RandomPlayer):
self.player1 = HumanPlayer
self.player2 = RandomPlayer
self.player1_score = 0
self.player2_score = 0
def play_round(self):
move1 = self.player1.move()
move2 = self.player2.move()
print(f"Player 1: {move1} Player 2: {move2}")
self.player1.learn(move1, move2)
self.player2.learn(move2, move1)
if (move1 == move2):
print("it's a tie!")
elif beats(move1, move2) is True:
self.player1_score += 1
elif beats(move2, move1) is True:
self.player2_score += 1
print("It's Tie, Play again!")
print(f"Scores, HumanPlayer: {self.player1.score} RandomPlayer: {self.player2.score}")
print("Game over!")
I'm pretty sure this is due to a typo. Rather than self.player1.score in your next to last print statement, you probably want self.player1_score, since that's an attribute you've defined in __init__. Similarly, you probably want self.player2_score instead of self.player2.score later in the same format string.
While it doesn't appear to be the cause of your current issues, there is another suggestion I'd like to make: Avoid using the same name for different things. You have a whole bunch of places where you're using the same name for both an instance and a class. For instance, your Game class takes arguments named HumanPlayer and RandomPlayer, which hide the classes with those names. You're also using your class names as variable names in each of your move methods. This is going to make bug fixing a nightmare! Use unique names. Python convention is to use CapitalizedNames for classes, lowercase_names_with_underscores for most other variables (including function and method names), and ALL_CAPS for constants (in the rare cases you need them), but you can use your own style if you prefer (just be consistent!).
Related
I'm working on a mini-project I'm doing for fun to practice python skills and I am stuck on a problem I can't seem to figure out. I have a function that gives me the default stats for every class in the game and I want it to change depending on what class/weapon I choose in the beginning. I am still trying to learn functions so any input will be valuable. So gameStat() is the default stats while gameStat() is the changed one.
import time
import random
inventory = []
def intro():
print("Hello for playing my game. It is a text based game that I am working on. \n")
print("I hope you enjoy playing it \n")
def chooseClass():
print("Please choose a class you would like to play as. Each class has a different background story to them")
print("-----------------------------------------------------------")
print("Please use the number given below to select them")
print("1: Priest\n" "2: Warrior\n" "3: Thief\n" "4: Ninja\n" "5: Pirate\n")
def classChosen(starterClass):
if starterClass == 1:
print("You have chosen Priest")
return "Priest"
elif starterClass == 2:
print("You have chosen Warrior")
return "Warrior"
elif starterClass ==3:
print("You have chosen Thief")
return "Thief"
elif starterClass ==4:
print("You have chosen Ninja")
return "Ninja"
elif starterClass ==5:
print("You have chosen Pirate")
return "Pirate"
else:
return None
def gameStat():
health = 100
mana = 100
strength = 5
magic = 5
exp = 0
baseStats(health,mana,strength,magic,exp)
def ChosenPriest(var):
if var == "Priest":
selectAns=""
selectAns=input("Would you like to know the backstory? \n:Please type 1 :Yes or 2 :No\n:")
if selectAns == 1:
print("INC")
#print("Since a child, you have been serving under the Church of Agathor.\n")
#print("You didn't have much of a choice because you had nowhere else to go.\n")
#print("You don't know who your parents are and the only thing the church would tell you that you suddenly appeared in front of the chruch with a gold cross.\n")
#print("You still have that cross til this day.\n")
#print("At the age of 16, everyone who serves for the lord will get their own holy weapon.\n")
#print("The weapon is used to fight off The Shadows. The Shadows are creatures created by the Shadow Lord, Gilmah.\n")
#print("Since the very beginning, Gilmah would rummaged through the land destorying and pillaging everything he sees.\n")
#print("One priest was able to seal him for thousands of years but he is soon to be awaken and he'll become stronger than ever.\n")
else:
print("Alright!")
def Weapons(weapon):
if weapon == 1:
print("You have chosen Magical Book!")
inventory.append("Magical Book")
return "Magical Book"
elif weapon == 2:
print("You have choosen a staff")
inventory.append("Staff")
return "Staff"
def baseStats(character,weapon):
if character == "Priest":
if weapon == "Magical Book":
mana=100
mana = mana + 50
return mana
elif weapon == "Staff":
magic=5
magic = magic + 5
return magic
#intro()
chooseClass()
userClass=None
while True:
try:
x=input("What class would you like to play?\n:")
if x>5 or x<1:
continue
else:
userClass=classChosen(x)
break
except NameError:
continue
character=ChosenPriest(userClass)
weapon=Weapons(input("What kind of holy weapon would you like to take? \n 1: Magical Book \n 2: Staff \n Use 1 or 2 to select your weapon! :"))
print(baseStats(character,weapon))
Thank you so much.
When you take any input it will be in string format to compare it with an integer you need to convert it to integer using int() function
I modified the code and it returns the value of "mana" or "magic" correctly
import time
import random
inventory = []
def intro():
print("Hello for playing my game. It is a text based game that I am working on. \n")
print("I hope you enjoy playing it \n")
def chooseClass():
print("Please choose a class you would like to play as. Each class has a different background story to them")
print("-----------------------------------------------------------")
print("Please use the number given below to select them")
print("1: Priest\n" "2: Warrior\n" "3: Thief\n" "4: Ninja\n" "5: Pirate\n")
def classChosen(starterClass):
if starterClass == 1:
print("You have chosen Priest")
return "Priest"
elif starterClass == 2:
print("You have chosen Warrior")
return "Warrior"
elif starterClass ==3:
print("You have chosen Thief")
return "Thief"
elif starterClass ==4:
print("You have chosen Ninja")
return "Ninja"
elif starterClass ==5:
print("You have chosen Pirate")
return "Pirate"
else:
return None
def gameStat():
health = 100
mana = 100
strength = 5
magic = 5
exp = 0
baseStats(health,mana,strength,magic,exp)
def ChosenPriest(var):
if var == "Priest":
selectAns=""
selectAns=int(input("Would you like to know the backstory? \n:Please type 1 :Yes or 2 :No\n:"))
if selectAns == 1:
print("INC")
#print("Since a child, you have been serving under the Church of Agathor.\n")
#print("You didn't have much of a choice because you had nowhere else to go.\n")
#print("You don't know who your parents are and the only thing the church would tell you that you suddenly appeared in front of the chruch with a gold cross.\n")
#print("You still have that cross til this day.\n")
#print("At the age of 16, everyone who serves for the lord will get their own holy weapon.\n")
#print("The weapon is used to fight off The Shadows. The Shadows are creatures created by the Shadow Lord, Gilmah.\n")
#print("Since the very beginning, Gilmah would rummaged through the land destorying and pillaging everything he sees.\n")
#print("One priest was able to seal him for thousands of years but he is soon to be awaken and he'll become stronger than ever.\n")
else:
print("Alright!")
def Weapons(weapon):
if weapon == 1:
print("You have chosen Magical Book!")
inventory.append("Magical Book")
return "Magical Book"
elif weapon == 2:
print("You have choosen a staff")
inventory.append("Staff")
return "Staff"
def baseStats(character,weapon):
if character == "Priest":
if weapon == "Magical Book":
mana=100
mana = mana + 50
return mana
elif weapon == "Staff":
magic=5
magic = magic + 5
return magic
#intro()
chooseClass()
userClass=None
while True:
try:
x=int(input("What class would you like to play?\n:"))
if x>5 or x<1:
continue
else:
userClass=classChosen(x)
break
except NameError:
continue
character=ChosenPriest(userClass)
weapon=Weapons(int(input("What kind of holy weapon would you like to take? \n 1: Magical Book \n 2: Staff \n Use 1 or 2 to select your weapon! :")))
print(baseStats(userClass,weapon))
In the gameState() function the baseStats takes 5 argument but when you defined baseStats it only takes two arguments character and weapon which is confusing.
I am creating a rock, paper, scissors game. I want it to be best of 3 matches and to be able to verify user input. I keep running into issues with the user input. I have tried multiple variations but I can't seem to figure it out. I know my code is probably messy, so any input on how to clean it up would be greatly appreciated. Thank you so much for your time.
import random
import sys
import time
print("Hello and welcome to the Rock, Paper, Scissors tournament.\n"
"The tournament will be the best of 3 wins.\n"
"It will be you against our highly intelligent computer opponent.\n"
"Good luck!")
# Create a function for the game
def play_game():
user_count = 0
comp_count = 0
tie_game = 0
while comp_count < 2 and user_count < 2:
user_choice = (int(input("-------------------------------------------"
"\nEnter choice by typing 1 2 or 3: \n 1. Rock \n 2. paper \n 3. scissor \n"
"-------------------------------------------\n")))
if user_choice == 1:
user_choice_name = 'Rock'
elif user_choice == 2:
user_choice_name = 'Paper'
elif user_choice == 3:
user_choice_name = 'Scissor'
else:
print("Please pick a valid number")
print(f"\nYou have chosen: {user_choice_name}")
print("\nNow it's the computer's turn to pick......")
time.sleep(3)
comp_choice = random.randint(1, 3)
if comp_choice == 1:
comp_choice_name = 'Rock'
elif comp_choice == 2:
comp_choice_name = 'Paper'
else:
comp_choice_name = 'Scissor'
print(f"\nComputer has chosen: {comp_choice_name}\n")
if user_choice == 1 and comp_choice == 2:
comp_count += 1
print("Computer wins this round with Paper! "
f"\n Computer: {comp_count}"
f"\n You: {user_count} \n\n")
elif user_choice == 1 and comp_choice == 3:
user_count += 1
print("You win this round with Rock!"
f"\n Computer: {comp_count}"
f"\n You: {user_count} \n\n")
elif user_choice == 2 and comp_choice == 1:
user_count += 1
print("You win this round with Paper!"
f"\n Computer: {comp_count}"
f"\n You: {user_count} \n\n")
elif user_choice == 2 and comp_choice == 3:
comp_count += 1
print("Computer wins this round with Scissor!"
f"\n Computer: {comp_count}"
f"\n You: {user_count} \n\n")
elif user_choice == 3 and comp_choice == 2:
user_count += 1
print("You win this round with Scissor!"
f"\n Computer: {comp_count}"
f"\n You: {user_count} \n\n")
elif user_choice == 3 and comp_choice == 1:
user_count += 1
print("Computer wins this round with Rock!"
f"\n Computer: {comp_count}"
f"\n You: {user_count} \n\n")
else:
if user_choice == comp_choice:
tie_game += 1
print(f"This round was a tie! Both choosing {user_choice_name}, try again!"
f"\n Computer: {comp_count}"
f"\n You: {user_count} \n\n")
else:
print(f'The game is now over with a score of: \n You:{user_count} \n to \n Computer:{comp_count}')
again = str(input("Do you want to play again, type 'yes' or 'no' \n"))
if again.lower() == "no":
print('Thank you for playing!')
sys.exit()
else:
play_game()
play_game()
Since I had a few minutes to kill with a cup of coffee, here's a rewrite of your program with a bunch of improvements, the validation you asked about and some tips on coding style:
import random
import time
print("Hello and welcome to the Rock, Paper, Scissors tournament.\n"
"The tournament will be the best of 3 wins.\n"
"It will be you against our highly intelligent computer opponent.\n"
"Good luck!")
# to avoid repeating these values over and over and changing numbers in to string,
# just defining them here. Name in capitals because it's global (generally bad)
# an even nicer solution would be to write a Game() class and put everything in
# there, but it would be a bit more advanced
RSP_OPTIONS = {
1: 'Rock',
2: 'Scissor',
3: 'Paper'
}
def get_user_choice():
# keep asking until a valid value is returned
while True:
# this is a bit fancy, but let's say you want to reuse the game for similar games
# with different options from rock, scissor, paper, you'd want this code to still work
# get a list of string versions of the numbers
numbers = list(map(str, RSP_OPTIONS.keys()))
# join them together like you presented them: 1, 2 or 3
options = ', '.join(numbers[:-1]) + ' or ' + numbers[-1] + ':\n'
# add the descriptions
options = options + ''.join(f'{n}: {name}\n' for n, name in RSP_OPTIONS.items())
try:
user_choice = (int(input("-------------------------------------------\n"
f"Enter choice by typing {options}"
"-------------------------------------------\n")))
except ValueError:
# any invalid option
user_choice = -1
# check if it's one of the valid options
if user_choice in RSP_OPTIONS:
return user_choice
else:
# it makes sense to generate a new line where you want it, instead of having
# to put new line characters at the start of other strings
print("Please pick a valid number\n")
def beats(choice1, choice2):
# choice1 beats choice2 if it's one greater, except when choice2 == 3 and choice1 == 1
# but to make it even nicer and have it work for other similar games, you could say
# "except when choice1 == the max choice and choice2 == the min choice"
return (choice2 - choice1 == 1 or
(choice1 == max(RSP_OPTIONS.keys()) and choice2 == min(RSP_OPTIONS.keys())))
# Create a function for the game
def play_game():
user_count = 0
comp_count = 0
tie_game = 0
# this is what you really want, best out of three, ties not counted?
while comp_count + user_count < 3:
user_choice = get_user_choice()
print(f"You have chosen: {RSP_OPTIONS[user_choice]}\n")
print("Now it's the computer's turn to pick......\n")
# this wait is not very nice, the user might try to hit enter or something
# you could consider printing the countdown, or telling the user to please wait
# even then, it's kind of silly to pretend the computer has to work hard here
time.sleep(3)
# this choice is always valid, so no problem
comp_choice = random.randint(1, 3)
# note that you don't need the name, you can just look it up whenever in RSP_OPTIONS
print(f"\nComputer has chosen: {RSP_OPTIONS[comp_choice]}\n")
# getting rid of some repetition, note how the code really reads like what is intended
if beats(comp_choice, user_choice):
comp_count += 1
# nice to also say what really beat them
print(f"Computer wins this round with {RSP_OPTIONS[comp_choice]} over {RSP_OPTIONS[user_choice]}!\n")
elif beats(user_choice, comp_choice):
user_count += 1
print(f"You win this round with {RSP_OPTIONS[user_choice]} over {RSP_OPTIONS[comp_choice]}!\n")
else:
# you can only get here on a tie
tie_game += 1
print(f"This round was a tie! Both choosing {RSP_OPTIONS[user_choice]}, try again!\n")
# you always print this, so just do it after the options:
print(f"Computer: {comp_count}\n"
f"You: {user_count}\n\n")
else:
print(f'The game is now over with a score of:\n You:{user_count}\n to\n Computer:{comp_count}\n')
again = str(input("Do you want to play again, type 'yes' or 'no' \n"))
# let's quit on anything starting with n
if again.lower()[0] == "n":
print('Thank you for playing!\n')
# instead of exiting hard, maybe just return, telling the caller we don't want to play again
return False
else:
# you were calling play_game again, but that causes the game to get more and more calls
# on top of each other, ultimately reaching an error state
# by returning first and then calling again, you avoid that problem
return True
# the function returns whether it should play again
while play_game():
pass
# once it leaves the loop, the game stops automatically here, no more code
There's still a lot of room for improvement though; try implementing some more advanced forms of RSP, or make the computer more intelligent than just playing random, but have it use some kind of strategy, perhaps with a bit of randomness mixed in.
And code-wise, try separating the game from the way it is presented on the screen; what if you decided to do this on the web instead of on a console, or in a graphics window? You could also consider putting all the code in a nice class, getting rid of global variables and allowing you to create more copies of the game as needed.
I'm learning python and about to complete a program to run a rock, paper, scissors game between two players for three rounds and update player scores at the end of each round and display it on screen:
import random
"""This program plays a game of Rock, Paper, Scissors between two Players,
and reports both Player's scores each round."""
moves = ['rock', 'paper', 'scissors']
"""#!/usr/bin/env python3
import random
"""This program plays a game of Rock, Paper, Scissors between two Players,
and reports both Player's scores each round."""
moves = ['rock', 'paper', 'scissors']
"""The Player class is the parent class for all of the Players
in this game"""
class Player:
def move(self):
return 'rock'
def learn(self, my_move, their_move):
pass
def beats(one, two):
return ((one == 'rock' and two == 'scissors') or
(one == 'scissors' and two == 'paper') or
(one == 'paper' and two == 'rock'))
class RandomPlayer(Player):
def move(self):
return random.choice(moves)
class Game:
def __init__(self, p1, p2):
self.p1 = p1
self.p2 = p2
def keep_p1_score(self, p1_Score):
return p1_Score
def play_round(self):
move1 = self.p1.move()
move2 = self.p2.move()
p1_Score = 0
p2_Score = 0
print(f"Player One played: {move1} Player Two played: {move2}")
if beats(move1, move2) == True:
print('**Player One wins**')
p1_Score += 1
elif beats(move2, move1) == True:
print('**Player Two wins**')
p2_Score += 1
else:
print('**TIE**')
print(f'Score: Player One: {p1_Score} Player Two: {p2_Score}')
self.p1.learn(move1, move2)
self.p2.learn(move2, move1)
def play_game(self):
print("Game start!")
for round in range(3):
print(f"Round {round + 1}:")
self.play_round()
print("Game over!")
if __name__ == '__main__':
game = Game(RandomPlayer(), RandomPlayer())
game.play_game()
The problem is when I run the code it doesn't update players scores. As you can see in this picture of the output even though player two won rounds two and three, his score at the end of run three is still 1 instead of 2. I know that's because for each iteration of play_round function in the for loop inside the play_game function the values of p1_score and p2_score resets to zero but I do not know how to stop that from happening. Any suggestion will be greatly appreciated.
program output
The problem is that p1_Score and p2_Score are local variables in play_round. So every time you call this function, you get a new instance of these variables. Moreover, you always set
p1_Score = 0
p2_Score = 0
in play_round. So at the end of the function no score will ever be larger than 1.
To rememdy this, use self.p1_Score and self.p2_Score to make these variables instance variables and also move the 0-initialization into the __init__ function of the game class. Alternatively, make the score a class variable of the Player class.
My code is not working. It says required argument 'HumanMove'.
I pretty much don't understand what python is trying to tell me.
see the code below.
The computer is bugging at this line: HumanMove = self.HumanPlayer.move()
import random
#Create player class
class Player:
def move(self):
return 'rock'
def learn(self, my_move, their_move):
pass
#Create random player class
class RandomPlayer:
def __init__(self):
Player.__init__(self)
def move(self, RandomPlayerMove):
self.move = RandomPlayerMove
#use imported random function
RandomPlayerMove = random.randint(1,3)
#Computer choice is either rock, paper, or scissors
if RandomPlayerMove == ("Rock"):
print("The computer choses ROCK")
elif RandomPlayerMove == ("Paper"):
print("The computer choses PAPER")
else:
print("The computer choses SCISSORS")
#return value
return RandomPlayerMove
#Create human player class
class HumanPlayer:
def __init__(self):
Player.__init__(self)
def move(self, HumanMove):
return HumanMove
##class that remembers what move the opponent played last round
class ReflectPlayer:
def __init__(self, ReflectPlayer):
Player.__init__(self)
self.ReflectPlayer = ReflectPlayer
#def move
def move(self, move):
self.move = move
def getmove(self, move):
return self.move
#define cycleplayer class that remembers what move it played last round,
# and cycles through the different moves.
class CyclePlayer:
def __init__(self, CyclePlayer):
Player.__init__(self)
self.CyclePlayer = CyclePlayer
self.human_player_history = {} # stores the frequency of human player
moves
for move in moves:
self.human_player_history[move] = 0
def move(self, max_move):
max_move = max(self.human_player_history.items(), key=lambda elem:
elem[1])[0]
if max_move == 'rock':
return 'paper'
if max_move == 'scissors':
return 'rock'
if max_move == 'paper':
return 'rock'
def beats(one, two):
return ((one == 'rock' and two == 'scissors') or
(one == 'scissors' and two == 'paper') or
(one == 'paper' and two == 'rock'))
#Create game class
class Game:
def __init__(self, HumanPlayer, RandomPlayer):
self.HumanPlayer = HumanPlayer
self.RandomPlayer = RandomPlayer
def play_round(self):
HumanMove = self.HumanPlayer.move()
RandomPlayerMove = self.RandomPlayer.move()
print(f"HumanPlayer: {HumanMove} RandomPlayer: {RandomPlayerMove}")
self.HumanPlayer.learn(HumanMove, RandomPlayerMove)
self.RandomPlayer.learn(RandomPlayerMove, HumanMove)
if beats(HumanMove, RandomPlayerMove):
print("HumanPlayer wins this round")
self.HumanPlayer.score += 1
elif beats(RandomPlayerMove, HumanMove):
print("RandomPlayer wins this round")
self.RandomPlayer.score += 1
else:
print("It's Tie, Play again!")
print(f"Scores, HumanPlayer: {self.p1.score} RandomPlayer:
{self.p2.score}")
def move(self, HumanMove):
^^^^^^^^^
return HumanMove
You defined move with the parameter HumanMove. When you call the method you must supply an argument for that parameter.
These are the instructions: This program should be written using a menu driven interface. It should contain at least 6 functions, as follows (you can have more if you think you need others). You should choose descriptive function names to properly describe their function (follow the convention for properly naming functions). Just to be clear, you should NOT have functions called function1, function2, etc. Replace the names below with your own function names in your code.
When I run it, I get an error code saying "expected an indented block" for the line if comp(==1 and user ==3).
Please let me know what's wrong, thanks!
#import random module
import random
#main function
def main():
#program message
print("Rock, Paper, Scissors Game")
#initializing variables that would hold choices of user and computer
comp = 1
user = 1
while comp == user:
print("Enter your choice in range from 1 to 3")
#prompt user to enter choice
user = int(input("Your choice: "))
#randomly assign choice to computer
comp = random.randint(1,3)
#display choice of computer
print("Computer Choice : ",comp)
#display game drawn message, when same choices
if (comp == user):
print("Game Drawn. Select again")
#calling function to decide winner
winner (comp, user)
#winner function
def winner(comp, user):
#rock and scissor choice
if(comp == 1 and user ==3):
print("Computer win")
print("The rock smashes scissor")
elif(comp == 3 and user ==1):
print("User win")
print("The rock smashes scissor")
else:
#paper and rock choice
if(comp == 1 and user == 2):
print("User win")
print("The paper wraps rock")
elif (comp == 2 and user ==1):
print("Computer win")
print("Scissors cut paper")
elif (comp == 2 and user == 3):
print("User win")
print("Scissors cut paper")
else:
print("Invalid selection")
#calling main function
main()
Besides the answer from Nathaniel Ford, your if-elif-else indendation is wrong at some places as well.
if (condition):
print "hi"
elif (condition):
print "hi again"
else:
print "hi again vol3"
This is the correct way to indendent if-elif-else conditions.
The problem is with the previous code line:
def winner(comp, user):
def is defining a function, and expects that function to have a body. Because you back the indentation out to the top level, the def body has nothing (not even a pass), and thus won't compile.
But note that isn't your only indentation problem. The definition of main prints one line print("Rock, Paper, Scissors Game"), and then sets some variables and... quits. Because the indentation of while comp == user: backs out a level, it doesn't exist inside the main definition. This a problem with pretty much every new block of your code. You should read up how Python structures code with indentation.