Hangman.Отлов повторно введенной буквы
Пишу программу "виселица". Уже почти все пункты реализованы. Остался один - отлавливать повторно введенную одну и ту же, отсутствующую букву в слове, по условиям, она не должна дублироваться в массиве, и тратить attempts. Я немножко завяз на данном этапе. Можно ли это попробовать сделать через два цикла?
for (int i = 0; i < guessedLetters.length; i++) {
for (int j = i + 1; j < guessedLetters.length; j++) {
if (guessedLetters[i] == guessedLetters[j]) {
break;
}
}
}
Основная логика
String[] figuresWord = {"one", "two", "three"};
String secretWord = figuresWord[(int) (Math.random() * figuresWord.length)].toLowerCase();
char[] guessedLetters = new char[secretWord.length()];
int attempts = 5;
for (int i = 0; i < guessedLetters.length; i++) {
guessedLetters[i] = '_';
}
while (attempts > 0) {
System.out.println("Текущее слово: " + String.valueOf(guessedLetters));
System.out.print("Угадай букву: ");
char guess = scan.next().toLowerCase().charAt(0);
if (!isLetter(guess)) {
System.out.println("Invalid input. Please enter a letter.");
continue;
}
boolean found = false;
for (int i = 0; i < secretWord.length(); i++) {
if (secretWord.charAt(i) == guess) {
guessedLetters[i] = guess;
found = true;
}
}
if (found && attempts != 5) {
attempts++;
System.out.println("Угадали букву, попыток " + attempts);
} else if(!found) {
attempts--;
System.out.println("Не угадали букву, попыток " + attempts);
}
switch (attempts) {
case 0: System.out.println(" |------| ");
case 1: System.out.println(" O");
case 2: System.out.println("/ \\ ");
case 3: System.out.println(" | ");
case 4: System.out.println("/ \\");
}
if (String.valueOf(guessedLetters).equals(secretWord)) {
System.out.println("Вы угадали слово: " + secretWord);
break;
}
}
if (attempts == 0) {
System.out.println("Попытки закончились");
}
private static boolean isLetter(char c) {
return (c >= 'a' && c <= 'z');
}
Ответы (2 шт):
Можно все введенные буквы собирать в строку и каждую новую проверять на наличие в этой строке:
if (guessedLetters.indexOf(guess) < 0) { // буквы нет
// do your stuff
}
Двойной цикл не нужен совершенно.
Для того, чтобы отслеживать ввод букв, достаточно завести массив булевых флажков Boolean[] usedLetters = new Boolean[26]
, в котором после инициализации будут записаны null
значения. Также можно было бы запоминать введённые буквы в сете символов Set<Character>
, но скорей всего этот материал ещё не учили.
Перед проверкой введённой буквы в слове следует проверить, содержит ли массив null
-значение для данной буквы. Если нет, значит данную букву уже вводили, иначе после поиска введённой буквы в загаданном слове следует установить соответствующий флажок.
// ...
Boolean[] usedLetters = new Boolean[26];
while (attempts > 0) {
System.out.println("Текущее слово: " + String.valueOf(guessedLetters));
System.out.print("Угадай букву: ");
char guess = Character.toLowerCase(scan.next().charAt(0));
if (!isLetter(guess)) {
System.out.println("Invalid input. Please enter a letter.");
continue;
}
if (null != usedLetters[guess - 'a']) {
System.out.println("You have already tried letter '" + guess + "'");
continue;
}
boolean found = false;
for (int i = 0; i < secretWord.length(); i++) {
if (secretWord.charAt(i) == guess) {
guessedLetters[i] = guess;
found = true;
}
}
usedLetters[guess - 'a'] = found;
// ...
}
Варианты с Set
:
- С использованием метода
contains
иHashSet
в качестве реализации
// ...
Set<Character> usedLetters = new HashSet<>();
while (attempts > 0) {
System.out.println("Текущее слово: " + String.valueOf(guessedLetters));
System.out.print("Угадай букву: ");
char guess = Character.toLowerCase(scan.next().charAt(0));
if (!isLetter(guess)) {
System.out.println("Invalid input. Please enter a letter.");
continue;
}
if (usedLetters.contains(guess)) {
System.out.println("You have already tried letter '" + guess + "'");
continue;
}
boolean found = false;
for (int i = 0; i < secretWord.length(); i++) {
if (secretWord.charAt(i) == guess) {
guessedLetters[i] = guess;
found = true;
}
}
usedLetters.add(guess);
// ...
}
- Более короткий вариант, с использованием только метода
add
, который будет возвращатьfalse
при попытке добавить существующее значение (т.е., сет не будет изменяться).
Также используется реализацияLinkedHashSet
, которая сохранит порядок вставки использованных букв.
// ...
Set<Character> usedLetters = new LinkedHashSet<>();
while (attempts > 0) {
System.out.println("Текущее слово: " + String.valueOf(guessedLetters));
System.out.print("Угадай букву: ");
char guess = Character.toLowerCase(scan.next().charAt(0));
if (!isLetter(guess)) {
System.out.println("Invalid input. Please enter a letter.");
continue;
}
if (!usedLetters.add(guess)) { // всегда пытаемся добавить букву в сет
System.out.println("You have already tried letter '" + guess + "'");
continue;
}
boolean found = false;
for (int i = 0; i < secretWord.length(); i++) {
if (secretWord.charAt(i) == guess) {
guessedLetters[i] = guess;
found = true;
}
}
// ...
}
Если нужно выводить особое сообщение, была ли введённая буква обнаружена в слове или нет, можно предложить ещё один вариант с использованием мапы Map<Character, Boolean>
по аналогии с массивом Boolean
, упомянутым в начале ответа.
При проверке наличия введённой буквы в мапе следует использовать метод Map::containsKey
, и затем для добавления элемента в мапу -- обычный Map::put
:
// ...
Map<Character, Boolean> usedLetters = new LinkedHashMap<>();
while (attempts > 0) {
System.out.println("Текущее слово: " + String.valueOf(guessedLetters));
System.out.print("Угадай букву: ");
char guess = Character.toLowerCase(scan.next().charAt(0));
if (!isLetter(guess)) {
System.out.println("Invalid input. Please enter a letter.");
continue;
}
if (usedLetters.containsKey(guess)) {
System.out.println("You have already tried letter '" + guess + "'");
if (usedLetters.get(guess)) {
System.out.println("The secret word contains this letter");
} else {
System.out.println("The secret word does not contain this letter");
}
continue;
}
boolean found = false;
for (int i = 0; i < secretWord.length(); i++) {
if (secretWord.charAt(i) == guess) {
guessedLetters[i] = guess;
found = true;
}
}
usedLetters.put(guess, found);
// ...
}