11
\$\begingroup\$

I recently began to dabble into the programming world and wrote a Dice Simulator Program. How do I know that I'm writing Good Code? In the sense, is it something similar to how a major Software Developing company would produce code for real problems.

""" This Program is Dice Simulator that produce an Output from 1-6
everytime the User presses Enter. In order to close the Program,
the User has to type "Exit" into the console.
"""

#Imports the random module to generate the random Integers
import random

#Initial Designer Print Statements
print(" Hi! Welcome to Dicey!")
print ("""

   .-------.    _______
  /   o   /|   /\\      \\
 /_______/o|  /o \\  o   \\
 | o     | | /   o\\______\\
 |   o   |o/ \\o   /o     /
 |     o |/   \\ o/  o   /
 '-------'     \\/____o_/

  """)


exit=False      #Set True When User types "Exit" into the console
count=0         #Count to keep track of Iterations/Dice rolls

#The Input is obtained below
enter=(input(("Press Enter to Roll (or) Type 'Exit' to Close. 
\n\n")).lower())

#Condition to check wether the user wants to Exit the program without 
#Rolling the Dice

if (enter=="exit"):
    exit=True

#Checks for Enter and Produces a random integer using the random module
while(enter=="" or not exit):
  dice_number=random.randint(1,6)
  count = count + 1
  print(f"{count}>You got a {dice_number}")
  enter=(input("Press Enter to Roll Again! \n").lower())

#If User inputs "Exit", Close the program.
if (enter=="exit"):
    exit=True

#If the User inputs anything else other than "Exit" Roll the dice again.
elif(enter is not ""):
    print("\n")
    continue
\$\endgroup\$
  • 8
    \$\begingroup\$ How come you can see faces 3 and 4 at the same time on your dice? \$\endgroup\$ – Mathias Ettinger May 19 '18 at 18:56
  • 4
    \$\begingroup\$ To elaborate the comment from @MathiasEttinger the opposing sides of a dice always sum to 7. 1 and 6. 2 and 5. 3 and 4. So you'll never see 3 and 4 at the same time. \$\endgroup\$ – Mast May 19 '18 at 21:31
  • \$\begingroup\$ What an absolutely delightful and lovely question. I would go so far as to say that if you can write half-good code, with an attitude like that,you have already won. \$\endgroup\$ – Sentinel May 19 '18 at 23:45
  • \$\begingroup\$ @MathiasEttinger The first number is more like an iteration or the number of times you have rolled the dice. The number following "You Got..." is the actual dice value. \$\endgroup\$ – Antony John May 20 '18 at 0:46
  • 2
    \$\begingroup\$ Mathias is referring to your ASCII art of the dice. Obviously they aren't the real results of your code, they just aren't a picture of real dice (since real dice wouldn't have 3 and 4 on touching faces). It's a silly mistake, but since you took the effort to add the graphic, and since you want to convey that this is a program that gives reliable results like a dice roll, it would probably be a good idea for those dice to actually have valid values showing. Touching faces will never add up to 7. \$\endgroup\$ – Anthony May 20 '18 at 6:51
13
\$\begingroup\$

Here are a few suggestions on how to simplify and format your code.

Break directly from the loop

In your loop construct there really is no point in keeping track of exit. In addition exit is used by Python, and it is better to not reuse these things becuase it can be confusing. Instead something like:

while True:
    if input(msg).lower() == 'exit':
        break

In addition this shows how you really only need one input statement. Instead the message for input can be set as needed.

Avoid extra parens

In all three of these cases you have an extra set of outer parens.

if (enter=="exit"):
while(enter=="" or not exit):
enter=(input("Press Enter to Roll Again! \n").lower())

Use descriptive variable names

As an example you have a variable named count, that I think would be more descriptive as roll_number. Additionally dice_number might be more descriptive as dice_value.

Use the programming language to its fullest.

Python has a bunch of nifty operators that can make code cleaner.

count = count + 1

Can be written as:

count += 1

which makes it more explicit that the variable is being incremented, and not just assigned.

PEP8

You should consider formatting your code in accordance with pep8. This is important when sharing code, as the consistent style makes it much easier for other programmers to read your code. There are various tools available to assist in making the code pep8 compliant. I use the PyCharm IDE which will show pep8 violations right in the editor.

One PEP8 note that I will highlight is to not use what are relatively obvious comments. With clean code and descriptive variable names the code will often be as descriptive as the comments.

Reconstructed code:

""" This Program is Dice Simulator that produce an Output from 1-6
everytime the User presses Enter. In order to close the Program,
the User has to type "Exit" into the console.
"""

import random

print(" Hi! Welcome to Dicey!")
print("""

   .-------.    _______
  /   o   /|   /\\      \\
 /_______/o|  /o \\  o   \\
 | o     | | /   o\\______\\
 |   o   |o/ \\o   /o     /
 |     o |/   \\ o/  o   /
 '-------'     \\/____o_/

  """)

roll_number = 0
msg = "Press Enter to Roll (or) Type 'Exit' to Close.\n\n"
while True:
    if input(msg).lower() == 'exit':
        break

    roll_number += 1
    dice_value = random.randint(1, 6)
    print(f"{roll_number}> You got a {dice_value}\n")

    msg = "Press Enter to Roll Again! \n"
\$\endgroup\$
  • 4
    \$\begingroup\$ while input(msg).lower() != 'exit': is a simpler way of writing the exit condition. \$\endgroup\$ – flornquake May 19 '18 at 19:22
  • \$\begingroup\$ Adding to the note about comments, my general rule of thumb is that comments shouldn't say what the code is doing, because as Stephen says, the code tells us that. Comments should say why the code is doing it, because that's the part which a maintainer doesn't know. \$\endgroup\$ – Graham May 20 '18 at 0:05
  • \$\begingroup\$ @StephenRauch Should I try writing more Pythonic Single lined code, or code that anyone can read? Also Thanks a million for your help! \$\endgroup\$ – Antony John May 20 '18 at 0:59
  • 2
    \$\begingroup\$ @AntonyJohn, the answer is YES! In my opinion Pythonic single liners are more readable if the complexity is kept in check. But you asked about anyone. That term will not include my mother, who while extremely talented, knows nothing about programming. So you would need to better define your audience included in the term anyone. If anyone is those who know Python, and those who want to know Python, then I will stick the YES answer. Cheers. \$\endgroup\$ – Stephen Rauch May 20 '18 at 1:05
  • \$\begingroup\$ @StephenRauch I had an illusion that writing readable code with excess comments is what a software company does to reduce the burden of Code reviewers. I do have a draft filled with single-liners but had a trade-off between optimization and readability. Will follow-up on your advice! :) \$\endgroup\$ – Antony John May 20 '18 at 7:01
6
\$\begingroup\$

How do I know that I'm writing Good Code?

That is a very broad question that can not be answered here. You can start by reading this classic book: Clean Code: A Handbook of Agile Software Craftsmanship (at least you can tackle some chapters that can be understood for your case)

In the sense, is it something similar to how a major Software Developing company would produce code for real problems?

Unfortunately no; especially when it comes to games development where competition is too rude and various advanced technical skills from different aspects and fields are required (this means more specialists are involved)

The minimum you can think about at this level is that your code is not reusable as it is. To remedy to this, you should at least re-design it in terms of functions. So if we start from @Rauch's answer, we could do something like this:

import random


def simulate_dice():
   """This function is Dice Simulator that produce an Output from 1-6
   everytime the User presses Enter. In order to close the Program,
   the User has to type "Exit" into the console. 
   """
   print(" Hi! Welcome to Dicey!")
   print("""

    .-------.    _______
   /   o   /|   /\\      \\
  /_______/o|  /o \\  o   \\
  | o     | | /   o\\______\\
  |   o   |o/ \\o   /o     /
  |     o |/   \\ o/  o   /
  '-------'     \\/____o_/

   """)
   roll_number = 0
   msg = "Press Enter to Roll (or) Type 'Exit' to Close.\n\n"
   while True:
       if input(msg).lower() == 'exit':
           break

       roll_number += 1
       dice_value = random.randint(1, 6)
       print(f"{roll_number}> You got a {dice_value}\n")

       msg = "Press Enter to Roll Again! \n"


if __name__ == '__main__':
   simulate_dice()

You may read about if __name__ == "__main__":

\$\endgroup\$
  • \$\begingroup\$ Would you really have the interface integrated with the logic and call it reusable? I would lose my mind if I got a dice simulator for my application and calling it returned a welcome message and exiting required passing it exit. \$\endgroup\$ – Anthony May 20 '18 at 7:07
  • \$\begingroup\$ Even with this function design, the code can not be used if you integrated a GUI because you will need radical code modification around this function, and surely you will need other helper functions too. And sure, this function needs more work than how it is now, but the OP says he just started coding, so suggesting advanced approaches may not be helpful for his case, but he can keep learning @Anthony \$\endgroup\$ – Billal Begueradj May 20 '18 at 7:21
  • \$\begingroup\$ I was just thinking a basic separation of concerns would be a good initial lesson. Even if it's just having simulate dicey as one function and simulate_dice another function that returns random.randint(1, 6). \$\endgroup\$ – Anthony May 20 '18 at 7:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.