Home » Guessing a number, but comments concerning

Guessing a number, but comments concerning

Solutons:


Welcome to the hell of comments, and personal taste. There are multiple answers to your core question that may be right:

  1. You have not commented enough.
  2. You have commented all the wrong things.
  3. You have commented too much.
  4. Your comments are in the wrong format.
  5. You are missing the formal comments.

To be clear though, nothing we can say will be in line with what your marks are based on, unless you can tell us why you were marked down… 😉


About Comments in general

OK, comments are supposed to make plain what the code does not tell us already.

Let me say that again.

Comments are supposed to make plain what the code does not tell us already.

Now, whether you are marked on that, or not, is a different story. I have found that the academic application of marks for comments is often contrary to the need for comments… particularly when the code is good code.

Good code seldom needs comments.

Let me say that again:

Good code seldom needs comments.

So, follow this logic through, and then follow the inverse back…

  1. Comments make plain what the code does not tell us already.
  2. Good code seldom needs comments.

thus….

  1. Good code seldom needs comments.
  2. Good code must make plain what the code does without the need for additional explanation.

Applied to your code

Let’s start at the top….

import java.util.*; //so I can use scanner

Now, if your code was:

import java.util.Scanner;

then it would not need the comment.

Your next comment is here:

  int max = 100; //sets limit on the random number generator

Well, that is, actually, not a horrible comment, or code. But, it could be better, if we gave it a decent name:

int randomGeneratorLimit = 100;

It would be even better if we made that magic number a constant:

private static final int RANDOM_GENERATOR_LIMIT = 100;

Now, no need for a comment at all.

Next up, this line:

  while (play) { //so game will restart after a win

Well, this one is interesting…. the comment is actually needed here because of the loop you are using.

If you convert this to a do-while loop, and use some functional extraction… then you can convert your code to a self-documenting, commentless block:

private static boolean playAgain() {
    System.out.print("Do you want to play again? ");
    String answer = input.nextLine();
    char firstLetter = answer.charAt(0);
    return firstLetter == 'y' || firstLetter == 'Y';
}

then you can use that function as follows:

do {

    ....... // game logic

} while (playAgain());

No need for a comment (or a play variable).

Similarly, you have the code:

     //so user can continue guessing until correct
     boolean win = false;  
     while (!win) {

This should be a do-while as well, and should look like:

do {
     ..... // game logic
} while (guess != numberToGuess);

Again, that makes the logic clear, no need for a comment.

I believe that has now eliminated all of your comments….. and replaced them with code that does not need a comment, because the code is self-explanatory.

In other news, if you had more functions, with good names, then your code would be simpler to read as well.

Bottom line, though, is that the comments in your code should fill in the blanks that your code does not. In addition, your comments should give details on the motivation, and not the application of your code. You should, in general, comment only on why your code does things, not what your code is doing.

That leads on to the other comments you are missing… JavaDoc.

JavaDoc is documentation that should explain what your code does at an abstract level.

You have no JavaDoc, and you likely should. JavaDoc is where you describe what your code does, because, typically, the people reading the javadoc are not reading the code, so they need something else to tell them what the code does.

So you want to write good comments.

Good comments…

  • …say why, not what.
  • …don’t state the obvious or rephrase what the code is already saying.
  • …don’t turn into lies if the code changes.

Let’s see…

import java.util.*; //so I can use scanner

The problem is that you’re importing an entire library, and specify that you’re only doing that for one of its types. Either you’re lying and you’re actually using more than that, or the import statement is overkill.

int max = 100; //sets limit on the random number generator

Comments on variables usually indicate poor naming, because good identifiers are self-explanatory. If max was called maxRandomValue, would this comment be needed?

int guess;//so I can compare console input to random number

This is another comment that used in-place of a more meaningful identifier. If guess was called userInput, would this comment be needed?

while (play) { //so game will restart after a win

There’s no reason to have this comment either; it’s pretty clear what the intent is here. The only potential issue I’m seeing with while (play) is that play is a verb, when a Boolean identifier is clearer when it starts with is or has – in this case, while(isPlaying).

 //so user can continue guessing until correct
 boolean win = false;

This comment isn’t needed either. Again it’s pretty clear what the intent is, but then again, it looks like a verb and could be called isCorrectGuess.


This is an interesting one:

//so user can choose to play another game    

    String answer = input.nextLine();
    char firstLetter = answer.charAt(0);
    if (firstLetter == 'y' || firstLetter == 'Y') {
    play = true;  
    } else {
    play = false;
} 

The indentation is clearly off here, and it’s confusing. Consider:

    String answer = input.nextLine();
    char firstLetter = answer.charAt(0);
    if (firstLetter == 'y' || firstLetter == 'Y') {
        play = true;  
    } else {
        play = false;
    } 

However you’re using a conditional to assign true in one branch, and false in the other – the whole if block is therefore useless:

    String answer = input.nextLine();
    char firstLetter = answer.charAt(0);
    play = firstLetter == 'y' || firstLetter == 'Y';

Now, about the comment…

//so user can choose to play another game    

This one is formulated in a way that makes it look like it’s saying why, but it basically says “this chunk of code does […]”. Whenever that happens, the rule of thumb is that you should extract that chunk into its own method.


Bottom line, I don’t think any of these comments are really needed. And do yourself a favor, drop that “so abc can xyz” formulation.

Bug

System.out.print("Your guess? " + numberToGuess);

Wells I guess I’m going to guess it right the first time, every time… 🙁

Code Review

@rolfl and @Mat’s Mug have provided valuable insights on your question about comments, so I’ll attempt to tackle the code part of it…

Use of boolean flags

Currently, both your loop conditions depend on setting boolean flags, which does make the code easier to read. Alternatively, since there are only two specific conditions when you want to exit from both loops, you can also consider doing a break instead at:

  1. Guessing the right number

    if (guess == numberToGuess) {
        break;
    }
    
  2. Exiting from the game

    if ( <first character of input is y/Y> ) {
        break;
    }
    

Thereafter, your while-loops will just be while (true) { ... }.

edit @rolfl’s approach is better and I’ll recommend it over the above.

Validating user input

guess = input.nextInt();
...
input.nextLine();

nextInt() throws a InputMismatchException if a non-integer input is entered, and not only that you must remember to ‘consume’ the current line by doing a nextLine() at the end. I’ll suggest reading the entire line in, do a Integer.parseInt(line) and catching the NumberFormatException for invalid inputs. You can then repeatedly prompt the user until you get a valid integer (maybe you’ll want to exclude negative values, or numbers outside your specified guessing range).

Printing this or that

There are two places where you are doing something similar to the following:

if (condition) {
    System.out.println("..." + "x" + "...");
} else {
    System.out.println("..." + "y" + "...");
}

Why not put this into a method that can abstract away this logic?

private static void printEither(boolean condition, String format, 
                                    String ifTrue, String ifFalse) {
    System.out.printf(format + "%n", condition ? ifTrue : ifFalse);
}

The assumption is that format has only one placeholder "%s", and format need not contain a trailing newline as the method is adding it. Usage:

printEither(guess > numberToGuess, "It's %s.", "lower", "higher");
...
printEither(numberOfTries == 1, "You got it right in " + numberOfTries + " %s!", 
                                    "guess", "guesses");

Do you want to play again?

The comparison can be simplified as such:

if (input.nextLine().substring(0, 1).equalsIgnoreCase("y")) {
    break;
}

try-with-resources

You should also use try-with-resources if you’re on Java 7 on your Scanner.

Related Solutions

How to generate a random string?

My favorite way to do it is by using /dev/urandom together with tr to delete unwanted characters. For instance, to get only digits and letters: tr -dc A-Za-z0-9 </dev/urandom | head -c 13 ; echo '' Alternatively, to include more characters from the OWASP...

How to copy a file from a remote server to a local machine?

The syntax for scp is: If you are on the computer from which you want to send file to a remote computer: scp /file/to/send username@remote:/where/to/put Here the remote can be a FQDN or an IP address. On the other hand if you are on the computer wanting to...

What is the difference between curl and wget?

The main differences are: wget's major strong side compared to curl is its ability to download recursively. wget is command line only. There's no lib or anything, but curl's features are powered by libcurl. curl supports FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP,...

Using ‘sed’ to find and replace [duplicate]

sed is the stream editor, in that you can use | (pipe) to send standard streams (STDIN and STDOUT specifically) through sed and alter them programmatically on the fly, making it a handy tool in the Unix philosophy tradition; but can edit files directly, too,...

How do I loop through only directories in bash?

You can specify a slash at the end to match only directories: for d in */ ; do echo "$d" done If you want to exclude symlinks, use a test to continue the loop if the current entry is a link. You need to remove the trailing slash from the name in order for -L to...

How to clear journalctl

The self maintenance method is to vacuum the logs by size or time. Retain only the past two days: journalctl --vacuum-time=2d Retain only the past 500 MB: journalctl --vacuum-size=500M man journalctl for more information. You don't typically clear the journal...

How can I run a command which will survive terminal close?

One of the following 2 should work: $ nohup redshift & or $ redshift & $ disown See the following for a bit more information on how this works: man nohup help disown Difference between nohup, disown and & (be sure to read the comments too) If your...

Get exit status of process that’s piped to another

bash and zsh have an array variable that holds the exit status of each element (command) of the last pipeline executed by the shell. If you are using bash, the array is called PIPESTATUS (case matters!) and the array indicies start at zero: $ false | true $...

Execute vs Read bit. How do directory permissions in Linux work?

When applying permissions to directories on Linux, the permission bits have different meanings than on regular files. The read bit (r) allows the affected user to list the files within the directory The write bit (w) allows the affected user to create, rename,...

What are the pros and cons of Vim and Emacs? [closed]

I use both, although if I had to choose one, I know which one I would pick. Still, I'll try to make an objective comparison on a few issues. Available everywhere? If you're a professional system administrator who works with Unix systems, or a power user on...

How do I use pushd and popd commands?

pushd, popd, and dirs are shell builtins which allow you manipulate the directory stack. This can be used to change directories but return to the directory from which you came. For example start up with the following directories: $ pwd /home/saml/somedir $ ls...

How to forward X over SSH to run graphics applications remotely?

X11 forwarding needs to be enabled on both the client side and the server side. On the client side, the -X (capital X) option to ssh enables X11 forwarding, and you can make this the default (for all connections or for a specific connection) with ForwardX11 yes...

What does “LC_ALL=C” do?

LC_ALL is the environment variable that overrides all the other localisation settings (except $LANGUAGE under some circumstances). Different aspects of localisations (like the thousand separator or decimal point character, character set, sorting order, month,...

What is a bind mount?

What is a bind mount? A bind mount is an alternate view of a directory tree. Classically, mounting creates a view of a storage device as a directory tree. A bind mount instead takes an existing directory tree and replicates it under a different point. The...

Turn off buffering in pipe

Another way to skin this cat is to use the stdbuf program, which is part of the GNU Coreutils (FreeBSD also has its own one). stdbuf -i0 -o0 -e0 command This turns off buffering completely for input, output and error. For some applications, line buffering may...

Can less retain colored output?

Use: git diff --color=always | less -r --color=always is there to tell git to output color codes even if the output is a pipe (not a tty). And -r is there to tell less to interpret those color codes and other escape sequences. Use -R for ANSI color codes only....

How do I copy a folder keeping owners and permissions intact?

sudo cp -rp /home/my_home /media/backup/my_home From cp manpage: -p same as --preserve=mode,ownership,timestamps --preserve[=ATTR_LIST] preserve the specified attributes (default: mode,ownership,timestamps), if possible additional attributes: context, links,...

Can I zip an entire folder using gzip?

No. Unlike zip, gzip functions as a compression algorithm only. Because of various reasons some of which hearken back to the era of tape drives, Unix uses a program named tar to archive data, which can then be compressed with a compression program like gzip,...

How do I check package version using apt-get / aptitude?

apt-get You can run a simulation to see what would happen if you upgrade/install a package: apt-get -s install <package> To see all possible upgrades, run a upgrade in verbose mode and (to be safe) with simulation, press n to cancel: apt-get -V -s upgrade...