views:

441

answers:

8

I'm working on a problem which uses a python class and has a constructor function to give the number of sides to one die and a function to roll the die with a random number returned based on the number of sides. I realize the code is very basic, but I'm having troubles understanding how to sum up the total of three rolled dice with different sides. Since a variable is passing the function instance what would be the best way to grab that value to add it up? Here is what I have.

*To clarify... I can get the totals of the roll1.roll_dice() to add up, but I have to show each roll individually and then the total of the three dice. I can do either one of those but not both.

class Die():

        def __init__(self, s = 6):
            self.sides = s
        def roll_die(self):
            x = random.randint(1,self.sides)
            return x

        roll1 = Die()   #Rolling die 1 with the default side of 6
        roll2 = Die(4)  #Rolling die 2 with 4 sides
        roll3 = Die(12) #Rolling die 3 with 12 sides

        print roll1.roll_die()  
        print roll2.roll_die()
        print roll3.roll_die()
+1  A: 

Since roll_die returns a value, you can add those values.

Try this.

roll1.roll_die() + roll2.roll_die()

What happens?

S.Lott
I guess I should have clarified... I can get the values of those rolls, but I have to show each of the rolls separately and then a total for the three rolls. So if I add up the rolls as you have done I can get a total, but not a value for each roll.
Jb
@jb: Update your question with additional information.
S.Lott
A: 

You can just sum the numbers. In case you want to sum the outcome of n rolls, consider adding this function to the class:

def sum_of_n_rolls(self, n)
    return sum(self.roll_die() for _ in range(n))

Also, consider renaming *roll_die* to just roll. It's obvious that it's not about rolling a rock, since the method is part of the class Die.


Edit: I now read you need to print intermediate rolls. Consider:

def n_rolls(self, n):
    return [self.roll_die() for _ in range(n)]

Now you can roll a 7-sided die 10 times:

rolls = Die(7).n_rolls(10)
print(rolls, sum(rolls))
Stephan202
+9  A: 

You can store the results in a list:

rolls = [Die(n).roll_die() for n in (6, 4, 12)]

then you can show the individual results

>>> print rolls
[5, 2, 6]

or sum them

>>> print sum(rolls)
13

Or, instead, you could keep a running total:

total = 0
for n in (6, 4, 12):
    value = Die(n).roll_die()
    print "Rolled a", value
    total += value
print "Total is", total

(edited to reflect the changes/clarifications to the question)

dF
+1 probably not what the class project requires :) Always loved messing with CompSci teachers heads.
David
This would work, although we have to "Create three dice, the first without stating the number of sides" so it takes the default from the constructor (6) rather than calling 6. Is there a way to pass an empty value in a list?
Jb
+2  A: 

I'm not sure exactly where you're confused. The simplest thing you need to do is separate the concept of a specific die you're going to roll (the object) with the action (rolling it). I would start here:

d6 = Die() #create die 1 with the default side of 6
d4 = Die(4) #create die 2 with 4 sides
d12 = Die(12) #create die 3 with 12 sides

roll1 = d6.roll_die()
roll2 = d4.roll_die()
roll3 = d12.roll_die()

print "%d\n%d\n%d\nsum = %d" % (roll1, roll2, roll3, roll1 + roll2 + roll3)

... and then get fancier with lists, etc.

Mike
My problem was that when I was recalling the instance I was getting a different sum than the dice I was rolling because it was summing up three different dice. I didn't think of the sum function... this is exactly what I needed. Sometimes the simplest things can be so tricky. Thanks.
Jb
Glad to help. (but I didn't mention sum(), someone else did...)
Mike
A: 

Guess I'd do something like this:

# Create dice
sides = [6,4,12]
dice = [Die(s) for s in sides]

# Roll dice
rolls = [die.roll_die() for die in dice]

# Print rolls
for roll in rolls:
    print roll

You can also combine a few of these steps if you like:

for num_sides in [6,4,12]:
    print Die(num_sides).roll_die()
Triptych
+3  A: 

It may also be useful to just store the last roll so you can get it whenever you want.

def __init__(self, s = 6):
    self.sides = s
    self.last_roll = None

def roll_die(self):
    self.last_roll = random.randint(1,self.sides)
    return self.last_roll
Trey Stout
+1: Change the state of the object.
S.Lott
A: 

If I understood you correctly you want a class attribute.

UPDATE: Added a way for automatically reseting the total

import random

class Die():
    _total = 0

    @classmethod
    def total(cls):
        t = cls._total
        cls._total = 0
        return t

    def __init__(self, s=6):
        self.sides = s

    def roll_die(self):
        x = random.randint(1,self.sides)
        self.__class__._total += x
        return x

roll1 = Die()   #Rolling die 1 with the default side of 6
roll2 = Die(4)  #Rolling die 2 with 4 sides
roll3 = Die(12) #Rolling die 3 with 12 sides

print roll1.roll_die()  
print roll2.roll_die()
print roll3.roll_die()
print Die.total()
print "--"
print roll1.roll_die()  
print roll2.roll_die()
print roll3.roll_die()
print Die.total()
Toni Ruža
Using a class attr for the total seems like a strange side effect. Especially in a game where two diff players roll the same set of dice. You would get weird side effects, plus you'd have to remember to reset it to zero.
Trey Stout
True, but thats not the use case Jb described (maybe he should clarify) and I don't agree that terms like "strange" or "side effect" are appropriate for describing this solution. BTW, the setting to zero could probably be automated by a getter.
Toni Ruža
Hmm. Thanks guys. I was also thinking about what chmod700 said. The next three die would also be summed up, where I would need it to be reset. Yes I should have clarified this. I play around with it.
Jb
I guess I just don't like using class variables for this sort of thing. A user of this class then has to remember every place they're being used to make sure he's not getting extra additions to his total. That's what I meant by side-effect.
Trey Stout
A: 

Let's get crazy :) (combined with my last answer as well)

class Die():
    def __init__(self, s = 6):
        self.sides = s
        self.last_roll = None

    def roll_die(self):
        self.last_roll = random.randint(1,self.sides)
        return self.last_roll

dice = map(Die, (6, 4, 12))
rolls = map(Die.roll_die, dice)

print rolls
print sum(rolls)
Trey Stout