Python cant call a function - python

I am developing a rock paper scissors on python and I am stuck.
I made a class that cycles between (rock, paper, and scissors ), I want the computer to know it's previous play.
for instance ( first round computer played rock, in the next round it should play paper)
but I don't know how to call the learn function to make it work
class Player:
def __init__(self):
self.score = 0
def move(self):
return 'rock'
def learn(self, my_move, their_move):
self.my_move = my_move
self.their_move = their_move
def beats(one, two):
return ((one == 'rock' and two == 'scissors') or
(one == 'scissors' and two == 'paper') or
(one == 'paper' and two == 'rock'))
class Game:
def __init__(self, p1, p2):
self.p1 = p1
self.p2 = p2
def play_round(self):
move1 = input("Pick something!\n")
move2 = self.p2.move()
print(f"Player 1: {move1} Player 2: {move2}")
self.p1.learn(move1, move2)
self.p2.learn(move2, move1)
if beats(move1, move2):
self.p1.score += 1
print ("You win")
print ("Human score = " + str(self.p1.score) + " " + "Computer score = " + str(self.p2.score) )
elif beats(move2,move1):
self.p2.score += 1
print ("Computer wins")
print ("Human score = " + str(self.p1.score) + " " + "Computer score = " + str(self.p2.score) )
else:
print ("Draw")
print ("Human score = " + str(self.p1.score) + " " + "Computer score = " + str(self.p2.score) )
def play_game(self):
print("Game start!")
for round in range(3):
print(f"Round {round}:")
self.play_round()
print("Game over!")
class human_player(Player):
def move(self):
return input("Pick something!\n")
class randomplayer(Player):
def move(self):
return random.choice(moves)
class repeat(Player):
def move(self):
return 'rock'
class cycleplayer(Player):
def move(self):
# calling my_move from the Player class
if self.learn.my_move == "rock" or "paper" or "scissors" :
return 'rock'
elif self.their_move == 'rock':
return "paper"
elif self.their_move == 'paper':
return "scissors"
elif self.their_move == 'scissors':
return "rock"
if HumanPlayer_choice == "cycle" :
game = Game(Player(), cycleplayer())
game.play_game()
This is the error I am getting.
Exception has occurred: AttributeError 'function' object has no
attribute 'my_move'
I know that I need to utilize the init function with the learn function to make it work but I not sure how.

The problem is on this line:
if self.learn.my_move == "rock" or "paper" or "scissors" :
learn function does not have an attribute named my_move. What you meant to do is probably
if self.my_move == "rock" or self.my_move == "paper" or self.my_move == "scissors" :
Note that you have to add self.my_move == before "paper" and "scissors"; otherwise it is evaluated like:
if (self.my_move == "rock") or ("paper") or ("scissors"):
and since non-empty strings are always evaluated as True, this if case is rendered useless.
As #DmitryErohin mentioned, there is a better way of achieving that without repeating yourself:
if (self.my_move in ("rock", "paper", "scissors")):
This is much less verbose and a lot more readable

There were a few problems in your code as far as I could follow. Take a look at the example below based on your code. There's some logic I could not follow so it may not behave exactly as you want. Suggestions:
as you just want to store the previous move for the cycle_player move, store it in the cycle object (instance) not on the Player
as the move method varies make it's implementation specific to a child class (e.g. human_player, random_player, cycle_player)
some methods are better as static rather than recreated in each instance methods
import random
class Player:
def __init__(self):
self.score = 0
class Game:
def __init__(self, p1, p2):
self.p1 = p1
self.p2 = p2
#staticmethod
def check_result(a, b): #Return win, draw, loose for a over b
if (a == b):
return 'draw'
if (a == 'rock' and b == 'scissors') or (a == 'scissors' and b == 'paper') or (a == 'paper' and b == 'rock'):
return 'win'
return 'loose'
def play_round(self):
#move1 = input("Pick something!\n")
move1 = self.p1.move()
move2 = self.p2.move()
print(f"Player 1: {move1} Player 2: {move2}")
result = Game.check_result(move1, move2) # a over b
if result == 'win':
self.p1.score += 1
print ("You win")
elif result == 'loose':
self.p2.score += 1
print ("Computer wins")
else:
print ("Draw")
print ("Human score = " + str(self.p1.score) + " " + "Computer score = " + str(self.p2.score))
def play_game(self):
print("Game start!")
for round in range(3):
print(f"Round {round + 1}:")
self.play_round()
print("Game over!")
class human_player(Player):
def move(self):
return input("Pick something!\n") #TODO validate input
class random_player(Player): #Option in game for computer to make random moves
def move(self):
return random.choice(["scissors","paper","rock"])
class repeat_player(Player): #Option
def move(self):
return 'rock'
class cycle_player(Player):
def __init__(self):
self.previous_move = None
super().__init__()
def move(self):
# calling my_move from the Player class
if self.previous_move is None :
next_move = 'rock'
elif self.previous_move == 'rock':
next_move = "paper"
elif self.previous_move == 'paper':
next_move = "scissors"
elif self.previous_move == 'scissors':
next_move = "rock"
self.previous_move = next_move
return next_move
#game = Game(human_player(), random_player())
#game = Game(human_player(), repeat_player())
game = Game(human_player(), cycle_player())
game.play_game()

Related

scissors paper stone game without the use of list in python

im new to this python program and was tasked to generate a game or scissors paper stone game in python without the use of a list. i have the function here as:
def getRandomShape():
Shape = random.randint(1, 3)
if Shape == 1:
print('Scissors'.upper())
elif Shape == 2:
print('Stone'.upper())
else:
print('Paper'.upper())
getRandomShape()
but whenever i call for the function, it says its not defined.
the error occurse at the possibleHands section where im unable to call for the function but able to at the bottom for the checkForWinner function call
here's the full program.
import random
print('welcome to scissors paper stone')
cpuScore = 0
playerScore = 0
tieScore = 0
possibleHands = getRandomShape(computerHand)
def getRandomShape(computerHand):
Shape = random.randint(1, 3)
if Shape == 1:
print('Scissors'.upper())
elif Shape == 2:
print('Stone'.upper())
else:
print('Paper'.upper())
def checkForWinner(playerHand, computerHand):
if(playerHand == 'Stone' and computerHand == 'Paper'):
print('you lost')
return 'cpu'
elif(playerHand == 'Stone' and computerHand == 'Scissors'):
print('you won')
return 'player'
elif(playerHand == 'Scissors' and computerHand == 'Paper'):
print('you won')
return 'player'
elif(playerHand == 'Scissors' and computerHand == 'Stone'):
print('you lost')
return 'cpu'
elif(playerHand == 'Paper' and computerHand == 'Scissors'):
print('you lost')
return 'cpu'
elif(playerHand == 'Paper' and computerHand == 'Stone'):
print('you won')
return 'player'
else:
print('its a tie. play again')
return 'tie'
while(playerScore != 3 and cpuScore != 3):
name = input('Please enter your name: ')
while True:
playerHand = (input('Round 1: '+str(name)+ ', please choose a shape:'))
if(playerHand == 'Scissors' or playerHand == 'Paper' or playerHand == 'Stone'):
break
else:
print('invalid input, case sensitive. Try again')
computerHand = random.choice(possibleHands)
print('your Hand: ', playerHand)
print('cpu Hand: ', computerHand)
results = checkForWinner(playerHand, computerHand)
if(results == 'player'):
playerScore += 1
elif(results == 'cpu'):
cpuScore += 1
else:
tieScore += 1
print('your score: ', playerScore, 'CPU: ', cpuScore, 'Ties: ', tieScore)
print('gg game over')
got this from a youtube tutorial
You must declare the function before its usage. On line 8 getRandomShape is called before its definition, so a NameError would occur.
What you can do is to put all the code that is not in a function, other than the import statements inside a main() function. And at the end you add:
if __name__ == ‘__main__’:
main()
When the program is called it would execute the main() function, and it would not matter if you put the function before or after others. The only thing that matters is you only call functions after they are already defined.
You can learn more about it here.
There are many more problems with this code, and this only fixes the NameError
that you are currently facing.

My input sometimes takes multiple times for it to go in the if statements

I am attempting to make a basic rock, paper, scissors game. When I input either rock, paper, or scissors, I sometimes have to enter the same thing multiple times for it to continue to the if statements. See code below:
# Rock, Paper, Scissors
player_total = 0
computer_total = 0
def get_computer_hand():
choice = randint(1, 3)
if choice == 1:
return "scissors"
elif choice == 2:
return "paper"
else:
return "rock"
def ask_user():
global player_total
global computer_total
player = input("Enter your hand (stop to stop): ")
if player == "stop":
print("Computer had ", computer_total, "points, you had ", player_total, " points.")
exit(0)
computer = get_computer_hand()
if player == "rock":
if computer == "paper":
return "win"
elif computer == "scissors":
return "lose"
else:
return "tie"
elif player == "paper":
if computer == "paper":
return "tie"
elif computer == "scissors":
return "lose"
else:
return "win"
elif player == "scissors":
if computer == "scissors":
return "tie"
elif computer == "paper":
return "win"
else:
return "lose"
def count_winner():
global player_total
global computer_total
player_total = 0
computer_total = 0
while True:
outcome = ask_user()
if outcome == "win":
print("You won that one.")
player_total += 1
elif outcome == "lose":
print("Computer won that one.")
computer_total += 1
count_winner()
I expect it to work the first time and to continue as usual, but I can't seem to figure out why it just asks "Enter your hand (stop to stop): " instead sometimes when I enter either rock, paper, or scissors.
This is happening because there is a tie happening between the computer and the user. This could be fixed by adding the end with the code of
else outcome == "tie":
print("You have tied with the Computer!")
computer_total += 1
player_total += 1
This would add a point to both sides and if you don't want that just delete the last two lines of my code

Input not read correctly, rock paper scissors lizard spock

as my homework (using codeskulptor.org) I put together a simple Rock-Paper-Scissors-Lizard-Spock 'game' in Python, where hard coded player's guesses were running the programme. Translation from name to number and other way round, random computer choice and printing... everything worked fine.
Then I tried to introduce input so that player gets to type their guess. However, the console prints only the log about wrong input but doesn't launch the rest of the programme if the input is actually correct... Tried various modifications, but I'm stuck... am I missing something obvious? Thanks!
import simplegui
import random
def get_guess(guess):
if guess == "rock":
return 0
elif guess == "Spock":
return 1
elif guess == "paper":
return 2
elif guess == "lizard":
return 3
elif guess == "scissors":
return 4
else:
print "Error guess_to_number:", guess, "is not a rpsls-element"
return
def number_to_name(number):
if number == 0:
return "rock"
elif number == 1:
return "Spock"
elif number == 2:
return "paper"
elif number == 3:
return "lizard"
elif number == 4:
return "scissors"
else:
print "Error number_to_name:", number, "is not in [0, 4]"
return
def rpsls(guess):
print
print "Player chooses", guess
player_number = get_guess(guess)
computer_number = random.randrange(5)
computer_choice = number_to_name(computer_number)
print "Computer chooses", computer_choice
diff_mod = (player_number - computer_number) % 5
if diff_mod == 0:
print "Player and computer tie!"
elif diff_mod == 1 or diff_mod == 2:
print "Player wins!"
else:
print "Computer wins!"
frame = simplegui.create_frame("GUI-based RPSLS", 200, 200)
frame.add_input("Enter guess for RPSLS", get_guess, 200)
frame.start()

Broken code, need help fixing

This code runs through properly once and then brings the error
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
paper
NameError: name 'paper' is not defined
I need the code to be able to run a game of rock, paper, lizard, spock to run 10 times showing a tally of the scores (as it goes and) at the end of the 10 (or the number of chosen) games.
Here is the code:
import random
numberofgames = raw_input("How many games do you want to play? ")
print "Please choose rock , paper , scissors , lizard, or spock (in lower case please)"
choice = raw_input("What do you choose? ")
player_choice = str(choice)
def name_to_number(name):
if name == "rock":
name = 0
return name
elif name == "spock":
name = 1
return name
elif name == "paper":
name = 2
return name
elif name == "lizard":
name = 3
return name
elif name == "scissors":
name = 4
return name
def number_to_name(number):
if number == 0:
number = "rock"
return number
elif number == 1:
number = "spock"
return number
elif number == 2:
number = "paper"
return number
elif number == 3:
number = "lizard"
return number
elif number == 4:
number = "scissors"
return number
try:
computer_choice = random.randrange(5)
player_number = name_to_number(player_choice)
print "Player choice is: " + player_choice
print "Computer choice is: " + number_to_name(computer_choice)
difference = (int(player_number) - computer_choice) % 5
draws = 0
playerwins = 0
computerwins = 0
if difference in [1, 2]:
print "Player wins!"
playerwins = playerwins + 1
elif difference == 0:
print "Player and computer tie!"
draws = draws + 1
else:
print "Computer wins!"
computerwins = computerwins + 1
print "Wins: " + str(playerwins) + "\n" + "Draws: " + str(draws) + "\n" + "Losses " + str(computerwins)
while playerwins + draws + computerwins <= numberofgames:
name_to_number()
except TypeError:
print "Sorry, please read the directions and type rock, paper, scissors, spock, or lizard in lowercase."
The code you posted raises TypeError: name_to_number() takes exactly 1 argument (0 given) because you call your name_to_number function without an argument.
Btw, here's a simpler version of that function:
name_to_number_dict = dict(rock=0, spock=1, paper=2,lizard=3,scissors=4)
def name_to_number(name):
if name not in name_to_number_dict:
raise ValueError("illegal name")
return name_to_number_dict[name]
Edit:
In fact you don't need such a function at all. A simpler approach might be the following:
import random
data = "rock", "spock", "paper", "lizard", "scissors"
def playgames():
tally = dict(win=0, draw=0, loss=0)
numberofgames = raw_input("How many games do you want to play? ")
numberofgames = int(numberofgames)
for _ in range(numberofgames):
outcome = playgame()
tally[outcome] += 1
print """
Wins: {win}
Draws: {draw}
Losses: {loss}
""".format(**tally)
def playgame():
choice = ""
while (choice not in data):
choice = raw_input("Enter choice (choose rock , paper , scissors , lizard, or spock):")
choice = choice.lower()
print "Player choice is:{}".format(choice)
player_number = data.index(choice)
computer_number = random.randrange(5)
print "Computer choice is: {}".format(data[computer_number])
difference = (player_number - computer_number) % 5
if difference in [1, 2]:
print "Player wins!"
outcome = "win"
elif difference == 0:
print "Player and computer tie!"
outcome = "draw"
else:
print "Computer wins!"
outcome = "win"
return outcome
playgames()

Rock, paper, scissors game. Writing a print statement that works

Here is my code:
from random import*
from myro import*
from math import*
def computerChoice():
computer = randint(0,2)
if (computer == 0):
choice = "rock"
elif(computer == 1):
choice = "paper"
else:
choice = "scissors"
return choice
def userGuess():
print " R = Rock"
print " P = Paper"
print " S = Scissors"
userChoice = raw_input("Enter R, P, or S: ")
return userChoice
def calculate(userChoice, choice):
userNameWins = 0
computerWins = 0
draws = 0
if(userChoice == "R" and choice == "paper"):
speak("scribbler wins")
computerWins = computerWins + 1
elif(userChoice== "R" and choice == "scissors"):
speak( "you win")
userNameWins = userNameWins + 1
elif(userChoice== "P" and choice == "rock"):
speak("you win")
userNameWins = userNameWins + 1
elif(userChoice== "P" and choice == "scissors"):
speak("scribbler wins")
computerWins = computerWins + 1
elif(userChoice == "S" and choice == "rock"):
speak("scribbler wins")
computerWins = computerWins + 1
elif(userChoice == "S" and choice == "paper"):
speak("you win")
userNameWins = userNameWins + 1
else:
speak("Draw")
draws = draws + 1
return userNameWins, computerWins, draws
def printResults(userNameWins, computerWins, draws)
# insert code for print statement
def main():
for x in range (5):
speak("Rock Papers Scissors ")
userChoice = userGuess()
choice = computerChoice()
calculate(userChoice,choice)
printResults (userNameWins, computerWins, draws)
I get an error when I try to define some variables and I don't know why.
I need a function that properly prints the results returned by calculate()
The part you're asking for is trivial. Since you didn't give us the desired output format, I'll guess at it, and hopefully you can fix it to match the way you want it to look:
def printResults(userNameWins, computerWins, draws)
print('user won {} times, computer won {} times, and players drew {} times'
.format(userNameWins, computerWins, draws))
However, your code isn't going to work, for at least two reasons.
First, you call this:
calculate(userChoice,choice)
… which returns the 3 values you want, but you never store them anywhere. In particular, you don't store them, or anything else, in variables named userNameWins, computerWins, and draws. So, this like will get a NameError:
printResults (userNameWins, computerWins, draws)
Second, you're looping 5 times over a function that, each time, returns a full set of values, but you're only calling printResults once, not 5 times. I'm not sure what you're intending here, but most likely, either you need to move printResults into the loop, or you need to add code that sums up the results across all the loops.
sorry about the wait but hopefully this solution is of help to you.
from random import randint
#from myro import *
choice = None
userChoice = None
userNameWins = 0
computerWins = 0
draws = 0
def computerChoice():
global choice
computer = randint(0,2)
if (computer == 0):
choice = "rock"
elif(computer == 1):
choice = "paper"
else:
choice = "scissors"
print "Scribbler selected " + choice
return choice
def userGuess():
global userChoice
print " R = Rock"
print " P = Paper"
print " S = Scissors"
userChoice = raw_input("Enter R, P, or S: ")
return userChoice
def calculate(userChoice, choice):
global userNameWins
global computerWins
global draws
if(userChoice == "R" and choice == "paper"):
print("scribbler wins")
computerWins = computerWins + 1
elif(userChoice== "R" and choice == "scissors"):
print( "you win")
userNameWins = userNameWins + 1
elif(userChoice== "P" and choice == "rock"):
print("you win")
userNameWins = userNameWins + 1
elif(userChoice== "P" and choice == "scissors"):
print("scribbler wins")
computerWins = computerWins + 1
elif(userChoice == "S" and choice == "rock"):
print("scribbler wins")
computerWins = computerWins + 1
elif(userChoice == "S" and choice == "paper"):
print("you win")
userNameWins = userNameWins + 1
else:
print("Draw")
draws = draws + 1
def printResults():
print "You won " + str(userNameWins) + " times"
print "Scribbler won " + str(computerWins) + " times"
print "There were " + str(draws) + " draws"
if (userNameWins > computerWins):
print "You win overall"
elif (userNameWins < computerWins):
print "Scribbler wins overall"
else:
print "It was a dead heat"
def main():
global userChoice
global choice
for x in range (5):
print ("Rock Papers Scissors ")
userChoice = userGuess()
choice = computerChoice()
calculate(userChoice,choice)
printResults ()
main()
I didn't have myro installed so I used print instead to display the results. Before you weren't saving the variables for the results anywhere so I made a global variable so that it can store the variables. Also I completed the printResults function.

Categories