So I made a dice rolling simulator in python, and while it does everything that I want it to I was told I could implement lists or a dictionary and it would be "better" code. I have tried adding both to my code and am completely lost. If any of you could help/show me that would be awesome. Here's my code, thanks so much.
from random import randint
print ""
die_amount = raw_input(">How many dice would you like to roll?: " )
die_amount = int(die_amount)
print ""
print "\t %s die are being rolled:" % die_amount
def dieroll(die_amount):
one = 0
two = 0
three = 0
four = 0
five = 0
six = 0
for i in range(1, die_amount+1):
roll = randint(1,6)
print "\t You rolled: %s" % roll
if roll == 1:
one +=1
elif roll == 2:
two +=1
elif roll ==3:
three +=1
elif roll == 4:
four +=1
elif roll == 5:
five+=1
elif roll == 6:
six +=1
print """
One's rolled: %s
Two's rolled: %s
Three's rolled: %s
Four's rolled: %s
Five's rolled: %s
Six's rolled: %s
""" % (one, two, three, four, five, six )
return [one, two, three, four, five, six]
dieroll(die_amount)
2 Answers 2
A Counter data structure does exactly what you are trying to do.
from collections import Counter
c = Counter()
for i in range(die_amount):
roll = randint(1,6)
c[roll] += 1
Or, even easier:
c = Counter(randint(1,6) for i in range(die_amount))
c[1] then contains the number of times 1 was rolled etc.
To print out the roll counts, you can use
for number, count in c.iteritems():
print "{}'s rolled: {}".format(number, count)
A Counter is basically a Python dictionary with a default value of zero. This makes it particularly suitable for counting how many objects occur in a list, for instance.
There are several reasons why this approach works better than keeping a separate variable for each count.
If you wanted to have a hundred-sided dice, you would have to define 100 separate variables. That's much more error prone.
It's, in principle, much faster. Having six different variables necessitates looping through them with a series of if-statements. Imagine you roll a six. You will have to evaluate five different if-statements until you get to
if roll == 6. By contrast, the counter uses a hash table, soc[roll]takes the same amount of time, regardless of how many rolls you make.
This begs the question: how can you know when you should be using a collection as opposed to a set of variables? The rule of thumb is that if a set of objects are different instances of the same thing, and we intend to use each object in exactly the same manner, they probably belong in a collection. In this case, a roll of 1 or a roll of 4 is essentially identical as far as the program flow is concerned. We will always treat them identically. They should therefore be kept in a collection.
5 Comments
return Counter(randint(1,6) for i in range(die_amount)). I suggest moving the print statements to a separate function (that way, you can re-use your die roll function in different programs without cluttering up your output).1's rolled: 0 ... Is that not what you want -- you may want to read about Python's format statement (docs.python.org/2/library/stdtypes.html#str.format )? In general, you can iterate through elements in a dictionary (or a counter) with a for loop like for key, value in c.iteritems(): #do something with key and value . You should be able to modify this to print however you like.If you want an answer that more closely matches your original implementation, but uses a list instead, here is a replacement for dieroll():
def dieroll(die_amount):
rolls = [0] * 6
for i in range(die_amount):
roll = randint(1,6)
print "\t You rolled: %s" % roll
rolls[roll-1] += 1
print """
One's rolled: %s
Two's rolled: %s
Three's rolled: %s
Four's rolled: %s
Five's rolled: %s
Six's rolled: %s
""" % tuple(rolls)
return rolls
python -c "import this"from the shell to read The Zen of Python.