Java猜词游戏首次循环后异常:二次输入'n'时出错求助
解决猜词游戏第二次游玩输入'n'报错的问题
嘿,我看到你这个猜词游戏遇到的问题了——第二次游玩时输入'n'会触发错误,对吧?让我帮你拆解一下问题根源,然后给出修复方案。
问题根源分析
你的错误本质上是输入流缓冲区残留的换行符引发的连锁反应,具体过程是这样的:
- 第一次游戏结束后,你用
input.next()获取用户是否重玩的选择,这个方法只会读取用户输入的字符(比如Y/N),但不会读取用户按下的回车键(换行符),这个换行符会留在输入缓冲区里。 - 进入第二次游戏循环后,第一个
letterGuess = input.nextLine()会直接读取到这个残留的换行符,也就是空字符串""。 - Java里
SECRET_WORD.indexOf("")会返回0(空字符串默认匹配任何字符串的开头),于是代码会把wordSoFar从"-----"改成"----"(长度从5变成4)。 - 当你输入'n'(转成大写为"N"),
SECRET_WORD.indexOf("N")返回4(因为"BRAIN"的最后一个字母N在索引4的位置),接下来代码尝试执行wordSoFar.substring(5,4)——起始索引大于结束索引,直接抛出StringIndexOutOfBoundsException,这就是你遇到的错误。
修复方案
1. 清空输入缓冲区的残留换行符
在使用input.next()获取重玩选择后,添加一行代码清空缓冲区里的换行符:
System.out.println("Would you like to play again?"); repeat = input.next(); input.nextLine(); // 新增这行,清空残留的换行符
2. 拦截空输入的情况
在处理用户输入的字母之前,先判断是否为空,如果是空输入,提示用户重新输入,避免后续的索引操作出错:
在letterGuess = letterGuess.toUpperCase()之后添加:
// 处理空输入,要求用户输入有效内容 while (letterGuess.isEmpty()) { System.out.print("Please enter a valid letter or " + FLAG + ": "); letterGuess = input.nextLine().toUpperCase(); }
3. 优化错误计数逻辑(额外小修复)
当前代码里,当用户输入!(猜整个单词的标记)时,会被当成错误字母计数,这显然不合理。我们可以调整逻辑,先判断是否是标记,再处理字母猜测:
System.out.print("Enter a letter (" + FLAG + " to guess entire word): "); letterGuess = input.nextLine(); letterGuess = letterGuess.toUpperCase(); // 先处理空输入 while (letterGuess.isEmpty()) { System.out.print("Please enter a valid letter or " + FLAG + ": "); letterGuess = input.nextLine().toUpperCase(); } // 如果是猜整个单词的标记,直接跳出循环处理,不计数错误 if (letterGuess.equals(FLAG)) { break; } // 处理字母猜测的逻辑 if (SECRET_WORD.indexOf(letterGuess) >= 0) { // 注意:当前代码只替换第一个匹配的字母,如果秘密单词有重复字母(比如"APPLE"),需要后续优化遍历替换所有匹配项 updatedWord = wordSoFar.substring(0, SECRET_WORD.indexOf(letterGuess)); updatedWord += letterGuess; updatedWord += wordSoFar.substring(SECRET_WORD.indexOf(letterGuess)+1, wordSoFar.length()); wordSoFar = updatedWord; } else { numGuesses += 1; }
修复后的完整代码
/* * WordGuess.java */ import java.util.Scanner; /** * Plays a word guessing game with one player. * */ public class WordGuess { //Main method public static void main(String[] arqs) { final String SECRET_WORD = "BRAIN"; final String FLAG = "!"; String wordSoFar = "", updatedWord = ""; String letterGuess, wordGuess = ""; int numGuesses = 0; String repeat = ""; Scanner input = new Scanner(System.in); /* begin game */ System.out.println ( "Word Guess game. \n" ); do{ numGuesses = 0; wordSoFar = ""; updatedWord = ""; for (int i = 0; i < SECRET_WORD.length() ; i++) { wordSoFar += "-"; //word, as dashes } System.out.println("Your word is "); System.out.println(wordSoFar + "\n"); //displays dashes /* allow player to make guesses */ do{ System.out.print("Enter a letter (" + FLAG + " to guess entire word): "); letterGuess = input.nextLine(); letterGuess = letterGuess.toUpperCase() ; // 处理空输入,要求用户输入有效内容 while (letterGuess.isEmpty()) { System.out.print("Please enter a valid letter or " + FLAG + ": "); letterGuess = input.nextLine().toUpperCase(); } // 如果是猜整个单词的标记,直接跳出循环处理,不计数错误 if (letterGuess.equals(FLAG)) { break; } /* player correctly guessed a letter--extract string in wordSoFar * up to the letter guessed and then append guessed letter to that * string Next, extract rest of wordSoFar and append after the guessed * letter */ if (SECRET_WORD.indexOf(letterGuess) >= 0) { updatedWord = wordSoFar.substring(0, SECRET_WORD.indexOf(letterGuess)); updatedWord += letterGuess; updatedWord += wordSoFar.substring(SECRET_WORD.indexOf(letterGuess)+1, wordSoFar.length() ) ; wordSoFar = updatedWord; }else { numGuesses += 1; } /* display guessed letter instead of dash */ System.out.println(wordSoFar + "\n"); } while (!wordSoFar.equals(SECRET_WORD) && numGuesses < 6); /* finish game and display message and number of guesses */ if (letterGuess.equals(FLAG)) { System.out.println("What is your guess? "); wordGuess = input.nextLine() ; wordGuess = wordGuess.toUpperCase() ; } if (wordGuess.equals(SECRET_WORD) || wordSoFar.equals(SECRET_WORD)) { System.out.println ( "You won! " ) ; } else { System.out.println("Sorry. You lose."); } System.out.println("The secret word is " + SECRET_WORD); System.out.println("You made " + numGuesses + " mistake."); System.out.println("Would you like to play again?"); repeat = input.next(); input.nextLine(); // 清空残留的换行符 }while(repeat.equalsIgnoreCase("Y")); System.out.println("GOOD BYE THANKS FOR PLAYING!"); } }//end of Word Guess class
后续优化提示
等你解决完这个问题后,替换成随机单词数组的计划就可以正常推进了。另外,当前代码只能替换单词中第一个匹配的字母,如果之后要支持有重复字母的秘密单词,你可以遍历整个字符串,把所有匹配的位置都替换成猜测的字母。
内容的提问来源于stack exchange,提问作者ARYA 8B
相关产品推荐
相关产品推荐

