コードのコメントに含めた機能を含める必要があるJavaでのハングマンテキストベースのゲームを作成しました。
要するに、ゲームはユーザーに、ユーザー(または2人目)が推測する単語を入力するように求めます。単語はプログラムによって検閲されます。プログラムは、推測された文字が単語に含まれているかどうかをユーザーに通知し、推測のたびに打ち切られた単語の進行状況を表示します。ユーザーが以前にその文字をすでに推測している場合、プログラムはそのことをユーザーに通知し、文字を繰り返さずに以前の推測を表示します。プログラムは最後に試行回数を表示します。
以下に記述したコードは機能し、リストしたすべての機能を備えています。しかし、これまでのところ独学であるため、最適ではなく、おそらくエチケットが非常に悪いようです。したがって、このコードを改善し、悪い習慣に陥らないようにするためのアドバイスを探しています(自分でJavaを学び続けているので、おそらくすでにhaha)を持っています。
//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() }
必要に応じて参照できるようにコードの出力例:
回答
いくつかの簡単な変更:
2つのスキャナーを作成します。1つはループ内にあり、もう1つは最初の名前が適切ではありません。
をinput
に変更し、guess
の使用をinput
。
if(repeated == false)
より適切に記述されます
if(!repeated)
同様に、他の場合も変更しますステートメント
過去の推測を保存するためにSet<String>
を使用します
移動しましたd times
の!repeated loop
内への宣言。これにより、宣言の使用がより近くなり、使用範囲が制限されます。
他の宣言が値の設定に結合され、新しい
String wordToGuess = input.nextLine().toUpperCase();
は削除され、必要な場合にのみ構築されるようになりました
わかりやすい名前にするために、いくつかの変数の名前が変更されました。
最終コード:
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!"); } }
コメント
- 別の提案:推測を文字列の代わりに、しかしそれはロジックのいくつかのマイナーなことを変更します…
回答
コードを共有していただきありがとうございます!見た目はかなり良いですが、(いつものように)修正して注意することがいくつかあります。
-
複数の
Scanner
インスタンスの作成:必要ありません。必要なのは1つだけです。複数作成すると、より多くのスペースが必要になります。typed word
とguess
を作成するのではなく、作成するだけです。input
などと呼ばれるもの。 -
Scanners
を閉じる:常に実行するしたがって、それらの使用を終了すると、「リソースリーク」の警告が表示されます。Scanner
を閉じると、Scanner
二度と使用することはできません。部屋を出るときに電気を消すようなものです。電気をつけたままにしても意味がありません。そうすると無駄になります。 -
==
をブール値で使用します。==
の代わりに、次のように!
を使用します。if(condition) { //if "condition" is true.
または
if(!condition) { //if "condition" is false