Ik heb een op tekst gebaseerd spel voor Hangman in Java geschreven dat de functies moet bevatten die ik in de opmerkingen van mijn code heb opgenomen .
Kortom, het spel zal de gebruiker vragen een woord te typen dat hij (of een tweede persoon) dan zal raden. Het woord wordt gecensureerd door het programma. Het programma vertelt de gebruiker of de geraden letter in het woord staat of niet, en laat de voortgang van het gecensureerde woord zien na elke poging. Als de gebruiker de letter al eerder heeft geraden, zal het programma de gebruiker hiervan op de hoogte stellen en hun eerdere gissingen laten zien zonder letters te herhalen. Het programma zal aan het einde het aantal pogingen tonen.
De code die ik hieronder heb geschreven, werkt en heeft alle functies die ik heb genoemd. Maar het lijkt niet optimaal en waarschijnlijk met een zeer slechte etiquette, aangezien ik tot dusver autodidact ben. Daarom ben ik op zoek naar advies om deze code te verbeteren en om ervoor te zorgen dat ik niet in slechte gewoonten kom ( Ik heb waarschijnlijk al haha) aangezien ik zelf Java blijf leren.
//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() }
Voorbeelduitvoer van mijn code ter referentie indien nodig:
Antwoord
Enkele eenvoudige wijzigingen:
Je maakt twee scanners , een binnen de lus en een met een slechte naam aan het begin. Ik hernoem de typedword
naar input
en vervang het gebruik van guess
door input
.
if(repeated == false)
zou beter geschreven zijn
if(!repeated)
Op dezelfde manier verander ik andere als verklaringen
Ik zou een Set<String>
gebruiken om eerdere gissingen op te slaan
Ik ben verhuisd d de declaratie van times
naar binnen de !repeated loop
zodat de declaratie dichter bij het gebruik ervan ligt en beperkt in omvang tot het gebruik.
Andere declaraties zijn samengevoegd met de instelling van de waarde, en sommige toewijzingen zijn gekoppeld, zoals de nieuwe
String wordToGuess = input.nextLine().toUpperCase();
tempstring
is verwijderd, het wordt nu alleen geconstrueerd wanneer dat nodig is
een aantal variabelen is hernoemd voor meer verklarende namen.
Laatste 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!"); } }
Reacties
Answer
Bedankt voor het delen van uw code! Het ziet er redelijk goed uit, maar (zoals altijd) zijn er enkele dingen die moeten worden opgelost en waar u op moet letten:
-
Meerdere
Scanner
instanties maken: U heeft er maar één nodig. Als u er meer dan één maakt, neemt u gewoon meer ruimte in beslag. In plaats vantyped word
enguess
te maken, hoeft u alleen maar een met de naaminput
of iets dergelijks. -
Je
Scanners
sluiten: doe altijd dus als u klaar bent met het gebruik ervan, anders krijgt u een waarschuwing “Resource-lek”. Als u eenScanner
sluit, wordt deScanner
kan niet opnieuw worden gebruikt. Het is alsof je de lichten uitdoet als je de kamer verlaat, het heeft geen zin ze aan te laten. Het is gewoon zonde als je dat doet. -
==
gebruiken met booleans. Gebruik in plaats van==
!
als volgt:if(condition) { //if "condition" is true.
of
if(!condition) { //if "condition" is false
char
in plaats van een string, maar dat verandert enkele kleine dingen in de logica …