试图用Java实现基于文本的Hangman游戏

我需要检查用户输入的字母以及他们猜测的空格是否位于隐藏单词的特定位置。

变量1等于用户猜测的空间索引..而letterGuess是他们猜测的字母。 我的代码怎么样错了?

例如:秘密字是你好

hidden word is == ----- 

用户猜测h 0 1 2 3所以,需要检查单词hello索引0 1 2 3处的空格是否包含用户猜到的“h”,如果是,需要将-----替换为h----

  String firstSpace = guessedSpaces.substring(0,1); String secondSpace = guessedSpaces.substring(2,3); String thirdSpace = guessedSpaces.substring(4,5); String fourthSpace = guessedSpaces.substring(6,7); int one = Integer.parseInt(firstSpace); int two = Integer.parseInt(secondSpace); int three = Integer.parseInt(thirdSpace); int four = Integer.parseInt(fourthSpace); (secretWord.charAt(one)==letterGuess) (secretWord.charAt(one)==letterGuess) (secretWord.charAt(one)==letterGuess) (secretWord.charAt(one)==letterGuess) 

这是一个完整的刽子手程序的简短代码:

 static int MAX_MISSES = 5; static String[] WORDS = { "QUICK", "BROWN", "JUMPS" }; // etc public static void main(String[] args) throws Exception { String word = WORDS[new Random().nextInt(WORDS.length)], guesses = " "; int misses = -1; for (Scanner in = new Scanner(System.in); !word.matches("[" + guesses + "]+") & (misses += word.contains(guesses.substring(0, 1)) ? 0 : 1) <= MAX_MISSES; guesses = in.nextLine().toUpperCase().charAt(0) + guesses) System.out.println(word.replaceAll("(?<=.)", " ").replaceAll("[^" + guesses + "]", "_")); System.out.println(word + (misses > MAX_MISSES ? " not" : "") + " solved with " + misses + " incorrect guesses"); } 

一些说明:

  • 正则表达式用于检查解决方案并显示当前的猜测状态
  • &在循环终止中用来代替&&来强制执行逻辑的两侧 – 因此总是正确地更新未命中
  • 已经使用各种其他技巧来故意增加代码密度

输入没有错误检查。 如果用户输入了多个字母,则仅使用第一个字母。 如果没有输入字母,它将会爆炸。 可以在不添加更多代码的情况下添加错误检查,但for行将是一个巨大的 – 我将其留作读者的练习。

此外,没有检查错误地多次猜测同一个字母。 使用这段代码,如果你猜两次正确的字母,没有什么不好的事情发生,但如果你猜两次错误的字母,它就算是一个单独的“未命中”,所以你将燃烧你的一个机会。

我的另一个答案

我对此有点太有趣了。

主要课程:

 public class HangmanWord { private static final char MASK_CHAR = '-'; private final String word; private final char[] maskedWordChars; private int totalMatched; public HangmanWord(String alphaNum_secretWord) { int wordLen = -1; try { wordLen = alphaNum_secretWord.length(); } catch(NullPointerException npx) { throw new NullPointerException("alphaNum_secretWord"); } if(wordLen == 0) { throw new IllegalArgumentException("alphaNum_secretWord is non-null, but empty."); } //default is automatically false maskedWordChars = new char[wordLen]; Arrays.fill(maskedWordChars, MASK_CHAR); totalMatched = 0; if(!Pattern.compile("^\\w+").matcher(alphaNum_secretWord).matches()) { throw new IllegalArgumentException("alphaNum_secretWord (\"" + alphaNum_secretWord + "\") must contain only letters and digits."); } word = alphaNum_secretWord; } public int length() { return maskedWordChars.length; } public int getTotalMatchedCount() { return totalMatched; } public boolean didWin() { return (getTotalMatchedCount() == length()); } 

HangmanWord中的主要逻辑function:

  public int getMatchedCountFromGuess(char guessChar, int... idxGuesses) { if(idxGuesses.length == 0) { throw new IllegalArgumentException("idxGuesses.length is zero."); } int guessedCount = 0; for(int idx : idxGuesses) { try { if(maskedWordChars[idx] == MASK_CHAR && word.charAt(idx) == guessChar) { maskedWordChars[idx] = guessChar; guessedCount++; } } catch(ArrayIndexOutOfBoundsException abx) { throw new IllegalArgumentException("Index " + idx + " is invalid, given length() is " + length(), abx); } } totalMatched += guessedCount; return guessedCount; } public String getMasked() { return (new String(maskedWordChars)); } 

和演示用法,它利用了下面的HangmanGuess类。

请注意,这接受用户输入。 因此上面的猜测类,我可以存储模拟输入。 下面有一系列猜测对象。

(使用用户输入测试这样一个重要的程序是一场噩梦。我实际创建了用户输入的代码,但是偶然删除了。我打算把它放在一个单独的函数中,所以它可以选择使用,但是分心了在我把它粘贴回去之前。每次运行它都是手工输入所有这些数据很麻烦 。我只是不明白为什么用户输入在CS教育中需要这么多/由新手选择,用于任何事情但最琐碎的程序。)

  public static final void main(String[] idx0_alphaNumSecretWord) { HangmanWord hword = null; try { hword = new HangmanWord(idx0_alphaNumSecretWord[0]); } catch(ArrayIndexOutOfBoundsException abx) { throw new IllegalArgumentException("Missing one required parameter: The alpha-numeric secret word."); } //TESTING ONLY: //#=matches in guess HangmanGuess[] testGuesses = new HangmanGuess[]{ //012345678901 new HangmanGuess('t', 2, 3, 4), //onomatopoeia new HangmanGuess('e', 6, 7, 8, 9), //1 new HangmanGuess('a', 6, 7, 8), new HangmanGuess('a', 4), //1 new HangmanGuess('o', 0, 3), //1 new HangmanGuess('o', 0, 2, 8 ,6), //3 new HangmanGuess('p', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), //1 new HangmanGuess('n', 1), //1 new HangmanGuess('t', 4, 5), //1 new HangmanGuess('z', 0), new HangmanGuess('m', 3, 4), //1 new HangmanGuess('i', 10), //1 new HangmanGuess('a', 11) //1 }; int testIdx = 0; 

主要用途 – 逻辑:

  while(!hword.didWin()) { System.out.print("The secret word is: " + hword.getMasked() + ". Guess (char idx idx idx ...): "); //LIVE only: (must create!) // HangmanGuess hguess = getGuessFromUserInput(); //Testing only...START HangmanGuess hguess = testGuesses[testIdx++]; System.out.print(hguess); //Testing only...END int matchesThisGuess = hword.getMatchedCountFromGuess(hguess.chr, hguess.idxGuesses); System.out.println(); if(matchesThisGuess == 0) { System.out.println("No characters guessed."); } } System.out.println("SUCCESS: " + hword.getMasked()); } } 

猜猜课:

 class HangmanGuess { public final char chr; public final int[] idxGuesses; public HangmanGuess(char chr, int... idxGuesses) { this.chr = chr; this.idxGuesses = idxGuesses; } public String toString() { StringBuilder bldr = (new StringBuilder()).append(chr).append(" "); for(int i : idxGuesses) { bldr.append(i + " "); } return bldr.toString(); } } 

输出:

 [C:\java_code\]java HangmanWord onomatopoeia The secret word is: ------------. Guess (char idx idx idx ...): t 2 3 4 No characters guessed. The secret word is: ------------. Guess (char idx idx idx ...): e 6 7 8 9 The secret word is: ---------e--. Guess (char idx idx idx ...): a 6 7 8 No characters guessed. The secret word is: ---------e--. Guess (char idx idx idx ...): a 4 The secret word is: ----a----e--. Guess (char idx idx idx ...): o 0 3 The secret word is: o---a----e--. Guess (char idx idx idx ...): o 0 2 8 6 The secret word is: ooao-oe--. Guess (char idx idx idx ...): p 0 1 2 3 4 5 6 7 8 9 10 11 The secret word is: ooa-opoe--. Guess (char idx idx idx ...): n 1 The secret word is: ono-a-opoe--. Guess (char idx idx idx ...): t 4 5 The secret word is: ono-atopoe--. Guess (char idx idx idx ...): z 0 No characters guessed. The secret word is: ono-atopoe--. Guess (char idx idx idx ...): m 3 4 The secret word is: onomatopoe--. Guess (char idx idx idx ...): i 10 The secret word is: onomatopoei-. Guess (char idx idx idx ...): a 11 SUCCESS: onomatopoeia 

完整源代码:

  import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.Arrays; /** 

{@code java HangmanWord onomatopoeia}

**/ public class HangmanWord { private static final char MASK_CHAR = '-'; private final String word; private final char[] maskedWordChars; private int totalMatched; public HangmanWord(String alphaNum_secretWord) { int wordLen = -1; try { wordLen = alphaNum_secretWord.length(); } catch(NullPointerException npx) { throw new NullPointerException("alphaNum_secretWord"); } if(wordLen == 0) { throw new IllegalArgumentException("alphaNum_secretWord is non-null, but empty."); } //default is automatically false maskedWordChars = new char[wordLen]; Arrays.fill(maskedWordChars, MASK_CHAR); totalMatched = 0; if(!Pattern.compile("^\\w+").matcher(alphaNum_secretWord).matches()) { throw new IllegalArgumentException("alphaNum_secretWord (\"" + alphaNum_secretWord + "\") must contain only letters and digits."); } word = alphaNum_secretWord; } public int length() { return maskedWordChars.length; } public int getTotalMatchedCount() { return totalMatched; } public boolean didWin() { return (getTotalMatchedCount() == length()); } public int getMatchedCountFromGuess(char guessChar, int... idxGuesses) { if(idxGuesses.length == 0) { throw new IllegalArgumentException("idxGuesses.length is zero."); } int guessedCount = 0; for(int idx : idxGuesses) { try { if(maskedWordChars[idx] == MASK_CHAR && word.charAt(idx) == guessChar) { maskedWordChars[idx] = guessChar; guessedCount++; } } catch(ArrayIndexOutOfBoundsException abx) { throw new IllegalArgumentException("Index " + idx + " is invalid, given length() is " + length(), abx); } } totalMatched += guessedCount; return guessedCount; } public String getMasked() { return (new String(maskedWordChars)); } public static final void main(String[] idx0_alphaNumSecretWord) { HangmanWord hword = null; try { hword = new HangmanWord(idx0_alphaNumSecretWord[0]); } catch(ArrayIndexOutOfBoundsException abx) { throw new IllegalArgumentException("Missing one required parameter: The alpha-numeric secret word."); } //TESTING only //#=matches in guess HangmanGuess[] testGuesses = new HangmanGuess[]{ //012345678901 new HangmanGuess('t', 2, 3, 4), //onomatopoeia new HangmanGuess('e', 6, 7, 8, 9), //1 new HangmanGuess('a', 6, 7, 8), new HangmanGuess('a', 4), //1 new HangmanGuess('o', 0, 3), //1 new HangmanGuess('o', 0, 2, 8 ,6), //3 new HangmanGuess('p', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), //1 new HangmanGuess('n', 1), //1 new HangmanGuess('t', 4, 5), //1 new HangmanGuess('z', 0), new HangmanGuess('m', 3, 4), //1 new HangmanGuess('i', 10), //1 new HangmanGuess('a', 11) //1 }; int testIdx = 0; while(!hword.didWin()) { System.out.print("The secret word is: " + hword.getMasked() + ". Guess (char idx idx idx ...): "); //LIVE only: (must create!) // HangmanGuess hguess = getGuessFromUserInput(); //Testing only...START HangmanGuess hguess = testGuesses[testIdx++]; System.out.print(hguess); //Testing only...END int matchesThisGuess = hword.getMatchedCountFromGuess(hguess.chr, hguess.idxGuesses); System.out.println(); if(matchesThisGuess == 0) { System.out.println("No characters guessed."); } } System.out.println("SUCCESS: " + hword.getMasked()); } } class HangmanGuess { public final char chr; public final int[] idxGuesses; public HangmanGuess(char chr, int... idxGuesses) { this.chr = chr; this.idxGuesses = idxGuesses; } public String toString() { StringBuilder bldr = (new StringBuilder()).append(chr).append(" "); for(int i : idxGuesses) { bldr.append(i + " "); } return bldr.toString(); } }

我的另一个答案

我采取了波西米亚人的密集和伟大的答案 ,并使其成为我自己的。 它并不是更好,我只是为了学习而做到了。 虽然它不符合OP的规范,但规范与普通的hangman非常不同(您必须明确指定猜测字母适用的索引)。 此应用程序更接近正常的Hangman规则。

与波希米亚代码的主要区别在于

  • 这是一段do-while ,而不是for循环。
  • 它只保留唯一的字符,并与单独的currCharGuessAsStr进行比较,而不是currCharGuessAsStr中的第一个字符。
  • 它通知用户输入错误(无字符)而不是崩溃,并要求输入为单个字母。
  • 它在每一步显示状态。

预循环:

 public class Hangman { static int MAX_BAD_GUESSES = 10; static String[] WORDS = { "QUICK", "BROWN", "JUMPS" }; // etc public static void main(String[] args) throws Exception { String word = WORDS[new Random().nextInt(WORDS.length)]; Scanner in = new Scanner(System.in); int badGuessCount = 0; String guessInput = null; //Could be character key, but a ONE-CHARACTER STRING instead //To avoid having to translate back and forth between string //and char. Map unqGuessedCharsAsStrMap = new TreeMap(); //Must be initialized to the empty string. Initializing to null //Will result in the literal string "null" being added to it. String allGuessCharsStr = ""; String currCharGuessAsStr = " "; 

循环:

  do { System.out.print(getMasked(word, allGuessCharsStr) + " Guess a character [Bad guesses: " + badGuessCount + " of " + MAX_BAD_GUESSES + "]: "); guessInput = in.nextLine(); if(guessInput != null) { //null on first iteration only if(!guessInput.matches("^[a-zA-Z]$")) { System.out.println("Bad input. Must a single letter."); badGuessCount++; } else { //Definitely valid input, and exactly one character currCharGuessAsStr = guessInput.toUpperCase(); if(unqGuessedCharsAsStrMap.containsKey(currCharGuessAsStr)) { //Trim to eliminate initialization space System.out.println("Already guessed that letter. All guesses: " + allGuessCharsStr.trim()); } else { unqGuessedCharsAsStrMap.put(currCharGuessAsStr, null); //Prepend just-guessed character and sort it. allGuessCharsStr += currCharGuessAsStr; char[] allGuessedChars = allGuessCharsStr.toCharArray(); Arrays.sort(allGuessedChars); allGuessCharsStr = new String(allGuessedChars); } if(!word.contains(currCharGuessAsStr)) { badGuessCount++; } } } } while(!word.matches("[" + allGuessCharsStr + "]+") && badGuessCount <= MAX_BAD_GUESSES); 

post-loop和getMasked(s,s)函数:

  System.out.println(getMasked(word, allGuessCharsStr)); System.out.println(word + (badGuessCount > MAX_BAD_GUESSES ? " not" : "") + " solved with " + badGuessCount + " incorrect guesses (max allowed=" + MAX_BAD_GUESSES + ")."); } /** @param all_guessesStrESIfNone May not be null. If empty, no guesses have been made yet. @exception PatternSyntaxException If all_guessCharsStr is empty. **/ private static final String getMasked(String secret_word, String all_guessesStrESIfNone) { try { if(all_guessesStrESIfNone.length() == 0) { all_guessesStrESIfNone = " "; //Any non-letter will suffice } } catch(NullPointerException npx) { throw new NullPointerException("all_guessesStrESIfNone"); } //Mask all not-yet-guessed characters with an underscore. secret_word = secret_word.replaceAll("[^" + all_guessesStrESIfNone + "]", "_"); //Insert a space between every character (trim eliminates the final). return secret_word.replaceAll("(.)", "$1 ").trim(); } } 

解决输出:

 [C:\java_code]java Hangman _ _ _ _ _ Guess a character [Bad guesses: 0 of 10]: a _ _ _ _ _ Guess a character [Bad guesses: 1 of 10]: b _ _ _ _ _ Guess a character [Bad guesses: 2 of 10]: c _ _ _ _ _ Guess a character [Bad guesses: 3 of 10]: d _ _ _ _ _ Guess a character [Bad guesses: 4 of 10]: e _ _ _ _ _ Guess a character [Bad guesses: 5 of 10]: f _ _ _ _ _ Guess a character [Bad guesses: 6 of 10]: j J _ _ _ _ Guess a character [Bad guesses: 6 of 10]: q J _ _ _ _ Guess a character [Bad guesses: 7 of 10]: m J _ M _ _ Guess a character [Bad guesses: 7 of 10]: p J _ MP _ Guess a character [Bad guesses: 7 of 10]: u JUMP _ Guess a character [Bad guesses: 7 of 10]: s JUMPS JUMPS solved with 7 incorrect guesses (max allowed=10). 

未解决的输出:

 [C:\java_code]java Hangman _ _ _ _ _ Guess a character [Bad guesses: 0 of 10]: a _ _ _ _ _ Guess a character [Bad guesses: 1 of 10]: b _ _ _ _ _ Guess a character [Bad guesses: 2 of 10]: c _ _ _ C _ Guess a character [Bad guesses: 2 of 10]: d _ _ _ C _ Guess a character [Bad guesses: 3 of 10]: e _ _ _ C _ Guess a character [Bad guesses: 4 of 10]: f _ _ _ C _ Guess a character [Bad guesses: 5 of 10]: j _ _ _ C _ Guess a character [Bad guesses: 6 of 10]: e Already guessed that letter. All guesses: ABCDEFJ _ _ _ C _ Guess a character [Bad guesses: 7 of 10]: Bad input. Must a single letter. _ _ _ C _ Guess a character [Bad guesses: 8 of 10]: tt Bad input. Must a single letter. _ _ _ C _ Guess a character [Bad guesses: 9 of 10]: q Q _ _ C _ Guess a character [Bad guesses: 9 of 10]: k Q _ _ CK Guess a character [Bad guesses: 9 of 10]: l Q _ _ CK Guess a character [Bad guesses: 10 of 10]: z Q _ _ CK QUICK not solved with 11 incorrect guesses (max allowed=10). 

完整代码:

  import java.util.Arrays; import java.util.Map; import java.util.TreeMap; import java.util.Random; import java.util.Scanner; /** 

{@code java Hangman}

**/ public class Hangman { static int MAX_BAD_GUESSES = 10; static String[] WORDS = { "QUICK", "BROWN", "JUMPS" }; // etc public static void main(String[] args) throws Exception { String word = WORDS[new Random().nextInt(WORDS.length)]; Scanner in = new Scanner(System.in); int badGuessCount = 0; String guessInput = null; //Could be character key, but a ONE-CHARACTER STRING instead //To avoid having to translate back and forth between string //and char. Map unqGuessedCharsAsStrMap = new TreeMap(); //Must be initialized to the empty string. Initializing to null //Will result in the literal string "null" being added to it. String allGuessCharsStr = ""; String currCharGuessAsStr = " "; do { System.out.print(getMasked(word, allGuessCharsStr) + " Guess a character [Bad guesses: " + badGuessCount + " of " + MAX_BAD_GUESSES + "]: "); guessInput = in.nextLine(); if(guessInput != null) { //null on first iteration only if(!guessInput.matches("^[a-zA-Z]$")) { System.out.println("Bad input. Must a single letter."); badGuessCount++; } else { //Definitely valid input, and exactly one character currCharGuessAsStr = guessInput.toUpperCase(); if(unqGuessedCharsAsStrMap.containsKey(currCharGuessAsStr)) { //Trim to eliminate initialization space System.out.println("Already guessed that letter. All guesses: " + allGuessCharsStr.trim()); } else { unqGuessedCharsAsStrMap.put(currCharGuessAsStr, null); //Prepend just-guessed character and sort it. allGuessCharsStr += currCharGuessAsStr; char[] allGuessedChars = allGuessCharsStr.toCharArray(); Arrays.sort(allGuessedChars); allGuessCharsStr = new String(allGuessedChars); } if(!word.contains(currCharGuessAsStr)) { badGuessCount++; } } } } while(!word.matches("[" + allGuessCharsStr + "]+") && badGuessCount <= MAX_BAD_GUESSES); System.out.println(getMasked(word, allGuessCharsStr)); System.out.println(word + (badGuessCount > MAX_BAD_GUESSES ? " not" : "") + " solved with " + badGuessCount + " incorrect guesses (max allowed=" + MAX_BAD_GUESSES + ")."); } /** @param all_guessesStrESIfNone May not be null. If empty, no guesses have been made yet. @exception PatternSyntaxException If all_guessCharsStr is empty. **/ private static final String getMasked(String secret_word, String all_guessesStrESIfNone) { try { if(all_guessesStrESIfNone.length() == 0) { all_guessesStrESIfNone = " "; //Any non-letter will suffice } } catch(NullPointerException npx) { throw new NullPointerException("all_guessesStrESIfNone"); } //Mask all not-yet-guessed characters with an underscore. secret_word = secret_word.replaceAll("[^" + all_guessesStrESIfNone + "]", "_"); //Insert a space between every character (trim eliminates the final). return secret_word.replaceAll("(.)", "$1 ").trim(); } }

你没有告诉我们它是怎么出错的。

我猜你正试图写一个’刽子手’程序。 我会猜测你忘记了charAt()返回的索引从零开始。