Skip to content

Instantly share code, notes, and snippets.

@OlegTihii
Created January 30, 2025 13:02
Show Gist options
  • Save OlegTihii/b8128337ae149be88232962e0a065f03 to your computer and use it in GitHub Desktop.
Save OlegTihii/b8128337ae149be88232962e0a065f03 to your computer and use it in GitHub Desktop.

https://github.com/MikitaRudy/HangmanGame
Ревью от Алексея


[Mikita Rudy]

Игра в процедурном стиле, состоит из нескольких классов.

НЕДОСТАТКИ РЕАЛИЗАЦИИ

  1. Неправильная последовательность в порядке отображения введенных букв- букву 'ц' я ввел второй, но в распечатке она стала первой. При этом введенная третьей буква 'к' в распечатке стала на третью позицию
Введите букву: й
  _______
  |     |
  |     O
  |
  |
  |
__|__
Слово: ______
Ошибки(1): [й]
Введите букву: ц
  _______
  |     |
  |     O
  |     |
  |
  |
__|__
Слово: ______
Ошибки(2): [ц, й]
Введите букву: к
  _______
  |     |
  |     O
  |    /|
  |
  |
__|__
Слово: ______
Ошибки(3): [ц, й, к]
  1. Вешаешь одноногого
Введите букву: г
  _______
  |     |
  |     O
  |    /|\
  |    /
  |
__|__
Слово: ______
Ошибки(5): [г, ц, й, к, н]
Введите букву: ш
Вы проиграли!
  1. При разработке UI требует не меньшего внимания к себе, чем код
Загаданое слово: деревоХотите сыграть в «Виселицу»? 

ХОРОШО

  1. Игра запускается
  2. Есть список неправильно введенных букв
  3. Можно ввести только одиночную букву русского алфавита
  4. Широко применяются константы
  5. В целом хороший нейминг
  6. Простой понятный алгоритм

ЗАМЕЧАНИЯ

  1. Нейминг

-Название метода вводит в заблуждение. Обещает найти все вхождения(букв), но на самом деле находит все вхождения буквы в слово И открывает эту букву в маске

private void findAllOccurrences(char letter) {
  //...
  hiddenWord.setCharAt(i, letter);
  //...
}

-Название должно как можно лучше объяснять суть явления

private Set<Character> wrongCharacters;

//ЛУЧШЕ:
private Set<Character> wrongLetters;

Oracle Java code conventions, part."Naming conventions" Мартин, "Чистый код", гл.2

  1. Нарушение DRY, магические буквы, числа, слова. Вводи константы. А если они уже есть- пользуйся
public static final String YES = "д";
public static final String NO = "н";
public static final String PLAY_REQUEST = "Хотите сыграть в «Виселицу»? \n Да (д)  \n Нет (н)";
public static final String YES_NO_INPUT = "Введите \"д\" или \"н\"!";

//ПРАВИЛЬНО:
public static final String YES = "д";
public static final String NO = "н";
public static final String PLAY_REQUEST = "Хотите сыграть в «Виселицу»? \n Да (%s)  \n Нет (%s)".formatted(YES, NO);
public static final String YES_NO_INPUT = "Введите \"%s\" или \"%s\"!".formatted(YES, NO);

Фаулер, "Рефакторинг", гл.8 п."Замена магического числа символической константой" refactoring.guru "Замена магического числа символьной константой"

  1. Создавай вспомогательные методы, делай программу более простой и понятной
if (word.indexOf(letter) != -1) {...}

if (hiddenWord.toString().equals(word)) {...}

//ПРАВИЛЬНО:
if (isНазваниеКотороеВсеОбъясняет(/*args or empty*/)) {...}

if (isСловоОтгадано(/*args or empty*/)) {...}

private boolean isНазваниеКотороеВсеОбъясняет(/*args or empty*/) {
  return word.indexOf(letter) != -1;
}

private boolean isСловоОтгадано(/*args or empty*/) {...}
  1. Если в блоке if есть return(break, continue, throw, exit и т.д.), то else не пишется - в этом случае неважно, будет else или нет, так как программа будет работать одинаково
if (input.length() == 1 && isRussianLetter(input.charAt(0))) {
  return input.charAt(0);
} else {
  System.out.println(Constants.INVALID_INPUT_MESSAGE);
}

//ПРАВИЛЬНО:
if (input.length() == 1 && isRussianLetter(input.charAt(0))) {
  return input.charAt(0);
} 
System.out.println(Constants.INVALID_INPUT_MESSAGE);
  1. class GallowsPrinter

-В любом switch-case должен быть default, в данном случае default должен бросать исключение с сообщением, что такого номера картинки не существует.

-Выдача картинок висельницы через switch-case или if-elseif - индусский код. Картинки нужно хранить в статическом массиве и выдавать по номеру, например, так

public final class HangmanPicture {
  //закрытый конструктор

  private static final String[][] PICTURES = {
    {
    "-----   ",
    "|       ",
    "|       ",
    "|       ",
    "|       ",
    "|       ",
    "------- ",
   },
   {
     "-----   ",
     "|   |   ",
     "|   O   ",
     "|       ",
     "|       ",
     "|       ",
     "------- ",
   },
   // more pics
  };

  public String[] get(int numPicture) {  
    return PICTURES[numPicture]; 
  }
}
  1. class Main, содержит точку входа main

+Только создает и запускает экземпляр Игры, это хорошо.

АРХИТЕКТУРА

Хотя проект состоит нескольких классов, он создан в процедурном стиле. Чтобы программа считалась выполненной в ООП стиле, она должна быть декомпозирована по правилам ООП и использовать ООП подходы при выполнении типичных задач, здесь этого не обнаружено.

ВЫВОД

Хорошая реализация игры в процедурном стиле.

#ревью #виселица

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment