4
\$\begingroup\$

I wrote this dice game as beginner practice. This is working code, but I would like to improve it by adding more functions. Though, since I am still a beginner, I don't know how, so help would be appreciated!

import random

print('Time to go gambling! Press ctrl + enter, or RUN (the big red button), to roll!')
dice = random.randint (1,20)
print(str(dice))
count = 1
while dice != 20:
  dice = random.randint (1,20)
  print(str(dice))
  count +=1
if count == 1:
  print('It took you ' + str(count) + ' try to get a 20... average.')
else:
  print('It took you ' + str(count) + ' tries to get a 20... embarrassing.')
New contributor
cyan is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
\$\endgroup\$
4
  • \$\begingroup\$ For some reason, every time I try to say hello on the first line of my question, it deletes it... \$\endgroup\$ Commented Dec 15 at 18:18
  • 5
    \$\begingroup\$ There is no need to say "hello", and that text would be edited out anyway. \$\endgroup\$ Commented Dec 15 at 18:30
  • 9
    \$\begingroup\$ "I would like to improve it by adding more functions. ..., I don't know how" please can you clarify if you're asking how to improve the existing code, or are you asking for ideas on what next to do? \$\endgroup\$ Commented Dec 15 at 18:33
  • \$\begingroup\$ Hello and welcome to the Stack Exchange network. Please note well that sites like this are not providing a discussion forum; we don't want introductions etc. in posts because the point of the post is not for you to socialize with us, but to persist as a landmark for others to find useful answers and advice later. Please read Why do clear, accurate, appropriately detailed posts still get edited? on the network-wide meta site for details. \$\endgroup\$ Commented 20 hours ago

5 Answers 5

9
\$\begingroup\$

First Impressions

You print out a message, 'Time to go gambling! Press ctrl + enter, or RUN (the big red button), to roll!', but the program does not wait for any user input (and there is no RUN button). This is a bit disconcerting. If these are features that you plan on adding later, then your code might comment on that. But it should not be putting this message out prematurely.

It is also not clear at this stage of coding what the actual game you are playing is and how it would work with a user. If you are looking for suggestions for what you should be adding to this code, we need to know a but more about the game.

Read the PEP 8 – Style Guide for Python Code

You should familiarize yourself with this guide, particularly the following areas:

  1. Comments
  2. Docstrings
  3. Indentation

Coding Suggestions

You have print(str(dice). This can be just print(dice) since print will automatically convert each argument to its string representation before outputting the value.

When count is 1, the print statement should be:

print('It took you 1 try to get a 20... average.')

In all other cases you should have:

print('It took you', count, tries to get a 20... embarrassing.')

print will by default output each argument separated by a space. That is, doing your own string concatenation is completely unnecessary. You could also use an f-string:

print(f'It took you {count} tries to get a 20... embarrassing')
\$\endgroup\$
6
  • 1
    \$\begingroup\$ I was using OneCompiler which has a red button titled "RUN". \$\endgroup\$ Commented Dec 15 at 19:11
  • 2
    \$\begingroup\$ So is that simply to start the script or for some other purpose? If it's to start the script the print statement will be executing only after you press the red button, so there is no point printing that message. \$\endgroup\$ Commented Dec 15 at 19:13
  • \$\begingroup\$ No, the program automatically runs once the tab opens. So, the user sees the instruction. \$\endgroup\$ Commented 2 days ago
  • \$\begingroup\$ "IDE" programs like OneCompiler are meant to help you with creating the code. They are not there for your user to run the code. Your code should be able to stand on its own (or at most, make use of a terminal where someone runs your code at the command line). \$\endgroup\$ Commented 20 hours ago
  • \$\begingroup\$ (My research is also telling me that OneCompiler is also in-browser, and specifically meant for Java... ???) \$\endgroup\$ Commented 19 hours ago
8
\$\begingroup\$

I would be inclined to make a function which acts as a generator to toss dice.

def toss_dice():
    while True:
        yield random.randint(1, 20)

We can now get our tossed dice until we roll a 20. It would also be an improvement to create a function to run a game, and then to ensure that function is only run if we're actually executing the file as a program, rather than importing it into another program.

import random

def toss_dice():
    while True:
        yield random.randint(1, 20)

def play_dice_game():
    count = 0
    
    for roll in toss_dice():
        print(f'{roll}')
        count += 1

        if roll == 20:
            break

    if count == 1:
        print(f'It took you 1 try to get a 20... average.')
    else:
        print(f'It took you {count} tries to get a 20... embarrassing')  

if __name__ == '__main__':
    play_dice_game() 
\$\endgroup\$
3
  • 1
    \$\begingroup\$ For a more advanced programmer, the generator could allow us to enumerate() the die rolls, and eliminate the need for separate counting. \$\endgroup\$ Commented 2 days ago
  • \$\begingroup\$ @TobySpeight building enumeration into the generator would be a bit awkward (since enumerate is meant to wrap an existing iterable) and make its purpose less clear. Better to use enumerate for the main loop: for count, roll in enumerate(toss_dice(), 1):. \$\endgroup\$ Commented 20 hours ago
  • \$\begingroup\$ @KarlKnechtel I suspect that is what he meant. :) \$\endgroup\$ Commented 19 hours ago
6
\$\begingroup\$

UX

When I run the code, I see this message printed first:

... Press ctrl + enter, or RUN (the big red button), to roll!

The message seems to indicate that I need to take action for the code to do something, but the code just runs automatically to completion. That is confusing to me. I think you should change or delete that message.

It can be replaced to show what the remaining output signifies (rolls of the dice).

Layout

The code uses 2-space indent, but it is easier to read and understand using the more common 4-space indentation. The black program can be used to automatically indent the code for you. It will also adjust whitespace around operators according to norms.

You should also add blank lines to separate sections of code. For example, add a blank line before and after the while loop.

Documentation

The PEP 8 style guide recommends adding docstring at the top of the code to summarize its purpose. For example:

"""
Dice roll game.

Add more details here...
"""

Simpler

This code:

print('It took you ' + str(count) + ' try to get a 20... average.')

is simpler using an f-string:

print(f'It took you {count} try to get a 20... average.')

You can change "try" to "tries" for improved grammar. You can also change the code to account for the case of one try.

Magic number

The number "20" is used in several places. You should assign it to a constant which can be used everywhere. The PEP 8 style guide recommends upper case for constant names:

MAX_VAL = 20

//...

dice = random.randint (1, MAX_VAL)

This also make the code more scalable to other maximum values.

\$\endgroup\$
1
\$\begingroup\$

Avoid repeating logic with better defaults

Instead of these three lines:

dice = random.randint (1,20)
print(str(dice))
count = 1

You can just initialize dice to 0 and count to 0 and let the while loop do the job for you.

Friendly messages

if count == 1:
  print('It took you ' + str(count) + ' try to get a 20... average.')
else:
  print('It took you ' + str(count) + ' tries to get a 20... embarrassing.')

Is it really that embarrassing to use two or more tries to get a 20 ? I think not. I would print the "average" message if there's around 18-22 tries, and possibly "embarrassing" if it takes more than that. But if so also include an "impressive!" message if it takes fewer tries than expected. Perhaps an idea for what to do next for you, to add a bunch of different "rating" strings (and do it in a clean way, of course!). You could even introduce something funny like checking if it's an odd number of tries and say "that's odd".

I would still argue against putting "embarrassing" in text facing the user, especially when it's not anything the user has control over.

\$\endgroup\$
0
\$\begingroup\$

Place for questions and studies

It’s good that you came to the Stack Exchange, even if you are an beginner. It will help you learn more about Python, and any other programming languages you want. It can be difficult at first, but keep looking for more information and you will get better over time. Look also at Stack Overflow, which is for codes with errors.

Another version of the code with explanations.

This is a version of your program with explanations about functions and details that are basic and you can learn, so read it slow, don't rush.

program_run = True
#Dont put 1-letter or 1-word names on variables,
#it will be harder to remenber what
# it does on the code.
#and use "_" between words,
try:
    #You use this function when knows this part
    # can raise an Exception, so you can try fix.
    #if you use an "try:", you need to use an "except:".
    import random
except ImportError:
    #There are many python defalt Exceptions, like:
    # ImportError, ValueError, OverflowError, and many others.
    print("Nescessary module(s) not found.\nNeeds: random.")
    program_run = False
    #This is something you can make, so if someone tries to run this code,
    # but doesn't have the nescessary modules,
    # the program dont sudenlly crash, and tells what modules it needs to run.

#allways try to make the functions up in the code, under the modules imported.
def dice_game_code(Dice_faces: int) -> int:
    #When creating an function, it's good you make like this:
    #   1. Name your function with an good explainer name.

    #   2. When putting an Parameter (Like the Dice_faces),
    #   its good to write the Type that this parameter
    #   needs to be. In this example, Dice_faces
    #   needs to be an integer.

    #   3. After the end of the () add an "-> 'return type'",
    #   telling the type of information this function returns.
    #   if it returns nothing:
    #   put "None"

    #   4. Right under, but into, the function, add an Docstring:
    #   This is an comment text explaining the Parameters, what returns,
    #   and what this function do.
    #   You can make this using """..."""
    """Code for the dice game.
    It runs till the dice is the same as the Dice_faces,
    wich is the max value it can get.

    Dice_faces: It's the total number of faces (in int Type) of the dice.

    Return: Returns the number of attempts needed to reach max value (in int Type)."""
    attempt = 0
    while True:
        dice = random.randint(1, Dice_faces)
        attempt += 1
        if dice == Dice_faces:
            #The "return" function is used on User functions to:
            #   1. To exit the function with value "None", when the
            #   "return" is alone.
            #   2. To exit the function with some information
            #   from inside the function. Like this example:
            return attempt
        print(f"{attempt}º attempt: {dice}")
if __name__ == "__main__":
    #This is an barrier that only alloys pass
    #when the actual program is running.
    #because, if you imports the dice_game_code()
    #to an different code, the entire program is read an ran.
    #but with this, only what is outside this indentation is read.
    if program_run:
        #Since the "program_run" has an boolean information,
        # the actuall variable is an boolean test.
        start_choice = input('Time to go gambling!\nPress [S]tart or [Q]uit!\n> ').lower().strip()
        #".lower()",  ".strip()", and ".upper()"
        # are some methods that you can use on strings, to:
        # 1. make all string lower-case
        # 2. removes characters in the string
        # (if let blank, it only removes all spaces in string)
        # 3. make all string upper-case
        if start_choice == "s":
            while True:
                #The dice_game_code() returns an value that i need outside,
                # so, to get this value, i need to put it into an variable.
                attempt = dice_game_code(20)
                # since i have put an Parameter on the function,
                # i need to give the information it needs to run.
                # otherwise it will raise an exception.
                end_text = "average." if attempt <= 5 else "embarrassing."
                #you can put If...else statements into variables and lists
                #to change then by the enviroment or set an rule to then.
                replay_choice = input(f"""It took you {attempt} attempt(s) to get 20... {end_text}
                \nWants to try again? (Y/N)\n> """).upper().strip()
                if replay_choice == "Y":
                    continue
                break
        print("\nBye!\n")

You can copy and paste this code to see it working.

here is the code with no comments, so its better to read the actual code:

program_run = True
try:
    import random
except ImportError:
    print("Nescessary module(s) not found.\nNeeds: random.")
    program_run = False
def dice_game_code(Dice_faces: int) -> int:
    """Code for the dice game.
    It runs till the dice is the same as the Dice_faces,
    wich is the max value it can get

    Dice_faces: It's the total number of faces (in int Type) of the dice.

    Return: Returns the number of attempts needed to reach max value (in int Type)."""
    attempt = 0
    while True:
        dice = random.randint(1, Dice_faces)
        attempt += 1
        if dice == Dice_faces:
            return attempt
        print(f"{attempt}º attempt: {dice}")
if __name__ == "__main__":
    if program_run:
        start_choice = input('Time to go gambling!\nPress [S]tart or [Q]uit!\n> ').lower().strip()
        if start_choice == "s":
            while True:
                attempt = dice_game_code(20)
                end_text = "average." if attempt <= 5 else "embarrassing."
                replay_choice = input(f"""It took you {attempt} attempt(s) to get 20... {end_text}
                \nWants to try again? (Y/N)\n> """).upper().strip()
                if replay_choice == "Y":
                    continue
                break
    print("\nBye!\n")
\$\endgroup\$
9
  • 3
    \$\begingroup\$ random is a built-in library, so why would import fail? The lib exists even in MicroPython. \$\endgroup\$ Commented 2 days ago
  • 2
    \$\begingroup\$ Use of whitespace/newlines in this code is rather suspect. \$\endgroup\$ Commented 2 days ago
  • 1
    \$\begingroup\$ @Unknown, not in the string literals, though you could use multi-line string literals, but rather in the code itself. \$\endgroup\$ Commented 2 days ago
  • 1
    \$\begingroup\$ If you are going to handle random not being imported, wouldn't it make more sense to exit the program there rather than set a flag that has to be checked later to prevent the rest of the program from being executed? \$\endgroup\$ Commented yesterday
  • 2
    \$\begingroup\$ You might get a better reception to your answers if you provided the observations about the code separately from the code. Alternate solutions by themselves are not considered good answers and may be down voted and or deleted by the community. I personally learned this the hard way by having several of my answers down voted. \$\endgroup\$ Commented yesterday

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.