Ich habe ein textbasiertes Hangman-Spiel in Java geschrieben, das die Funktionen enthalten muss, die ich in den Kommentaren meines Codes enthalten habe .
Kurz gesagt, das Spiel fordert den Benutzer auf, ein Wort einzugeben, das er (oder eine zweite Person) dann erraten wird. Das Wort wird vom Programm zensiert. Das Programm teilt dem Benutzer mit, ob der erratene Buchstabe im Wort enthalten ist oder nicht, und zeigt den Fortschritt des zensierten Wortes nach jeder Vermutung an. Wenn der Benutzer den Buchstaben bereits zuvor erraten hat, teilt das Programm dem Benutzer dies mit und zeigt seine vorherigen Vermutungen an, ohne Buchstaben zu wiederholen. Das Programm zeigt die Anzahl der Versuche am Ende an.
Der unten geschriebene Code funktioniert und verfügt über alle von mir aufgelisteten Funktionen. Aber es scheint nicht optimal zu sein und wahrscheinlich mit einer sehr schlechten Etikette, da ich bisher Autodidakt bin. Deshalb suche ich nach Ratschlägen, die diesen Code verbessern und sicherstellen, dass ich keine schlechten Gewohnheiten habe ( Ich habe wahrscheinlich schon haha), da ich weiterhin selbst Java lerne.
//Simple Hangman game where user types a word, program stores it in all CAPS for easier user readability and censors the word (i.e *****) //User then guesses one letter at a time until the entire word is guessed. Program will inform the user if the guess is in the word, and show the progress of the word after each guess. //If the guessed letter is in the word, program will print out the # of times the letter is in the word. //Program will store and print out # of guesses (attempts) needed to guess the word at the end of the program. //If user tries to duplicate a previous guess, program will inform user of that and show previous guesses by user. Attempt count will not go up for duplicate guesses. //When the program shows previous guesses by the user (using a string), it cannot contain duplicate letters. (i.e: if user guesses "s" twice, "s" will still only show up once in the string) //StackOverFlow readers: This program works as intended, but as a self-taught beginner coder, I need assistance on optimal coding style (less lines the better) and good coding principles/etiquette //I definitely think there are much better ways to code this, but I cannot think of any more (as you probably noticed, this is v3, which has more features and yet similar amount of lines as version 1 haha) //All and any help is appreciated! Thank you :D import java.util.*; public class HangmanGameV3 { public static void main(String [] args){ //Initialize all the variables used here String storedword; char[] charstring; int length; char[] censor; int attempts=0; StringBuilder pastguesses = new StringBuilder(); //String Builder to add and print out previous guesses Scanner typedword = new Scanner(System.in); System.out.println("Enter your word to guess: "); storedword = typedword.nextLine(); storedword = storedword.toUpperCase(); //stores the word and changes it to all caps length = storedword.length(); charstring = storedword.toCharArray(); //creates char array of string //creates and prints an array of chars with the same length as string censor = storedword.toCharArray(); System.out.println("Your secret word is: "); for (int index = 0; index < length; index++){ censor[index] = "*"; } //Main loop to take guesses (is this while loop the ideal loop here? while (String.valueOf(censor).equals(storedword)== false){ //Initialize all variables in loop char charguess; String tempword; String tempstring; boolean correct = false; //required for if loops below/lets the user know if the letter is in the word or not int times = 0; //number of times a letter is in the word boolean repeated = false; //check if user guessed the same letter twice //prints the censored secret word for(int a= 0; a < length; a++){ System.out.print(censor[a]); } System.out.println(); //asks user for guess, then stores guess in Char charguess and String tempstring Scanner guess = new Scanner(System.in); System.out.println("Type your guess: "); tempword = guess.next(); charguess = tempword.charAt(0); //gets char data from scanner pastguesses.append(charguess); //adds guess to previous guess string tempstring = pastguesses.toString(); //checks if user already guessed the letter previously if (tempstring.lastIndexOf(charguess, tempstring.length() -2 ) != -1){ System.out.println("You already guessed this letter! Guess again. Your previous guesses were: "); pastguesses.deleteCharAt(tempstring.length()-1); System.out.println(tempstring.substring(0, tempstring.length()-1)); repeated = true; } //if the guess is not a duplicated guess, checks if the guessed letter is in the word if (repeated == false){ for (int index = 0; index < length; index++){ if(charstring[index] == Character.toUpperCase(charguess)) { censor[index] = Character.toUpperCase(charguess); //replaces * with guessed letter in caps correct = true; times++; } } if(correct == true){ System.out.println("The letter " + charguess + " is in the secret word! There are " + times +" " + charguess + " "s in the word. Revealing the letter(s): "); } else if (correct == false){ System.out.println("Sorry, the letter is not in the word. Your secret word: "); } System.out.println(); } attempts++; } System.out.println("You guessed the entire word "+ storedword.toUpperCase() + " correctly! It took you " + attempts + " attempts!"); //typedword.close(); //StackOverFlow readers: is this necessary? Not sure how to use .close() }
Beispielausgabe meines Codes als Referenz, falls erforderlich:
Antwort
Einige einfache Änderungen:
Sie erstellen zwei Scanner , einen innerhalb der Schleife und einen zu Beginn schlecht benannten. Ich benenne den typedword
bis input
und ersetzen Sie die Verwendung von guess
durch input
.
if(repeated == false)
wäre besser geschrieben
if(!repeated)
Ebenso ändere ich andere, wenn Anweisungen
Ich würde eine Set<String>
verwenden, um vergangene Vermutungen zu speichern.
Ich habe mich bewegt d die Deklaration von times
innerhalb der !repeated loop
, damit ihre Deklaration näher an ihrer Verwendung liegt und in ihrem Umfang auf ihre Verwendung beschränkt ist.
Andere Deklarationen wurden mit der Einstellung des Werts verknüpft und einige Zuweisungen verkettet, z. B. die neue
String wordToGuess = input.nextLine().toUpperCase();
tempstring
wurde entfernt, es wird nur jetzt erstellt, wenn dies erforderlich ist.
Eine Reihe von Variablen wurde für erklärendere Namen umbenannt.
Endgültiger Code:
import java.util.HashSet; import java.util.Scanner; import java.util.Set; public class HangmanGameV3 { public static void main(String[] args) { int attempts = 0; Set<String> previousGuesses = new HashSet<>(); Scanner input = new Scanner(System.in); System.out.println("Enter your word to guess: "); String wordToGuess = input.nextLine().toUpperCase(); int length = wordToGuess.length(); char[] wordToGuessChars = wordToGuess.toCharArray(); //creates char array of string //creates and prints an array of chars with the same length as string char[] censor = wordToGuess.toCharArray(); System.out.println("Your secret word is: "); for (int index = 0; index < length; index++) { censor[index] = "*"; } //Main loop to take guesses (is this while loop the ideal loop here? while (!String.valueOf(censor).equals(wordToGuess)) { //Initialize all variables in loop boolean correct = false; //required for if loops below/lets the user know if the letter is in the word or not boolean repeated = false; //check if user guessed the same letter twice //prints the censored secret word for (int a = 0; a < length; a++) { System.out.print(censor[a]); } System.out.println(); //asks user for guess, then stores guess in Char charguess and String tempstring System.out.println("Type your guess: "); String currentGuess = input.next().toUpperCase().substring(0, 1); char currentGuessChar = currentGuess.charAt(0); //gets char data from scanner //checks if user already guessed the letter previously if (previousGuesses.contains(currentGuess)) { System.out.println("You already guessed this letter! Guess again. Your previous guesses were: "); System.out.println(previousGuesses.stream().reduce("", String::concat)); repeated = true; } previousGuesses.add(currentGuess); //if the guess is not a duplicated guess, checks if the guessed letter is in the word if (!repeated) { int times = 0; //number of times a letter is in the word for (int index = 0; index < length; index++) { if (wordToGuessChars[index] == currentGuessChar) { censor[index] = currentGuessChar; //replaces * with guessed letter in caps correct = true; times++; } } if (correct) { System.out.println("The letter " + currentGuessChar + " is in the secret word! There are " + times + " " + currentGuessChar + " "s in the word. Revealing the letter(s): "); } else { System.out.println("Sorry, the letter is not in the word. Your secret word: "); } System.out.println(); } attempts++; } System.out.println("You guessed the entire word " + wordToGuess.toUpperCase() + " correctly! It took you " + attempts + " attempts!"); } }
Kommentare
- Ein weiterer Vorschlag: Es könnte interessant sein, die Vermutung in einem anstelle eines Strings, aber das ändert einige kleinere Dinge in der Logik …
Antwort
Vielen Dank, dass Sie Ihren Code geteilt haben! Es sieht ziemlich gut aus, aber (wie immer) gibt es einige Dinge zu beheben und zu beachten:
-
Erstellen mehrerer
Scanner
-Instanzen: Sie brauchen nur einen. Das Erstellen von mehr als einem benötigt nur mehr Platz. Anstatttyped word
undguess
zu erstellen, erstellen Sie einfach eine mit dem Nameninput
oder so ähnlich. -
Schließen Ihrer
Scanners
: Immer Wenn Sie mit der Verwendung fertig sind, wird eine Warnung „Ressourcenleck“ angezeigt. Wenn Sie eineScanner
schließen, wird dieScanner
kann nicht wieder verwendet werden. Es ist, als würde man das Licht ausschalten, wenn man den Raum verlässt. Es macht keinen Sinn, sie eingeschaltet zu lassen. Es ist nur eine Verschwendung, wenn man dies tut. -
Verwenden von
==
mit Booleschen Werten. Verwenden Sie anstelle von==
!
wie folgt:if(condition) { //if "condition" is true.
oder
if(!condition) { //if "condition" is false