Reputation: 770
I'm still considering myself a programming newbie (my reputation is largely because of gamedev.SE), and as such I've run into a problem I can't solve on my own.
I have a function that takes a specified number of dice and rolls them, and returns the result. However, if it happens to roll the highest value available, eg 6 on a 6-sided die, it removes the die in question and rolls two new dice in its place instead. It's working as intended, but I have a problem with implementing another part that's necessary: keeping track of number of 1's rolled, and specifically any 1's rolled in the initial dice.
from random import randint
def roll_die(number, sides=6):
results = []
for dice in range(number):
roll = randint(1, sides)
if roll == sides:
#rolling two new dice instead
results.append(roll_die(2, sides))
else:
results.append(roll)
return sum(results)
I'm also unsure whether storing the results in a list and then summing it is the best way to do it, but I suppose I'll never reach large enough number of dice to be worried about that.
How can I keep track of the first dice rolled? When I say "first" I mean in the initially specified number to be rolled, before any new dice are added due to rolling sixes.
Upvotes: 0
Views: 4064
Reputation: 61615
You (and the other answer) are making this much too complicated.
Don't roll new dice immediately. Tally up how many new dice there are to be rolled and roll them once you've done your book-keeping.
Don't build up a list of everything that was rolled. You don't need it. Roll the initial dice, gather statistics, and then recurse to roll more dice.
Avoid writing explicit loops to accumulate data. Python knows how to accumulate data. Just tell it what you want to end up with in the list (via a list comprehension).
Don't make several recursive calls. One will do. Think about how you would do it with physical dice: you pull out the sixes all together, and then double them up and reroll.
from random import randint
def roll_dice(count, sides=6):
if count == 0: return (0, 0) # we need to guard against infinite recursion.
initial = [randint(1, sides) for die in range(count)]
initial_mins = initial.count(1)
initial_maxes = initial.count(sides)
# Add up all the dice that weren't maximum.
subtotal = sum(result for result in initial if result != sides)
# Recurse to re-roll the maxed-out dice.
ignored, reroll = roll_dice(2 * initial_maxes, sides)
return (initial_mins, subtotal + reroll)
Note that the recursive call returns a number of initial ones, which we ignore, because we only care about ones rolled the first time through. We unpack the recursive result and keep the interesting value, i.e. the total for the recursively re-rolled dice.
We could also do it iteratively, and only add up the ones on the first iteration:
from random import randint
def roll_dice(count, sides=6):
initial_mins = None
result = 0
while count:
dice = [randint(1, sides) for die in range(count)]
if initial_mins == None: initial_mins = dice.count(1)
result += sum(result for result in dice if result != sides)
count = 2 * dice.count(sides) # number to roll the next time through.
return (initial_mins, result)
Note how the None
sentinel value is used to ensure that we set the initial_mins
the first time through and then skip it every other time. This is cleaner than using an "impossible" integer value such as -1. Embrace dynamic typing. :)
Upvotes: 2
Reputation: 3049
have a second array maybe original = []
and in the roll == sides
part of the if append a sides
in the else
append roll
. you could then return [sum(results), original]
. in your if roll == sides:
you would then have to do something like results.append(roll_die(2,sides)[0])
in answer to your list question you could just add the value of the roll to an integer each roll then return that.
An example:
from random import randint
def roll_die(number, sides=6):
results = []
ones = 0
for dice in range(number):
roll = randint(1, sides)
if roll == sides:
#rolling two new dice instead
results.append(roll_die(2, sides)[0])
else:
results.append(roll)
if roll == 1:
ones += 1
return sum(results), ones
Upvotes: 2