Rayfd3s
Rayfd3s

Reputation: 51

python function random cycling if statements

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

Answers (5)

Totem
Totem

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

1.618
1.618

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

Luka Rahne
Luka Rahne

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

Adam Smith
Adam Smith

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

Eric Renouf
Eric Renouf

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

Related Questions