[Tutor] Crazy craps problem

Steven D'Aprano steve at pearwood.info
Sun Oct 9 08:42:46 CEST 2011


col speed wrote:
> Hi again, Once more I've come up with a problem I can't explain. It must be
> something simple, but I can't work it out.
> The part of the script that is causing the problem is as follows:
> 
> 
> def point(num):
>     while True:
>         raw_input("Roll")

You ask the user for input, but don't do anything with their answer. Is 
that deliberate?


>         uno, dos = random.choice(dice), random.choice(dice)
>         three = uno+dos

It is confusing to have a variable called "three" which isn't equal to 
three. Likewise for "uno" and "dos", especially for Spanish or Italian 
speakers.


>         print "{0} + {1} = {2}".format(uno, dos, three)
>         print "Point is {0}. You scored {1}.".format(num, three)
>         if three == num:
>             return "win"

What happens if the caller passes 7 as the argument to point?


>         if three == 7:
>             return "lose"
>         else:
>             print "Try again."
> 
> What I have tried to do is - simulate dice throws, if the total is the same
> as originally thrown, return from the function(this works). If I throw a 7,
> I also want to return(this does not work as you can see from this sample
> output:


I cannot confirm that behaviour. When I try it, it works as expected: if 
you throw seven, it breaks out of the loop and you lose immediately.

I've tried that a couple of times, but because the scores are random, it 
takes a while. So I monkey-patched the game for testing purposes:


Kids! Don't do this at home! Monkey-patching is bad and wrong! <wink>


 >>> class MonkeyPatchedRandom:
...     scores = [6, 1, 3, 4, 5, 6, 2, 1, 1, 3]
...     index = -1
...     def choice(self, arg):
...             self.index += 1
...             return self.scores[self.index]
...
 >>> random = MonkeyPatchedRandom()
 >>> point(3)
Roll
6 + 1 = 7
Point is 3. You scored 7.
'lose'
 >>>


As you can see, if you happen to roll 7 on the first go, it exits the 
loop as expected.


[...]
> Point is 4. You scored 7.
> You have lost! You have $100 left.

There is nothing in the point() function that could possible print "You 
have lost". There is obviously some other code that you aren't showing us.


> As you can see, after throwing a 7, it just continues. It only returns after
> throwing a second 7.
> 
> 1. I know it's bad form to print from a function, I'll change it later.

A better way of stating this is that you should separate *interface* 
from *implementation*: printing messages to the user is part of the 
interface, and actually comparing dice rolls and deciding whether you 
have won or lost is part of the implementation, so they should be in 
separate functions.


> 2. I've tried the second if statement using "elif".
> 3. I've tried omitting the "three" variable and just using "uno" + "dos".
> 4. I've used "uno" and "dos" because I use "one" and "two" in another part
> of the script(outside and after the function definition), although they
> shouldn't be affected in any way.

Local variables are local. You don't need to fear that variables "one" 
and "two" inside function A will clash with variables inside function B 
(unless you declare them as global!). So don't worry about having every 
variable in every function have a unique name.

More importantly, though, it is confusing to name a variable "one". One 
what? Better names would be "roll_one", "score_one", "dice_a", or even 
"a" and "b" -- at least they are *generic* names and you won't fool the 
reader into expecting that variable two == 2.



-- 
Steven



More information about the Tutor mailing list