[Tutor] The game of nim in python

Danny Yoo dyoo at hashcollision.org
Fri Apr 22 22:58:49 EDT 2016


On Fri, Apr 22, 2016 at 5:45 AM, Henderson, Kevin (GE Aviation, US)
<KevinM.Henderson at ge.com> wrote:
> Python to Jython.
>
> Can you help me with a Jython code for the Nim game?

If you can say more about what you're like help with, we can tailor
advice toward what you want.  I'll treat this as a quick-and-dirty
design review.


... ok, I see a lot of globals.  It might make sense to consider
modifying the functions that take in and produce values.


For example, your computer player:

> def removingStrawsComputer():
>     removedNumber=random.randint(1,3)
>     global strawsNumber
>     while removedNumber>strawsNumber:
>         removedNumber=random.randint(1,3)
>     strawsNumber-=removedNumber
>     return strawsNumber

essentially depends on the initial strawsNumber, and returns an
updated strawsNumber to represent how the computer is playing.



Rather than have it work on the 'strawsNumber' global directly, you
can pass in the value as an argument.

#######################################
 def removingStrawsComputer(strawsNumber):
     removedNumber=random.randint(1,3)
     while removedNumber>strawsNumber:
         removedNumber=random.randint(1,3)
     strawsNumber-=removedNumber
     return strawsNumber
#######################################


How would this change affect the rest of the program?  It would touch
callers of removingStrawsComputer, and in that case, that's the main
game() function.

It would change:


##########################################################
def game():
    while gameover==False:
        print("It's ",player2,"turn. The number of straws left: ",
removingStrawsComputer())
        ...
##########################################################

to:

##########################################################
def game():
    while gameover==False:
        currentStraws = removingStrawsComputer(currentStraws)
        print("It's ",player2,"turn. The number of straws left: ",
currentStraws)
        ...
##########################################################

I would argue that the revised version is better for readability
because it's more clear that we're calling removingStrawsComputer so
that we can change currentStraws.




The other thing that caught my eye is related to game() too. This line:

        print("It's ",player2,"turn. The number of straws left: ",
removingStrawsComputer())

Yes, we looked at this line earlier.  :P

I think this is too clever, believe it or not.  I'd recommend breaking
this out into two separate statements.

       currentStraws = removingStrawsComputer()
       print("It's ",player2,"turn. The number of straws left: ", currentStraws)

The reason is because the original is calling removingStrawsComputer()
for an essential side-effect, which is ok normally, except this is
being done in the context of a print statement.  That's the part that
can be error-prone.

Print statements are often added and removed to make things look
nicer.  I would think that commenting out a print statement would be
mostly harmless, for example, but in this case, it's *crucial* that we
don't in this situation, because it affects the state of the game.

In general, when using print(), avoid putting in side-effecting things
as arguments.  It's one of those code smells that a programmer learns
to avoid.


More information about the Tutor mailing list