I have this program that i have been working on
which plays rock paper scissors game with the user.

'''play a game of Rock, Paper, Scissors'''
from random import randint 

def firstChooserWins( chooserChoice, otherChoice ): 
    #print chooserChoice, otherChoice 

    if (chooserChoice == "Rock" and otherChoice == "Scissors") or \ 
       (chooserChoice == "Paper" and otherChoice == "Rock") or \ 
       (chooserChoice == "Scissors" and otherChoice == "Paper"): 
        return True 
    else: 
        return False 

def playGame(): 
    choice = { 1:"Rock", 2:"Paper", 3:"Scissors" } 

    while True: 
        playerPick = int(raw_input(""" 
Enter choice: 
0 : Quit 
1 : Rock 
2 : Paper 
3 : Scissors 

Your choice : """)) 

        if playerPick == 0: 
            break 

        if playerPick not in choice.keys(): 
            print "Invalid choice" 
            continue 

        playerChoice = choice[playerPick] 
        computerChoice = choice[randint(1,3)] 

        print "You chose %s, the computer chose %s" % ( playerChoice, computerChoice ) 

        if firstChooserWins( playerChoice, computerChoice ): 
            print "You win!" 
        else: 
            print "You lose!" 

        print "Bye!"
def main(): 
    playGame()
main()

but i need to modify it to so it contains a "best of x" loop
then for it to stop as soon as the user or the COM has won

Everytime i think i have the right logic or statements it either crashes or doesnt work correctly

Any suggestions??

Your 'playgame()' def doesn't actually return anything. Why not return a 1 for win or a 0 for loose. Then, in your main() function, use:

### Main Script

wins = 0
games = 0

while 1:
    result = playgame()

    if result == 1:
        win += 1
        pass

    games += 1

    if result == 'exit':
        break

    continue
    # Continue to loop until 'playgame()' returns the string 'exit'

print '''Game over.
Results:
Wins: %s
Games: %s
''' % (wins, games)

sys.exit()

Get the idea?

I have this program that i have been working on
which plays rock paper scissors game with the user.
but i need to modify it to so it contains a "best of x" loop
then for it to stop as soon as the user or the COM has won

Everytime i think i have the right logic or statements it either crashes or doesnt work correctly

Any suggestions??

Here is some fixing, it keeps the user choose to quit by zero, you must modify to accommodate the logic of choosing how many games and finishing accordingly.

You can take out multiple return values and use your own style. I do hate C:ism of main() as main body of code.

You have not noticed the situation when choices are the same.

'''play a game of Rock, Paper, Scissors'''
from random import randint 

def firstChooserWins( chooserChoice, otherChoice ): 
    #don't use \ in the end of condition use extra parenthesis

    if ((chooserChoice == "Rock" and otherChoice == "Scissors") or
       (chooserChoice == "Paper" and otherChoice == "Rock") or
       (chooserChoice == "Scissors" and otherChoice == "Paper")): 
        return True 
    else: 
        return False 

def playGame(): 
    choice = { 1:"Rock", 2:"Paper", 3:"Scissors" } 


    you=computer=0
    while True: 
        playerPick = int(raw_input(""" 
Enter choice: 

0 : Quit

1 : Rock 
2 : Paper 
3 : Scissors 

Your choice : """)) 

        if playerPick == 0:  
            return you,computer

        if playerPick not in choice.keys(): 
            print "Invalid choice" 
            continue 

        playerChoice = choice[playerPick] 
        computerChoice = choice[randint(1,3)] 
        
        print "You chose %s, the computer chose %s" % ( playerChoice, computerChoice )
        print

         
        if firstChooserWins( playerChoice, computerChoice ): 
            print "You win!"
            you+=1
        else:
           ## choices were same or computer chose better
            print "You lose!"
            computer+=1
        print    
        print "Situation"
        print
        print "\tYou     :",you
        print "\tComputer:",computer
        print


## Sorry, but I hate this style.
## def main(): 
##    playGame()
## main()

you,computer=playGame() ## use multiple return values to little show off ;-)
print
if you>computer:
    print "You won!"
elif you==computer:
    print "Games were equal:"
else:
    print "You lost!"
    
print "\tYou     :",you
print "\tComputer:",computer
print
print "Bye!"

How about this data structure instead. Your code is very short. Sometimes it pays to start to write again from beginning. I corrected it myself and the changes were really many.

Tony

import random
## alternative data structure demonstration
win = { "Rock":"Scissors","Paper":"Rock","Scissors":"Paper" }
choices = ["Scissors","Paper","Rock"]

for i in range(10):
    ch = random.choice(choices)
    print "I chose %s, please choose %s." % (ch, win[ch])

Edited 6 Years Ago by pyTony: n/a

## Sorry, but I hate this style.
## def main():
## playGame()
## main()

I agree with Tony, using the 'C' style of code, while acceptable, only adds lines and brings nothing to the table.

Unlike 'C' programming, you can run actual Python code from the main body, you don't have to define functions and call them just to get results. I would suggest only using functions/subroutines (same thing, different names) for processes that are done again and again. Otherwise, if it's code that's only executed once, put it in the main body.

I agree with Tony, using the 'C' style of code, while acceptable, only adds lines and brings nothing to the table.

Unlike 'C' programming, you can run actual Python code from the main body, you don't have to define functions and call them just to get results. I would suggest only using functions/subroutines (same thing, different names) for processes that are done again and again. Otherwise, if it's code that's only executed once, put it in the main body.

There are advantages in this style

def main():
    ....

if __name__ == "__main__":
    main()

You can change completely the effect of your program by modifying only the last line. This is very useful when you're extending, debugging or testing your code. You cannot do this with code at script level.

Edited 6 Years Ago by Gribouillis: n/a

You can change completely the effect of your program by modifying only the last line. This is very useful when you're extending, debugging or testing your code. You cannot do this with code at script level.

That is true and I've used that method, however, I find it to be better used in longer, more complex programs, not in the short ones such as this.

That is true and I've used that method, however, I find it to be better used in longer, more complex programs, not in the short ones such as this.

I would think that beginners can stay with their first programs with the style of Python helloworld

print "hello world!"

I agree that using if __name__ == "__main__": is useful.
That stops the execution when importing the code to other programs.
Then usually after that I put interactive loop for testing the module or processing of the sys.argv for command line use.

I would maybe put some interactive loops to seperate function/procedure, if the program has also command line argument checking. I would however try to have code that I really want results from as even it is not good to rely on global state before calling some functions, sometimes it is so much more practical.

I have seen that statement about uncluttering the main routines code to only initializing/object creation and call is good for the performance as local variable access is faster than globals. That looks at lest sometimes not to prove true from my measurements. I think I start a thread of that today or tomorrow.

Edited 6 Years Ago by pyTony: n/a

That is true and I've used that method, however, I find it to be better used in longer, more complex programs, not in the short ones such as this.

I would have to agree to that.
I think much of the code commonly put in a main function should be just placed in the module-level. That would simplify things for small programs.

You can change completely the effect of your program by modifying only the last line. This is very useful when you're extending, debugging or testing your code. You cannot do this with code at script level.

If you want to use this style of programming then you should use function names more descriptive than "main". It is indeed irritating when you are looking at someone else's code to check what is being run first, and finding a single, orphaned "main()", and then having to hit the page up button until you find the actual code that should have been where the language design designates.

Edit: Anyone want to submit a PEP to throw an error if "main" is used as a function name.

Edited 6 Years Ago by woooee: n/a

If you want to use this style of programming then you should use function names more descriptive than "main". It is indeed irritating when you are looking at someone else's code to check what is being run first, and finding a single, orphaned "main()", and then having to hit the page up button until you find the actual code that should have been where the language design designates.

Edit: Anyone want to submit a PEP to throw an error if "main" is used as a function name.

hm, I guess the PEP would be rejected. I like the name main() precisely because it doesn't mean anything: It's the place where I write the code that I would otherwise write at module level, but I put it in a main function because I anticipate that sooner or later I will need to run some other code to test the program, say test_func(), and I can comment or uncomment one of these lines

if __name__ == "__main__":
    # main()
    test_func()

A good PEP would be to replace if __name__ == "__main__": by something that looks better. I suggest we unite or efforts to suggest a new keyword main in a PEP and write instead

if main:
    play_game()

A side effect would be the impossibility of a function called main.

Edited 6 Years Ago by Gribouillis: n/a

Hey, why not just store it in a string and eval() it?

_main = eval("__name__ == '__main__'")

if _main:
    main()

Edited 6 Years Ago by hondros: n/a

I wrote a small module main.py . You would write only

import main
main(play_game)

Here it is

# main.py
"""
Module main.py

This module contains a replacement for the 2 lines syntax

if __name__ == "__main__":
    my_function(arg, k=arg)

This is replaced by

import main
main(my_function, arg, k=arg)

The effect is the same. You can also use

import main
if main:
    my_function(arg, k = arg)
"""

import types

class Main(types.ModuleType):
    def __init__(self, *args, **kwd):
        types.ModuleType.__init__(self, *args, **kwd)
        self.__dict__.update(globals())
    def __call__(self, func, *args, **kwd):
        if self:
            return func(*args, **kwd)
    def __nonzero__(self):
        import inspect
        frame = inspect.currentframe()
        try:
            name = frame.f_back.f_globals["__name__"]
        finally:
            del frame
        return name == "__main__"
    __bool__ = __nonzero__

import sys
sys.modules["main"] = Main("main")

Edited 6 Years Ago by Gribouillis: added the __nonzero__ feature

If you want this kind of behaviour why not just stick with convention?

Make the program module and do:

from mygame import mygame
mygame(maxplays=4)
from mygame import mygame_test as mygame
mygame(maxplays=4)

Total change for testing: type 'mygame_test as' in the command which is in history list of my editor. Or maybe this is the case of difficulty of python to forget imported modules and I should use 'reload' or some similar command (I do not know)?

Edited 6 Years Ago by pyTony: n/a

If you want this kind of behaviour why not just stick with convention?

Make it the program module and do:

from mygame import mygame
mygame(maxplays=4)
from mygame import mygame_test as mygame
mygame(maxplays=4)

Because you need 2 files. The idea of __name__ == "__main__" is that the same file can be used as a module or as a script.

Because you need 2 files. The idea of __name__ == "__main__" is that the same file can be used as a module or as a script.

Program mygame would have normal separation for main part, which process the command line, which are not executed when importing the module. I do not talk of making another file, I suggested usage from python command line for testing.

But the program could keep the normal main part, and no need to do c main-functions.

My idea is opposite: argv processing belongs to main body of module, not to some function of the module, which get imported as function when testing.

I do not have, however programmed any very big project with python. I have only started to learn to use basic profiling. 'unittest's etc are still unexplored territory for me.

My testing has been

  1. write alternative for the hottest function in my code
  2. put another function beside old version: myfunc2 instead of myfunc.
  3. Search and replace myfunc to myfunc2.
  4. Run the program file ignoring the usage message from argv processing (close command window+F5, or F5 from the code window in IDLE)
  5. Do some calling to my function under testing from python editors command line (using functions that call it, it directly)

Tony

Edited 6 Years Ago by pyTony: n/a

Program mygame would have normal separation for main part, which process the command line, which are not executed when importing the module. I do not talk of making another file, I suggested usage from python command line for testing.

But the program could keep the normal main part, and no need to do c main-functions.

My idea is opposite: argv processing belongs to main body of module, not to some function of the module, which get imported as function when testing.

I do not have, however programmed any very big project with python. I have only started to learn to use basic profiling. 'unittest's etc are still unexplored territory for me.

My testing has been

  1. write alternative for the hottest function in my code
  2. put another function beside old version: myfunc2 instead of myfunc.
  3. Search and replace myfunc to myfunc2.
  4. Run the program file ignoring the usage message from argv processing (close command window+F5, or F5 from the code window in IDLE)
  5. Do some calling to my function under testing from python editors command line (using functions that call it, it directly)

Tony

I agree with you that we don't need a C-like main function, and also that the above discussion doesn't apply to structured tests in a big project, but, from my experience, when you write code at module level and you start modifying your program, you always end up putting the code in a function because it gives you control over when exactly that code is executed, so why not put it in a function in the first place ?

The discussion about __name__ == "__main__" above, is mainly concerned with the situation when you're writing a small script from scratch and you're in a fast phase of edit-run-edit-test-change this-run-change that, etc. :)

Edited 6 Years Ago by Gribouillis: n/a

Any way to edit the subject of the thread or add to it?

Or cross post it to start new thread, replies to new thread?

Sorry newbie question, but I want to know for future when discussion goes so wildly of the topic.

Tony

Any way to edit the subject of the thread or add to it?

Or cross post it to start new thread, replies to new thread?

Sorry newbie question, but I want to know for future when discussion goes so wildly of the topic.

Tony

I don't think there is a rule. I think it's worth starting a new thread if there's going to be python code in it.

i like the code that was written below

'''play a game of Rock, Paper, Scissors'''
from random import randint

def firstChooserWins( chooserChoice, otherChoice ):
    #don't use \ in the end of condition use extra parenthesis

    if ((chooserChoice == "Rock" and otherChoice == "Scissors") or
       (chooserChoice == "Paper" and otherChoice == "Rock") or
       (chooserChoice == "Scissors" and otherChoice == "Paper")):
        return True
    else:
        return False

def playGame():
    choice = { 1:"Rock", 2:"Paper", 3:"Scissors" }


    you=computer=0
    while True:
        playerPick = int(raw_input("""
Enter choice:
0 : Quit
1 : Rock
2 : Paper
3 : Scissors
Your choice : """))
        
        if playerPick == 0:
            return you,computer
        
        if playerPick not in choice.keys():
            print "Invalid choice"
            continue
        
        playerChoice = choice[playerPick]
        computerChoice = choice[randint(1,3)]
        
        print "You chose %s, the computer chose %s" % ( playerChoice, computerChoice )
        print

        
        if firstChooserWins( playerChoice, computerChoice ):
            print "You win!"
            you+=1
        else:
            ## choices were same or computer chose better
            print "You lose!"
            computer+=1
        print
        print "Situation"
        print
        print "\tYou :",you
        print "\tComputer:",computer
        print

        
## Sorry, but I hate this style.
## def main():
## playGame()
## main()

        
you,computer=playGame() ## use multiple return values to little show off ;-)
print
if you>computer:
    print "You won!"
elif you==computer:
    print "Games were equal:"
else:
    print "You lost!"
print "\tYou :",you
print "\tComputer:",computer
print
print "Bye!"

but i still need the loop of "best of x " to finish the question off

any suggestions?

I did the remarks and small corrections, but you seemed not have read my remark:

What happens when computer choose Scissors and player chooses Scissors

Better to start with this my succestion of data structure. Solution is very simple to make from this.

Here my demonstration from previous post again:

How about this data structure instead. Your code is very short. Sometimes it pays to start to write again from beginning. I corrected it myself and the changes were really many.

Tony

import random
## alternative data structure demonstration
win = { "Rock":"Scissors","Paper":"Rock","Scissors":"Paper" }
choices = ["Scissors","Paper","Rock"]

for i in range(10):
    ch = random.choice(choices)
    print "I chose %s, please choose %s." % (ch, win[ch])

Edited 6 Years Ago by pyTony: Better datastructure for rock, paper, scissors.

This article has been dead for over six months. Start a new discussion instead.