Reputation: 51
I'm making a rock paper scissor game and have run into a problem with the decisioncycle()
. What I'm trying to do is ask the user to input a choice in usercycle()
, have the computer generate a random choice in gamecycle()
, then determine who won the round and keep track of each result with a win and loss count. It seems to be deciding when to work at random.
import random
class rpsgame:
rps= ["rock", "paper","scissors"]
wincount=0
losecount=0
def usercycle(self):
userchoice = input("rock, paper, scissor.....")
print("SHOOT")
return userchoice
def gamecycle(self):
computerchoice = random.choice(rpsgame.rps)
return computerchoice
def decisioncycle(self):
if rpsgame.usercycle(self) == rpsgame.rps[0] and rpsgame.gamecycle(self) == rpsgame.rps[1]:
print("paper beats rock, you lose!")
rpsgame.losecount +=1
elif rpsgame.usercycle(self) == rpsgame.rps[1] and rpsgame.gamecycle(self) == rpsgame.rps[0]:
print("paper beats rock, you win!")
rpsgame.wincount+=1
elif rpsgame.usercycle(self) == rpsgame.rps[0] and rpsgame.gamecycle(self) == rpsgame.rps[2]:
print("rock beats scissors, you win!")
rpsgame.wincount+=1
elif rpsgame.usercycle(self) == rpsgame.rps[2] and rpsgame.gamecycle(self) == rpsgame.rps[0]:
print("rock beats scissors, you lose!")
rpsgame.losecount+=1
elif rpsgame.usercycle(self) == rpsgame.rps[1] and rpsgame.gamecycle(self) == rpsgame.rps[2]:
print("scissors beats paper, you lose!")
rpsgame.losecount+=1
elif rpsgame.usercycle(self) == rpsgame.rps[2] and rpsgame.gamecycle(self) == rpsgame.rps[1]:
print("scissors beats paper, you win!")
rpsgame.wincount+=1
elif rpsgame.usercycle(self) == rpsgame.gamecycle(self):
print("it's a tie!!!")
print("wins {}, losses {}".format(rpsgame.wincount, rpsgame.losecount))
while True:
rg = rpsgame()
rg.usercycle()
rg.gamecycle()
rg.decisioncycle()
I think my problem is in the decisioncycle(). this is my first shot at a class as the game was working with global variables, but I read here that that is a bad practice to carry out for the future.
Upvotes: 5
Views: 182
Reputation: 7369
I think this could actually be simplified. There are some mistakes, and they look like they are due to a simple unfamiliarity with classes. Take a look here:
class RpsGame:
# create a game loop. Let's try a while loop
# also, let's try using a dict to make comparisons easier
def play(self):
rps = {'rock':'scissors', 'paper':'rock', 'scissors':'paper'}
score = 0
# lets just say player must win 3 or lose 3 to end the game
while -3 < score < 3:
# ask user for their choice just once here, for instance
user = raw_input("Rock, paper or scissors: ").lower()
# and check the input is valid
# get the computer choice with random
# then find the winner and adjust score
# when score reaches -3, computer wins etc.
# comparisons could go like:
if com == rps[user]:
score += 1
elif user == rps[com]:
score -= 1
self.game_over(score)
def game_over(self, score):
if score == -3:
result == "You win"
else:
result == "You lose"
print "%s!!" % result
# We would start by instantiating the game
game = RpsGame()
# And then calling the play method
game.play()
I would go and have more of a read about classes and the usage of 'self' if I were you also.
Upvotes: 1
Reputation: 1765
I think you should make a separate function for determining the winner, and use a dict, rather than a 7-way if statement:
def who_won(player, computer):
rules = {"rock": "scissors", "paper": "rock", "scissors": "paper"}
if player == computer:
return None
if rules[computer] == player:
return "computer"
return "player"
It's probably a good idea to check for invalid input, but that should be done in the input function, rather than this function.
Upvotes: 1
Reputation: 10467
instead of evaluating each combination using numerous cycles you can use modular arithmetic.
lets say that you make mapping
"rock" => 0
"paper"=>1
"scissors" => 2
you can evaluate solution as
(A.number - B.number) % 3
if this result is 0, it is draw, if it is 1 that A won if 2 A is lost
Upvotes: 3
Reputation: 54223
Lots of funky things there, but I think the problem you're having is that you're passing self
to a function that doesn't (really) take an argument as input.
class TestClass(object):
def some_method(self):
return random.choice(['rock', 'paper', 'scissors'])
def make_choice(self):
return self.some_method(self)
# raises TypeError
A method's classes are AUTOMATICALLY given the instance it belongs to as the first argument. If you try and pass that again, it fails.
That said, I think your class should look something like:
class Roshambo(object):
ROCK = 'rock'
PAPER = 'paper'
SCISSORS = 'scissors'
OPTIONS = [ROCK, PAPER, SCISSORS]
def get_user_input(self):
choice = input("r/p/s? ").lower()
if choice.startswith('r'): choice = self.ROCK
elif choice.startswith('p'): choice = self.PAPER
elif choice.startswith('s'): choice = self.SCISSORS
else:
# what do we do now?
pass # for now
return choice
def get_computer_input(self):
return random.choice(self.OPTIONS)
def start(self):
# get input ONCE...
user_choice = get_user_input()
computer_choice = get_computer_input()
if user_choice == ROCK and computer_choice == ROCK:
# tie
# etc....
Then instantiate
game = Roshambo()
And run
game.start()
Upvotes: 0
Reputation: 14520
You are asking for a new user input in each condition. You probably want to read it just once and then compare it each time like
user_choice = self.usercicle()
game_choice = self.gamecycle()
if(user_choice == self.rps[0] and game_choice == self.rps[1]):
print "Paper beats rock, you lose!"
self.losecount += 1
elif( user_choice...
and so forth
Upvotes: 2