Java程序运行hangman游戏时出现逻辑错误

3

这里又有一个hangman问题需要添加到库中。我的实体和边界类都已经完成,只差一个名为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 += "*";
    }

}

值得注意的是,我正在上一门计算机科学课程,对于抄袭他人代码有严格的法律规定。

所以,如果有任何好心人看到这篇文章,请用尽量简单易懂的英语解释我存在哪些问题。我仍然希望能够理解这段代码,只是目前陷入了逻辑困境。提前感谢您的帮助。


3
我已经在你有关复制代码的注意事项上加粗了文字,以免人们不小心忽略它并为你提供完整的解决方案。话虽这样说,你尝试在调试器中运行代码了吗?比如像Eclipse、Netbeans或IntelliJ IDEA这样的IDE可能会自带调试器。 - nanofarad
1
谢谢你的帮助!是的,我在Netbeans中运行了调试器,特别是在revelLetter()方法调用上,它似乎通过了for循环,并且正确地添加了字母,但是我不知道在那个for循环之后发生了什么。如果我在return correctChars之前放置一个sout语句,它会打印出正确猜测的字母数量(无论是1、2还是3),但是然后它也会打印出0。这让我想到可能有第二次迭代正在重置我的变量。但是我似乎无法分离出问题所在。 - LumberSzquatch
我无法发现具体的问题,但我建议简化revealLetter中的if条件,只需使用(letter.charAt(0) == hiddenWord.charAt(i)),因为揭示已经揭示的字母应该是一个无操作。此外,为什么您在该类中的方法是非静态的,而hiddenWordpartiallFoundWord是静态的呢? - nanofarad
我有一个复合布尔值,它检查位置(i)是否为星号,如果是,并且猜测的字母正确,则将该字母添加到新字符串tempString中,以及其他未填充的空格。另外我忘了,在我的for循环中的else语句中,correctChars被设置为零。我会编辑它的。至于静态/非静态;我不确定,正如我所说,我还在学习,所以这可能只是我粗略地看过去的。它们是静态的有帮助吗? - LumberSzquatch
静态意味着它在您的应用程序中是相同的。非静态意味着您为类的每个实例获取单独的值。如果您正在使用像 new WordHider() 这样的构造函数,则通常选择非静态方式。有关更多详细信息,请参阅此问题和答案 - nanofarad
非常感谢您,先生。您的评论和那个问答都非常有用。我很感激您的帮助。 - LumberSzquatch
1个回答

4
在您的驱动程序 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的原因吗? - LumberSzquatch
关于tempString +=,您的意思是它们完全执行相同的操作,还是它们是两种达到相同预期结果的不同风格技术? - LumberSzquatch
+= 是实现相同结果的两种不同方式,因此选择较短的形式。您还可以考虑使用 StringBuilder,因为它具有轻微的性能优势,并可能会为您赢得导师的额外加分! - Ken Y-N
我明白了,谢谢你分享这个!我快速阅读了一下StringBuilder的使用方法,我绝对能看到它的好处。但还有最后一件事想请教您,先生。您能详细说明一下您在我的main()语句中所说的意思吗?我一直在尝试修改它,但仍然有些困惑。我还在学习中,我的批判性思维还在发展中,所以我可能会稍微错过您的观点。 - LumberSzquatch
没事了!我重新阅读了你的评论,然后将我的 else 从 main 中删除,现在很好了。非常感谢你的帮助。 - LumberSzquatch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接