运行hangman(Java)的程序中的逻辑出错

Posted

技术标签:

【中文标题】运行hangman(Java)的程序中的逻辑出错【英文标题】:Logic going awry in a program that runs hangman (Java) 【发布时间】:2014-10-23 16:39:12 【问题描述】:

所以这里还有一个刽子手问题要添加到这里的库中。除了一个名为revealLetter() 的方法外,我的实体和边界类几乎都是完整的,该方法用正确猜测的字母替换空白。它还计算正确猜到的字母(如果有)的数量,并将该整数返回给驱动程序以确定它是否命中或命中。如果用户输入了错误的字母,revealLetter() 将返回零,否则它将返回正确字母的数量以确定正确的字母。我的问题是,revealLetter() 总是返回零,尽管填写了正确的字母。我已经投入了一些 sout 来隔离正在发生的事情,并且在退出我的 for 循环后,计数器似乎设置为零。我还在学习 Java,所以很有可能它很简单,但目前对我来说似乎很复杂。这是驱动程序:

package hangman;

import java.util.Scanner;

public class Hangman 

public static int NUMBER_MISSES = 5;

public static void main(String[] args) 

    String guessedLetter;
    WordHider hider = new WordHider();
    Dictionary dictionary = new Dictionary();

    Scanner Keyboard = new Scanner(System.in);
    hider.setHiddenWord(dictionary.getRandomWord());
    System.out.println(hider.getHiddenWord().length());
    System.out.println(hider.getHiddenWord());

    do 
        hider.wordFound();
        System.out.printf(hider.getPartiallyFoundWord() + "   Chances Remaing: %d \nMake a guess: ", NUMBER_MISSES);
        guessedLetter = Keyboard.nextLine();
        hider.revealLetter(guessedLetter.toLowerCase());
        if (hider.revealLetter(guessedLetter)== 0) 
            NUMBER_MISSES--;
            if (NUMBER_MISSES == 4) 
                System.out.println("Swing and a miss!");
            
            else if (NUMBER_MISSES == 3) 
                System.out.println("Yup. That. Is. A. Miss.");
            
            else if (NUMBER_MISSES == 2) 
                System.out.println("MISS! They say third time is a charm.");
            
            else if (NUMBER_MISSES == 1) 
                System.out.println("Ouch. One guess left, think carefully.");
                          
         else 
            System.out.println("That's a hit!");
        
        if (hider.wordFound() == true) 
          NUMBER_MISSES = 0;
        
     while (NUMBER_MISSES > 0);

    if ((NUMBER_MISSES == 0) && (hider.wordFound() == false)) 
        System.out.println("Critical Failure. The word was " + hider.getHiddenWord() + " try harder next time and you'll win.");
     else if ((NUMBER_MISSES == 0) && (hider.wordFound() == true)) 
        System.out.println(hider.getHiddenWord() + "\nBingo! You win!");
    


这是将单词从 .txt 存储到数组并生成随机单词的类:

package hangman;

import java.util.Random;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class Dictionary 

//Random randomizer = new Random();
private static String randomWord;
String[] dictionary = new String[81452];
private static String FILE_NAME = "dictionarycleaned.txt";

Dictionary() 
    int words = 0;
    Scanner infile = null;
    try 
        infile = new Scanner(new File(FILE_NAME));
        while (infile.hasNext()) 
            dictionary[words] = infile.nextLine();
            words++;

        
        //System.out.println(dictionary[81451]);
     catch (FileNotFoundException e) 
        System.err.println("Error opening the file " + FILE_NAME);
        System.exit(1);
    



public String getRandomWord()
  //randomWord = (dictionary[randomizer.nextInt(dictionary.length)]);  //Are either of these techniques better than the other?
  randomWord = (dictionary[new Random().nextInt(dictionary.length)]);
  return randomWord;    

这是包含revealLetter()的类,它也处理随机词:

package hangman;

public class WordHider 

private static String hiddenWord;
private static String partiallyFoundWord;

WordHider() 

    hiddenWord = "";
    partiallyFoundWord = "";



public String getHiddenWord() 
    return hiddenWord;


public String getPartiallyFoundWord() 

    return partiallyFoundWord;



public void setHiddenWord(String newHiddenWord) 
    int charCount;
    hiddenWord = newHiddenWord;
    for (charCount = 0; charCount < hiddenWord.length(); charCount++) 
        partiallyFoundWord += "*";
    



public int revealLetter(String letter) 
    int correctChars = 0;

    if (letter.length() < 1 || letter.length() > 1) 
        correctChars = 0;
        return correctChars;
     else 

        String tempString = "";

        for (int i = 0; i < hiddenWord.length(); i++) 
            if ((letter.charAt(0) == hiddenWord.charAt(i)) && (partiallyFoundWord.charAt(i) == '*'))                    
                correctChars++;
                tempString += Character.toString(hiddenWord.charAt(i));

             else 
                tempString += partiallyFoundWord.charAt(i);



            

        
        partiallyFoundWord = tempString;           
    

    return correctChars;


public boolean wordFound() 
    boolean won = false;
    if (partiallyFoundWord.contains(hiddenWord)) 
        won = true;
    
    return won;


public void hideWord() 
    for (int i = 0; i < hiddenWord.length(); i++) 
        partiallyFoundWord += "*";
    


还值得注意的是,我正在上 CS 大学课程,并且对于复制不属于我的代码有严格的法律。因此,如果有任何善良的灵魂发生在这件事上,可以你用英语解释我做错了什么。我仍然想弄清楚代码,我只是逻辑上卡住了。在此先感谢

【问题讨论】:

我将您关于复制代码的通知加粗,以免人们不小心忽略它并为您提供完整的解决方案。话虽如此,您是否尝试过在调试器中运行代码,例如 Eclipse、Netbeans 或 IntelliJ IDEA 等 IDE 中可能包含的调试器? 谢谢你!是的,我专门在 revelLetter() 方法调用上运行了调试器(在 Netbeans 中),它似乎通过了 for 循环,它会正确添加字母,但我不知道在 for 循环之后发生了什么。如果我在返回的正确字符上方放置一个 sout 语句,它会打印正确猜测的字母的数量(无论是 1、2 还是 3),但它也会打印零。这让我认为某处有第二次迭代正在重置我的变量。但我似乎无法隔离问题。 我无法发现具体问题,但我建议将revealLetter 中的 if 条件简化为仅(letter.charAt(0) == hiddenWord.charAt(i)),因为显示已显示的字母应该是无操作的。另外,为什么hiddenWordpartiallFoundWord 是静态的,而你的类中的方法是非静态的? 我有复合布尔值,以便它检查位置 (i) 是否是星号,如果是并且猜到的字母是正确的,它会将该字母与其他未填充的字符串一起添加到新字符串 tempString空白。我也忘了,在我的 for 的 else 中,correctChars 被设置为零。我会编辑那个。至于静态/非静态;我不确定,正如我所说的我还在学习,所以这可能只是我对事物的看法。那些是静态的有帮助吗? 静态意味着它在您的应用程序中是相同的。非静态意味着您为类的每个实例都获得了一个单独的值。如果您使用像new WordHider() 这样的构造函数,那么通常非静态是要走的路。详情请参阅this question and answers。 【参考方案1】:

在您的驱动程序main() 中,您有:

hider.revealLetter(guessedLetter.toLowerCase());
if (hider.revealLetter(guessedLetter)== 0)

这就是为什么你接到一个成功的电话,然后第二次就没有什么可做的了。我可以强调一些风格问题,但一个重要的问题是:

if (letter.length() < 1 || letter.length() > 1) 
    correctChars = 0;
    return correctChars;
 else 

为什么不只是letter.length() != 1,因为correctChars 已经初始化为零,你不需要再做一次,所以整个“then”部分可以被删除,if 变成letter.length() == 1

还有:

tempString += Character.toString(hiddenWord.charAt(i));

还有:

tempString += partiallyFoundWord.charAt(i);                                   

两者都做同样的事情,所以选择一种风格或另一种风格。

【讨论】:

感谢您的建议,非常感谢。我的 if 语句的这种简短表达方式确实看起来好多了,不那么笨重了。不过,关于我的 main() 中的 if 。那么,该语句总是接收零作为返回值,这就是为什么它永远不会转到 else 的原因? 关于 tempString += 你的意思是两者都做同样的事情,还是因为它们是两种不同的风格技术来实现相同的预期结果? += 是实现相同结果的两种不同方式,因此请选择较短的形式。您也可以考虑使用StringBuilder,因为这会带来轻微的性能优势,并且可能会从您的教练那里获得加分! 我明白了,谢谢你的分享!我快速阅读了 StringBuilder 的用法,我绝对可以看到它的好处。好先生,如果您这么客气的话,您还有最后一件事。您能否详细说明您对我的 main() 中的语句的含义?我一直在修补它,但我仍然有点卡住。我还在学习,我的批判性思维还在发展,所以我有点错过你的观点。 没关系!我重新阅读了您的评论,然后将我的 else 从 main 中删除,现在它很好,很漂亮。感谢您的所有帮助。

以上是关于运行hangman(Java)的程序中的逻辑出错的主要内容,如果未能解决你的问题,请参考以下文章

Java中的异常

异常处理

Scanf 在循环中跳过(Hangman)

09-JAVA中的异常处理

把java项目挂在服务器上出错

Java 的异常处理机制