2014-10-08 2 views
0

Я пытаюсь создать игру палача. У меня все работает так, как я хочу, за исключением одного метода. Этот метод называется processGuess и берет строку String и два массива String в качестве параметров. Первый массив - это массив spaceArray и содержит символы подчеркивания, соответствующие длине предполагаемого слова (например: hello производит [ _ , _ , _ , _ , _ ]). Второй массив называется wordArray и содержит слово, которое пользователь пытается угадать.Почему метод не работает, как я думал?

Как я себе мой метод работу следующим образом:

  1. Создать массив, который хранит все догадывались буквы (guessArray)
  2. Создать счетчик, который отслеживает числа догадок (guessCounter)
  3. Используйте цикл for, чтобы перебирать каждую букву слова и сравнивать его с буквой, которую пользователь угадал.
    a. Если буква находится в слове, добавьте письмо в правильный индекс spaceArray
  4. Сравнить spaceArray по wordArray a. Если равный, напечатайте что-то, говорящее, что они выиграли в x количество догадок
    b. Если не равно.
    1. печати spaceArray
    2. Вызвать метод, который просит пользователя угадать следующую букву
    3. этот метод так, что обрабатывается новый догадывался письмо вызова.

Проблема заключается в том, что, когда я вспоминаю этот метод, не содержит новое письмо, но все еще содержит старое письмо. Я не знаю, что я делаю неправильно. Это первый случай, когда я попытался использовать методы внутри метода.

Вот мой метод:

public static void main(String[] args) throws FileNotFoundException { 
    Scanner file = new Scanner(
      new File("C:/FilesForJava/ScrabbleDictionary.txt")); 
    instructions(); 
    String[] dictionary = createDictonaryArray(file); 
    String[] randomWord = getRandomWord(dictionary); 
    String[] underscoreArray = showSpaces(randomWord); 
    String letter = getGuesses(); 
    processGuess(letter, underscoreArray, randomWord); 
} 
public static void instructions() {  
    System.out.println("Let's play hangman!"); 
    System.out.println(); 
} 
public static String[] createDictonaryArray(Scanner inputFile) 
     throws FileNotFoundException {  
    int wordCount = 0;  
    while(inputFile.hasNext()) { 
     String word = inputFile.next(); 
     wordCount++;     
    } 
    String[] scrabbleDictionary = new String[wordCount]; 
    Scanner file = new Scanner(
      new File("C:/FilesForJava/ScrabbleDictionary.txt")); 
    while(file.hasNext()) {   
     for(int i = 0; i < wordCount; i++) { 
      scrabbleDictionary[i] = file.next(); 
     } 
    } 
    file.close(); 
    return scrabbleDictionary;  
} 
public static String[] getRandomWord(String[] dict) {  
    String word = dict[(int)(Math.random() * dict.length)];   
    String[] wordArray = new String[word.length()];  
    for(int i = 0; i < wordArray.length; i++) { 
     wordArray[i] = word.trim().substring(0, 1); 
     word = word.trim().substring(1);   
    }  
    return wordArray; 
} 

public static String[] showSpaces(String[] word) { 
    String[] spaceArray = new String[word.length];  
    for(int i = 0; i < word.length; i++) { 
     spaceArray[i] = "_";    
    } 
    System.out.println(Arrays.toString(spaceArray)); 
    System.out.println(); 
    return spaceArray; 
} 
public static String getGuesses() { 
    Scanner guess = new Scanner(System.in); 
    System.out.println("Guess a letter: ");  
    String letter = guess.next(); 
    System.out.println(); 
    //guess.close(); 
    return letter;    
} 
public static void processGuess(String letter, String[] spaceArray, 
     String[] wordArray) { 
    int guessCounter = 0;   
    String[] guessArray = new String[spaceArray.length]; 
    for(int i = 0; i < spaceArray.length; i++) { 
     guessCounter++; 
     guessArray[i] = letter; 
     String indexLetter = wordArray[i];   
     if(indexLetter.equalsIgnoreCase(letter)) { 
      spaceArray[i] = letter;       
     }  
    } 
    if(spaceArray.equals(wordArray)) { 
     System.out.println("Yes! You won in " + guessCounter + "guesses!"); 
    }else { 
     System.out.println(Arrays.toString(spaceArray)); 
     getGuesses(); 
     processGuess(letter, spaceArray, wordArray); 
    }  
} 
+0

1.) что делает 'getGuesses()' do? 2.) Я не думаю, что вы должны были использовать рекурсию здесь. – EpicPandaForce

+0

Мне нужно больше кода, но я предполагаю, что вам нужно вернуть свое письмо из 'getGuesses' и передать его в' processGuess' вместо параметра 'letter'. –

+0

@ Zhuinden Я добавил остальную часть своего кода. – comfortablyNumb

ответ

1

Вам необходимо пройти новую догадку в ваш метод processGuess. Попробуйте что-то вроде этого:

else { 
    System.out.println(Arrays.toString(spaceArray)); 
    String newLetter = getGuesses(); 
    processGuess(newLetter, spaceArray, wordArray); 
}  
+0

А теперь я понимаю и вижу, где я ошибся.Большое спасибо за Вашу помощь. – comfortablyNumb

+0

Вам не нужно создавать новую String для передачи, вы можете просто установить букву на то, что возвращает getGuesses, или даже просто вызвать метод следующим образом: processGuess (getGuesses(), spaceArray, wordArray), но это ничтожно, иначе точно right –

1

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

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

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

В любом случае причина, по которой рекурсивный вызов вашего метода см. только первая буква догадалась, что это то, что вы им передаете.Метод getGuesses() ничего не делает для изменения локальной переменной letter (и не может ее сделать), а сам метод просто передает все, что было передано ему.

+0

Я сам учу себя и не имею ничего общего, кроме книги, которую я использую, поэтому я уверен, что есть намного лучшие способы разработки того, что я пытаюсь сделать. Я буду следовать вашим предложениям и переделывать свои методы. Я создал guessArray, потому что в конечном итоге я покажу пользователю массив букв, которые он использовал. Я использовал String массивы только потому, что я больше знаком с Strings, чем с символами. Спасибо за ваш вклад. – comfortablyNumb

1

Вы написали метод как рекурсивный метод (возможно, это не лучший способ сделать это). Проблема заключается в том, что когда рекурсивный метод объявляет локальную переменную, каждый вызов рекурсивного метода имеет свою собственную копию локальных переменных.

Таким образом, вы звоните processGuess, что создает guessArray. Тогда processGuess называет себя снова, который имеет свой собственный guessArray, и после того, как это происходит несколько раз, вы будете иметь стек, который выглядит примерно так:

+--------------------------------------------------------+ 
+ processGuess#1          + 
+ local variables: guessCounter#1, guessArray#1, i#1 + 
+--------------------------------------------------------+ --> calls: 
+ processGuess#2          + 
+ local variables: guessCounter#2, guessArray#2, i#2 + 
+--------------------------------------------------------+ --> which calls: 
+ processGuess#3          + 
+ local variables: guessCounter#3, guessArray#3, i#3 + 
+--------------------------------------------------------+ --> which calls: 
+ processGuess#4          + 
+ local variables: guessCounter#4, guessArray#4, i#4 + 
+--------------------------------------------------------+ 

Когда processGuess#4 изменяет guessArray, он изменяет guessArray#4. Но у этого есть no эффект на guessArray#3, guessArray#2, или guessArray#1. Все это отдельные локальные переменные, и они являются ссылками, которые относятся к четырем различным объектам. Таким образом, когда , processGuess#3 и processGuess#2 все возвращаются, изменения, внесенные ими в их собственные guessArray, теряются, а processGuess#1 будут видеть только те изменения, которые он сам сделал самостоятельно guessArray.

Как я уже сказал, я бы не использовал рекурсию для этой конкретной проблемы. Но это определенно проблема в других случаях, когда рекурсия - это правильный способ сделать что-то. Решения следующие: (1) объявить переменную или объект за пределами рекурсивным методом, как поле экземпляра в объекте - тогда все они будут иметь доступ к одной и той же переменной; или (2) добавить параметр к рекурсивному методу, чтобы рекурсивные вызовы могли совместно ссылаться на один и тот же объект.

[Примечание: номера #1, #2, которые я добавил, предназначены только для объяснения вещей; они не являются частью синтаксиса языка или что-то в этом роде.]

+0

Благодарим вас за ввод. Я возьму твои и другие комментарии к сердцу и переработаю мой дизайн. – comfortablyNumb

+0

guessArray в конечном итоге поможет пользователю отслеживать угадываемые буквы. Я покажу его после каждой догадки. Я еще не реализовал его. – comfortablyNumb

+0

@comfortablyNumb OK. Если это правда, вы, вероятно, не захотите, чтобы каждый рекурсивный вызов создавал новый (при условии, что вы продолжаете использовать рекурсию). – ajb

1

Ну, похоже, у вас может быть пара проблем.

Во-первых, рекурсия является очень плохим выбором для этого метода. Я думаю, что вы ищете цикл while, в котором условие изменяется, когда строки равны. Использование рекурсии здесь бесполезно увеличивает размер стека, когда вы вызываете все больше и больше методов, но никогда не возвращаетесь от них.

Теперь, что касается вашего вопроса, в коде, который вы нам дали, переменная буква никогда не изменяется. Я предполагаю, что get guesss возвращает строку? Если это правда, вам нужно установить букву, равную ей.

Я также хотел бы предложить использовать символ вместо строки.

public static void processGuess(String letter, String[] spaceArray, 
           String[] wordArray) { 
    while(true) { 
    int guessCounter = 0; 
    String[] guessArray = new String[spaceArray.length]; 
    for (int i = 0; i < spaceArray.length; i++) { 
     guessCounter++; 
     guessArray[i] = letter; 
     String indexLetter = wordArray[i]; 
     if (indexLetter.equalsIgnoreCase(letter)) { 
      spaceArray[i] = letter; 
     } 
    } 
    if (spaceArray.equals(wordArray)) { 
     System.out.println("Yes! You won in " + guessCounter + "guesses!"); 
     break; 
    } else { 
     System.out.println(Arrays.toString(spaceArray)); 
     letter = getGuesses(); 
    } 
    } 
} 
+0

Спасибо, Джаред. Вы и другие дали мне много указателей. Я вернусь и переработаю всю программу. – comfortablyNumb

Смежные вопросы