1

I've been learning through an online course and I was trying to come up with ideas for things I could create to "test" myself as it were so I came up with a rock paper scissors game. It was working well so I decided to try and add a way of keeping track of your score vs the computer. Didn't go so well.

Here's what I have:

from random import randint

ai_score = 0
user_score = 0

def newgame():
    print('New Game')
    try:
        while(1):
            ai_guess = str(randint(1,3))
            print('\n1) Rock \n2) Paper \n3) Scissors')
            user_guess = input("Select An Option: ")

            if(user_guess == '1'):
                print('\nYou Selected Rock')

            elif(user_guess == '2'):
                print('\nYou Selected Paper')

            elif(user_guess == '3'):
                print('\nYou Selected Scissors')

            else:
                print('%s is not an option' % user_guess)

            if(user_guess == ai_guess):
                print('Draw - Please Try Again')
            elif (user_guess == '1' and ai_guess == '2'):
                print("AI Selected Paper")
                print("Paper Beats Rock")
                print("AI Wins!")
                ai_score += 1
                break
            elif (user_guess == '1' and ai_guess == '3'):
                print("AI Selected Scissors")
                print("Rock Beats Scissors")
                print("You Win!")
                user_score += 1
                break
            elif (user_guess == '2' and ai_guess == '1'):
                print("AI Selected Rock")
                print("Paper Beats Rock")
                print("You Win!")
                user_score += 1
                break
            elif (user_guess == '2' and ai_guess == '3'):
                print("AI Selected Scissors")
                print("Scissors Beats Paper")
                print("AI Wins!")
                ai_score += 1
                break
            elif (user_guess == '3' and ai_guess == '1'):
                print("AI Selected Rock")
                print("Rock Beats Scissors")
                print("AI Wins!")
                ai_score += 1
                break
            elif (user_guess == '3' and ai_guess == '2'):
                print("AI Selected Paper")
                print("Scissors Beats Paper")
                print("You Win!")
                user_score += 1
                break
            else:
                pass
                break

    except KeyboardInterrupt:
        print("\nKeyboard Interrupt - Exiting...")
        exit()

#1 = Rock, 2 = Paper, 3 = Scissors


def main():
    while(1):
        print("\n1) New Game \n2) View Score \n3) Exit")
        try:
            option = input("Select An Option: ")

            if option == '1':
                newgame()   
            if option == '2':
                print("\nScores")
                print("Your Score: " + str(user_score))
                print("AI Score: " + str(ai_score))
            elif option == '3':
                print('\nExiting...')
                break
            else:
                print('%s is not an option' % option)
        except KeyboardInterrupt:
            print("\nKeyboard Interrupt - Exiting...")
            exit()


main()

I read somewhere that global variables can work but are generally frowned upon. Not sure why but then I can't say they're =0 so couldn't get that to work. Putting the ai_score and user_score in the newgame() doesn't work because it sets it to 0 every time you re run. Any help would be much appreciated.

As a quick extra note, the second

else:
   print('%s is not an option' % option)

in main() always seems to execute and always says "1 is not an option" and I have no idea why it does that. I would assume something to do with while loops but I need those to keep it running so an explanation of why and how to fix would be great. At the end of the day, I'm just here to learn more.

benten
  • 1,995
  • 2
  • 23
  • 38
bobvader2001
  • 11
  • 1
  • 5
  • Make a dictionary with `key:value` pairs of the items and what they beat, it'll make comparison easier, and you won't have to assign numbers – Andrew Sep 08 '16 at 19:04
  • If you want you could make a class and set the score as a class variable where the methods (newgame) would update that class variable. In main you could just ask what the score of the class variable is for that object. Would that be acceptable? – MooingRawr Sep 08 '16 at 19:06
  • Which version of python are you using? – Brendan Abel Sep 08 '16 at 19:16
  • @MooingRawr I didn't ask the question. – Brendan Abel Oct 05 '16 at 23:59

3 Answers3

2
from random import randint

class newgame():

    ai_score = 0
    user_score = 0

    def __init__(self):
        self.ai_score = 0
        self.user_score = 0

    def playgame(self):
        print('New Game')
        try:
            while(1):
                ai_guess = str(randint(1,3))
                print('\n1) Rock \n2) Paper \n3) Scissors')
                user_guess = input("Select An Option: ")

                if(user_guess == '1'):
                    print('\nYou Selected Rock')

                elif(user_guess == '2'):
                    print('\nYou Selected Paper')

                elif(user_guess == '3'):
                    print('\nYou Selected Scissors')

                else:
                    print('%s is not an option' % user_guess)

                if(user_guess == ai_guess):
                    print('Draw - Please Try Again')
                elif (user_guess == '1' and ai_guess == '2'):
                    print("AI Selected Paper")
                    print("Paper Beats Rock")
                    print("AI Wins!")
                    self.ai_score += 1
                    break
                elif (user_guess == '1' and ai_guess == '3'):
                    print("AI Selected Scissors")
                    print("Rock Beats Scissors")
                    print("You Win!")
                    self.user_score += 1
                    break
                elif (user_guess == '2' and ai_guess == '1'):
                    print("AI Selected Rock")
                    print("Paper Beats Rock")
                    print("You Win!")
                    self.user_score += 1
                    break
                elif (user_guess == '2' and ai_guess == '3'):
                    print("AI Selected Scissors")
                    print("Scissors Beats Paper")
                    print("AI Wins!")
                    self.ai_score += 1
                    break
                elif (user_guess == '3' and ai_guess == '1'):
                    print("AI Selected Rock")
                    print("Rock Beats Scissors")
                    print("AI Wins!")
                    self.ai_score += 1
                    break
                elif (user_guess == '3' and ai_guess == '2'):
                    print("AI Selected Paper")
                    print("Scissors Beats Paper")
                    print("You Win!")
                    self.user_score += 1
                    break
                else:
                    pass
                    break

        except KeyboardInterrupt:
            print("\nKeyboard Interrupt - Exiting...")
            exit()

    #1 = Rock, 2 = Paper, 3 = Scissors


def main():
    game_object = newgame()
    while(1):
        print("\n1) New Game \n2) View Score \n3) Exit")
        try:
            option = input("Select An Option: ")

            if option == '1':
                game_object.playgame()
            elif option == '2':
                print("\nScores")
                print("Your Score: " + str(game_object.user_score))
                print("AI Score: " + str(game_object.ai_score))
            elif option == '3':
                print('\nExiting...')
                break
            else:
                print('%s is not an option' % option)
        except KeyboardInterrupt:
            print("\nKeyboard Interrupt - Exiting...")
            exit()


main()

Classes are wonderful. __init__ is the constructor for this class. It basically makes the object instant for the class and sets the variable to what you want. game_object = newgame() makes the class object and stores it into game_object. To get the class variable of the game_object, we use game_object.ai_score. Since you made a class object it's class variables are still in scope of the object you made, even though it might be outside of your function. Generally, if I need to use a variable outside of a function, and is tempted to use Global, I make a class instead. There are some cases where you wouldn't want this, but personally I haven't come across one. Also you might want to look into like what the comments were saying about using dictionary as options. Any other questions?

Edit:

To answer your new question about print('%s is not an option' % option) always running, is because in your code you had if option == '1': and then if option == '2': You want the option 2 to be elif. I fixed it in my code. If statements are in blocks. since you started a new if, the else didn't check first first if to see if it's a valid option. It was out of it's scope in a sense. So since your code was basically saying is option equal to 1? is it equal to 2 or 3 or anything else? notice these are two different questions?

MooingRawr
  • 4,901
  • 3
  • 24
  • 31
  • I was only watching a super basic course like completley from scratch 0 python knowledge and it didn't even mention classes xD I didn't even know they were a thing in Python. Also what's with the double underscores either side of init? I've seen it a few times before and i'm not sure what it means – bobvader2001 Sep 08 '16 at 19:52
  • http://stackoverflow.com/questions/8689964/why-do-some-functions-have-underscores-before-and-after-the-function-name TL;DR: trailing underscore is to avoid keywords... `class_` is usable. Leading underscore get's more tricky, `__hello` is "private" but not really. It's not like java or c# private variables. It does the same but you can still access them outside of the class. I know it's confusing don't worry about it, there are more people who explains it better than I do. – MooingRawr Sep 08 '16 at 20:00
  • `__init__` is set up that way to be a "magic methods" you don't mess with them. http://stackoverflow.com/questions/2657627/why-does-python-use-magic-methods – MooingRawr Sep 08 '16 at 20:00
  • @flint his first question did get answer by my answer. He was asking about accessing a variable outside of his method, which can be solved by using class. Yes it introduce something new to him but hes learning right? He edited his question now to something else. And of course I ran my/his/her code. I was answering the question that was presented, now that it changed my answer will too. – MooingRawr Sep 08 '16 at 20:02
  • Thanks for all you're help dude. You're awesome! :D Looks like I need to do some research into classes :P – bobvader2001 Sep 08 '16 at 20:15
  • @bobvader2001 if you feel the question has been answer to your liking, feel free to accept one of the three answers given. (the check mark on the question you liked the most) – MooingRawr Oct 06 '16 at 13:22
1

It seems that the variable option is not '1', right ? Well, that's because the function input does not return a character string, but an integer. You can see this by adding a little trace in this program.

print (option, type (option))

after a line where the variable option has been set.

This will tell you of what type is the variable option, in that case it is an integer. So first, you need to replace the comparisons against strings (like if option == '1': by comparisons against integers, that is : if option == 1:.

As for the second question : variables declared or assigned inside of a function exist for the scope of that function only. If you need to use a variable inside a function that has outer scope, it should be redeclared inside the function as global (even if they are "frowned upon" -- and there are good reasons for this). At the beginning of def newgame(): you need to declare again your global variables : global ai_score, user_score. You can also use classes to get familiar with object oriented programming and write nicer code. There is an other error left in this program, but I'm sure you'll find out.

Flint
  • 1,651
  • 1
  • 19
  • 29
0

At least one problem is this: your main has if...if...elif...else. The second if probably needs to be an elif. Tip: When you have a flow-of-control problem, put print statements inside each control branch, printing out the control variable and everything else that might possibly be relevant. This tells you which branch is being taken -- in this case, which branches, plural.

You don't say exactly what the problem was with keeping score, but I imagine it was an exception along the lines of variable referenced before assignment. If so, you should put "global ai_score" somewhere at the top of the function. What's going on is that Python can, but doesn't like to, recognize variables outside a function that are being used inside the function. You have to push a little. Consider:

>>> bleem = 0
>>> def incrbleem():
...   bleem += 1
...
>>> incrbleem()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in incrbleem
UnboundLocalError: local variable 'bleem' referenced before assignment
>>> def incrbleem():
...   global bleem
...   bleem += 1
...
>>> bleem
0
>>> incrbleem()
>>> bleem
1

By the way, your code isn't bad at all, for a newbie. I've seen much, much worse! For what it's worth, I don't think global variables are bad for a small, throw-away program like this. Once you have two programmers, or two threads, or two months between work sessions on the program, globals can definitely cause problems.

D-Von
  • 416
  • 2
  • 5
  • I see. Thanks for your help. I'd fixed exactly the same problems with the elif in exactly that point when I first wrote it but I obviously accidentally undid it and didn't think to look there again lol. I'll try and add your code when I next get a chance as programming is more of a hobby for me right now around studying because unfortunately my college doesn't offer computer science :( – bobvader2001 Sep 08 '16 at 19:59