Угадывая число, но комментарии относительно

Я всегда отмечу свои комментарии, и мне просто хотелось узнать, приемлемы ли эти комментарии или что я должен включить /где я должен их включать.

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

public class GuessingGame {
   public static void main(String[] args) {

      Random rand = new Random ();
      int max = 100; //sets limit on the random number generator
      Scanner input = new Scanner(System.in);
      int guess;//so I can compare console input to random number
      boolean play = true;
      int totalGames = 0;  
      int totalGuesses = 0; 
      int bestGame = Integer.MAX_VALUE; 

      System.out.println("Can you guess the word?");
      System.out.println("I am sure you cannot guess!");
      System.out.println("Go ahead and try!");
      System.out.println();

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

         System.out.println("I'm thinking of a number between 1 and " + max + "...");
         int numberToGuess = rand.nextInt(max) + 1;
         int numberOfTries = 0;
         //so user can continue guessing until correct
         boolean win = false;  
         while (!win) {

            System.out.print("Your guess? " + numberToGuess);
            guess = input.nextInt();
            numberOfTries++;

            if (guess == numberToGuess) {
               win = true;  
            } else if (guess > numberToGuess) {
               System.out.println("It's lower.");
            } else if (guess < numberToGuess) {
               System.out.println("It's higher.");
            }      
            input.nextLine();
         }

         if (numberOfTries == 1) {
            System.out.println("You got it right in " + numberOfTries + " guess!");
         } else {
            System.out.println("You got it right in " + numberOfTries + " guesses!");
         }   

            totalGames++;
            totalGuesses+= numberOfTries;
            System.out.print("Do you want to play again? ");

            //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;                               
         } 


         bestGame = Math.min(bestGame, numberOfTries);
         System.out.println();               
      }

      System.out.println("Overall results:");
      System.out.println("Total games   = " + totalGames);  
      System.out.println("Total guesses = " +  totalGuesses);
      System.out.printf("Guesses/game  = %.1f \n", totalGuesses/(double)totalGames);
      System.out.println("Best game     = " + bestGame);
   }  
}
69 голосов | спросил Eric Irwin 8 Mayam15 2015, 07:00:58

5 ответов


146

Добро пожаловать в ад комментариев и личный вкус. Существует несколько ответов на ваш основной вопрос, который может быть прав:

  1. Вы недостаточно комментировали.
  2. Вы прокомментировали все неправильные вещи.
  3. Вы слишком много комментировали.
  4. Ваши комментарии не в том формате.
  5. Вам не хватает официальных комментариев.

Чтобы быть ясным, ничто из того, что мы можем сказать, не будет соответствовать тому, на чем основаны ваши оценки, если вы не можете сказать нам, почему вы были помечены вниз ...; -)


О комментариях вообще

ОК, комментарии должны ясно показать, что код нам уже не говорит.

Позвольте мне еще раз сказать.

  

Комментарии должны сообщать нам, что код не сообщает нам.

Теперь, если вы отметили это, или нет, это другая история. Я обнаружил, что академическое применение меток для комментариев часто противоречит необходимости комментариев ... особенно когда код является хорошим кодом.

Хороший код редко нуждается в комментариях.

Позвольте мне сказать , что снова:

  

Хороший код редко нуждается в комментариях.

Итак, следуйте этой логике, а затем следуйте обратной обратной ...

  1. Комментарии ясно показывают, что код нам уже не говорит.
  2. Хороший код редко нуждается в комментариях.

Таким образом ....

  1. Хороший код редко нуждается в комментариях.
  2. Хороший код должен прояснить, что делает код без необходимости в дополнительных объяснениях.

Применяется к вашему коду

Начнем с вершины ....

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

Теперь, если ваш код:

import java.util.Scanner;

, тогда ему не понадобится комментарий.

Следующий комментарий здесь:

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

Ну, это, на самом деле, не ужасный комментарий или код. Но, может быть, лучше, если бы мы дали ему достойное имя:

int randomGeneratorLimit = 100;

Было бы еще лучше, если бы мы сделали это магическое число постоянным:

private static final int RANDOM_GENERATOR_LIMIT = 100;

Теперь нет необходимости комментировать.

Далее, эта строка:

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

Ну, это интересно ... комментарий действительно нужен здесь из-за цикла, который вы используете.

Если вы преобразуете это в цикл do-while и используете некоторое функциональное извлечение ... тогда вы можете преобразовать свой код в самостоятельный документирующий блок комментариев:

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';
}

, то вы можете использовать эту функцию следующим образом:

do {

    ....... // game logic

} while (playAgain());

Нет необходимости в комментариях (или переменной play).

Аналогично, у вас есть код:

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

Это тоже должно быть сделано, и должно выглядеть так:

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

Опять же, это делает логику понятной, нет необходимости в комментариях.

Я считаю, что теперь все ваши комментарии были устранены ..... и заменил их кодом, который не нуждается в комментариях, потому что код не требует пояснений.

В других новостях, если у вас было больше функций, с хорошими именами, тогда ваш код будет проще читать.

В то же время нижняя строка состоит в том, что комментарии в вашем коде должны заполнять пробелы, которые не имеют ваш код. Кроме того, ваши комментарии должны содержать подробную информацию о мотивации , а не приложении вашего кода. Вы должны, в общем, комментировать только то, почему ваш код делает что-то, а не то, что делает ваш код.

Это приводит к другим комментариям, которые вам не хватает ... JavaDoc.

JavaDoc - это документация, которая должна объяснить, что делает ваш код на абстрактном уровне.

У вас нет JavaDoc, и вы, вероятно, должны это сделать. JavaDoc - это то, где вы описываете, что делает ваш код, потому что, как правило, люди, читающие javadoc, не читают код, поэтому им нужно что-то еще, чтобы рассказать им, что делает код.

ответил rolfl 8 Mayam15 2015, 07:26:03
39

Итак, вы хотите написать хорошие комментарии.

Хорошие комментарии ...

  • ... скажем почему , а не что .
  • ... не указать очевидный или перефразировать то, что уже говорит код.
  • ... не превращаются в ложь, если код изменяется.

Давайте посмотрим ...

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

Проблема в том, что вы импортируете всю библиотеку и указываете, что вы делаете это только для one своих типов. Либо вы лжете, и вы используете больше, чем это, или оператор import перегружен.

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

Комментарии к переменным обычно указывают на плохое присвоение имен, поскольку хорошие идентификаторы не требуют пояснений. Если max был вызван maxRandomValue, нужен ли этот комментарий?

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

Это еще один комментарий, который использовал место более значимого идентификатора. Если guess был вызван userInput, нужен ли этот комментарий?

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

Нет причин для этого комментария; довольно ясно, что намерение здесь. Единственная потенциальная проблема, с которой я сталкиваюсь с while (play), заключается в том, что play является verb , когда булевский идентификатор становится яснее при его запуске с is или has - в этом случае while(isPlaying).

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

Этот комментарий не нужен. Опять же, довольно ясно, что это за намерение, но опять же, он выглядит как глагол и может называться isCorrectGuess.


Это интересно:

//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;
} 

Отступ явно не работает, и это запутывает. Рассмотрим:

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

Однако вы используете условное обозначение true в одном ветви, а false в другом - весь if бесполезна:

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

Теперь, о комментарии ...

//so user can choose to play another game    

Этот формулируется таким образом, что он выглядит , как будто он говорит почему , но в основном говорит: «Этот кусок кода делает [...]». Всякий раз, когда это происходит, эмпирическое правило заключается в том, что вы должны извлечь этот кусок в свой собственный метод.


В нижней строке, я не думаю, что любой из этих комментариев действительно необходим. И сделайте себе одолжение, оставьте формулировку «так abc can xyz».

ответил Mathieu Guindon 8 Mayam15 2015, 07:27:24
25

Ошибка

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

Уэллс, я думаю, я собираюсь угадать это в первый раз, каждый раз ...: (

Обзор кода

@rolfl и @ Mat's Mug предоставили ценную информацию о вашем вопросе о комментариях, поэтому я попытаюсь решить ее часть code ...

Использование флагов boolean

В настоящее время оба условия цикла зависят от флагов boolean, что делает код более удобным для чтения. В качестве альтернативы, поскольку есть только два конкретных условия, когда вы хотите выйти из обоих циклов, вы также можете рассмотреть break:

  1. Угадывание правильного числа

    if (guess == numberToGuess) {
        break;
    }
    
  2. Выход из игры

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

После этого ваш while -loops будет просто while (true) { ... }.

изменить подход @ rolfl's , и я рекомендую его по выше.

Проверка ввода пользователя

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

nextInt() выдает InputMismatchException, если вводится нецелый ввод, и не только вы должны помнить, что «потребляете» текущую строку, выполняя nextLine () в конце. Я предлагаю прочитать всю строку, сделав nextLine() и ловить Integer.parseInt(line) для недопустимых входов. Затем вы можете повторно запрашивать пользователя, пока не получите действительное целое число (возможно, вы захотите исключить отрицательные значения или цифры вне указанного диапазона гаданий).

Печать тех или иных

Есть два места, где вы делаете что-то похожее на следующее:

NumberFormatException

Почему бы не поместить это в метод, который может абстрагировать эту логику?

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

Предполагается, что private static void printEither(boolean condition, String format, String ifTrue, String ifFalse) { System.out.printf(format + "%n", condition ? ifTrue : ifFalse); } имеет только один placeholder format, а "%s" не должен содержать завершающую новую строку, поскольку метод добавив его. Использование:

format

Вы хотите снова сыграть?

Сравнение может быть упрощено как таковое:

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

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

Вы также должны использовать try-with-resources , если вы используете Java 7 на try-with-resources.

ответил h.j.k. 8 Mayam15 2015, 09:02:39
18

Любопытно, что ваш вводный текст говорит "Can you guess the word?" Я думал, что это была , а не .

Ваши комментарии в основном безобидны. Худший - //so I can use scanner, что немного вводит в заблуждение, потому что вам также нужен import для java.util.Random. Вам было бы лучше писать

import java.util.Random;
import java.util.Scanner;

â € | без комментариев.

Моя главная проблема - это длина функции main() - 70 строк. Исключительная длина кода затрудняет просмотр и понимание всего кода сразу. Разбирая его на функции, вы позволяете анализировать каждую функцию отдельно, и вы также можете дать имя каждому фрагменту функциональности. Если вы выбираете хорошие имена, то программа может быть несколько самодокументирована. Если вы пишете JavaDoc, это еще более эффективный тип комментария.

Кроме того, вам следует избегать использования переменных флага, таких как play и win для управления потоком программы. Напишите правильные петли и, если необходимо, используйте ключевые слова, такие как continue или break, чтобы добраться туда, куда вы хотите пойти.

Обратите внимание, что если вы просто нажмете Enter в разделе «Вы хотите снова сыграть?» вопрос, ваша программа выйдет из строя с помощью StringIndexOutOfBoundsException.

import java.util.Random;
import java.util.Scanner;

public class GuessingGame {
    private static final int MAX = 100;
    private final Random rand = new Random();
    private final Scanner input;

    public GuessingGame(Scanner input) {
        this.input = input;
    }

    /**
     * Picks a number and asks for guesses until a correct guess.
     *
     * @return The number of guesses used (1 if guessed on the first try)
     */
    public int play() {
        System.out.println("I'm thinking of a number between 1 and " + MAX + "...");
        int numberToGuess = rand.nextInt(MAX) + 1;
        int score;
        for (score = 1; ; score++) {
            System.out.print("Your guess? ");
            int guess = input.nextInt();

            if (guess == numberToGuess) {
               break;
            } else if (guess > numberToGuess) {
               System.out.println("It's lower.");
            } else if (guess < numberToGuess) {
               System.out.println("It's higher.");
            }      
            input.nextLine();
        }
        System.out.printf("You got it right in %d guess%s!\n",
                          score,
                          score == 1 ? "" : "es");
        return score;
    }

    /**
     * Asks the user if he/she wants to play again.
     *
     * @return true for a "yes" answer, false for a "no" or unrecognized answer
     */
    public boolean playAgain() {
        System.out.print("Do you want to play again? ");
        String answer;
        while ((answer = input.nextLine()).isEmpty());
        char firstLetter = answer.charAt(0);
        return (firstLetter == 'y' || firstLetter == 'Y');
    }

    /**
     * Plays number-guessing games until user decides to quit,
     * then displays statistics.
     */
    public static void main(String[] args) {
        try (Scanner input = new Scanner(System.in)) {
            System.out.println("Can you guess the number?\n" +
                               "I am sure you cannot guess!\n" +
                               "Go ahead and try!\n");

            int guesses = 0, gamesPlayed = 0, bestScore = Integer.MAX_VALUE;
            GuessingGame game = new GuessingGame(input);
            do {
                int score = game.play();
                bestScore = Math.min(bestScore, score);
                guesses += score;
                gamesPlayed++;
            } while (game.playAgain());

            System.out.println("Overall results:");
            System.out.printf("Total games   = %d\n", gamesPlayed);  
            System.out.printf("Total guesses = %d\n", guesses);
            System.out.printf("Guesses/game  = %.1f\n", guesses/(double)gamesPlayed);
            System.out.printf("Best game     = %d\n", bestScore);
        }
    }
}
ответил 200_success 8 Maypm15 2015, 21:03:08
16

В вашем коде отсутствуют несколько очень важных комментариев. Некоторые из комментариев у вас есть ложь, другие тривиальны, другие же не говорят, что вы должны говорить.

Самый важный комментарий для всех

(С точки зрения юристов)

// Copyright 2015 Eric Irwin. All rights reserved.

Это не имеет большого значения в мире присвоений классов. В рабочем мире это может иметь большое значение. Некоторые люди уточняют, какие права зарезервированы. Зачем? Зарезервируйте все права. Или, возможно, обратитесь к лицензионному соглашению. Хранение его короткое и простое облегчает вставку этого очень важного комментария.

Самые важные комментарии всех

(С точки зрения javadoc)

Каждый класс, каждая функция должна иметь комментарий javadoc. Вы не (не должны!) За борт. Не говорите, когда вы его написали, или даже кто это написал. Напишите на простом английском языке (или просто французский, немецкий или любой другой), почему класс или функция существует.

В случае класса скажите, почему класс существует, как его использовать. Большинство классов имеют несколько функций-членов, несколько членов данных. Внешний пользователь, который вызывает эти функции-члены в случайном порядке, скорее всего, будет тостом. Как функции-члены должны быть упорядочены, как они взаимодействуют друг с другом: это тот материал, который вы хотите поместить в комментарий javadoc этого класса.

В случае функции документируйте, что делает функция, почему она существует - на простом английском языке. Документируйте аргументы функции и возвращаемое значение из функции. В одном случае (main) это может быть явно очевидным, но программа имеет только один main. Аргументы в main часто сложны, как может быть. В этом случае вы не используете аргументы - так скажите!

Другие отсутствующие комментарии

Ваши комментарии показывают небольшие вещи, но не хватает большой картины. Прекрасный пример:

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

Гораздо лучше, на мой взгляд:

// Play game after game until the user decides to stop.
while (play) {

Этот внешний цикл существует, поэтому пользователь может играть в несколько игр. (Это, вероятно, было частью задания. Скажите так.) Это большая картина. Итак, игра возобновится после победы? Это не «большая картина». Хотя хорошо написанный код может в какой-то мере объяснить, он не объясняет общую картину, а также намерение или архитектуру.

Комментарии к концу строки по сравнению с комментариями полной строки

Большинство ваших комментариев - комментарии в конце строки. Этот стиль комментариев заставляет людей быть краткими; чаще всего, чрезмерно кратким. Он также призывает людей прокомментировать очевидное (например, i++; // increment i). Единственное, что хуже, чем i++; // increment i - комментарий, который несовместим с кодом.

Комментировать очевидное с комментарием конца строки легко, но ваш код по большей части должен быть очевиден. Комментарий к очевидному не нужен. Комментируя это не так очевидно? Конец строки обычно не делает этого очень хорошо.

ответил David Hammen 10 Mayam15 2015, 06:36:05

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132