I'm trying to make a hangman game. On each turn, the user guesses a letter. If they guessed correctly, they can guess again. Otherwise, their remaining available guesses drops by one, and the guessed letter is put into an array.
When the user hits zero remaining guesses, the program is supposed to ask if they want to play again. If they answer yes, it is supposed to restart the game, and if they answer no, the program ends.
The problem I'm having is with the array that holds the guesses, and with restarting the game.
Also, the program will error every once in a while when starting. The error is
Exception in thread "main" java.lang.NullPointerException at Hangman1.main(Hangman1.java:27)
The error when trying to restart the game is
Exception in thread "main" java.lang.NullPointerException at Hangman1.main(Hangman1.java:101)
searchArray is the method that is supposed to take the position of the char array and copy that in asterisk array and return asterisk array, that doesn't seem to work. Running debug it seems the problem that causes the program to crash is that word will sometimes end up null, but only sometimes and I don't really know why
import java.util.*;
import java.io.*;
public class Hangman1 {
static Scanner keyboard = new Scanner(System.in);
public static final int MAXSIZE = 15000;
public static final int NUM_GUESS = 8;
public static final int WORD_LENGTH = 20;
public static void main(String[] args) {
int random = pickrandom(MAXSIZE);
try {
// Set up connection to the input file
Scanner input = new Scanner(new FileReader("dictionary.txt"));
instructions();
keyboard.nextLine();
clearScreen();
String word = randomWord(input, random);
System.out.println(word);
String[] charArray = word.split("");
System.out.print("\n");
String[] asterisk = asteriskLine(word);
String decision = "Y";
//decision = keyboard.nextLine().toUpperCase();
System.out.println("Word to guess :");
for (int count = 0; count < word.length(); count++) {
System.out.print(asterisk[count]);
}
System.out.print("\n");
int tries = NUM_GUESS;
System.out.println("Enter a letter to guess or 9 to quit");
String guess = keyboard.next();
String[] wrongGuesses = new String [NUM_GUESS];
int guessMade = 0;
do {
//System.out.println(tries);
while (!(guess.equals("9")) && !(guess.equals(word)) && (tries > 0))
{
String letter = guess.substring(0,1);
if (word.indexOf(letter) < 0) {
clearScreen();
tries--;
wrongGuesses = wrongGuesses(guessMade, wrongGuesses, letter);
printArray(asterisk, charArray, word, tries, wrongGuesses, guessMade);
guessMade++;
guess = keyboard.next();
}
else {
clearScreen();
asterisk = searchArray(charArray, asterisk, guessMade, letter, word);
printArray(asterisk, charArray, word, tries, wrongGuesses, guessMade);
guess = keyboard.next();
}
if (charArray == asterisk) {
System.out.println("You won!");
}
if (tries == 0) {
System.out.println("You have no more guesses left");
}
}
if (guess.equals("9")) {
System.out.println("Thanks for playing");
}
System.out.println("Play again? Y/N");
decision = keyboard.next().toUpperCase();
if (decision.equals("Y")) {
random = pickrandom(MAXSIZE);
word = randomWord(input, random);
charArray = word.split("");
System.out.print("\n");
asterisk = asteriskLine(word);
guess = keyboard.next();
}
} while (decision.equals("Y"));
//System.out.println("Play again? Y/N");
//decision = keyboard.nextLine().toUpperCase();
}
catch (FileNotFoundException e) {
System.out.println("There was an error opening one of the files.");
}
}
//Clears screen after introduction
private static void clearScreen() {
for (int blanks = 0; blanks < 80; blanks++) {
System.out.println();
}
}
// This method returns a randomly selected integer
// between 0 and count-1
public static int pickrandom(int count) {
Random generator = new Random();
return generator.nextInt(count);
}
// Places asterisks in place of the letters in the word
// Parameter is the string word. it holds mystery word
public static String[] asteriskLine(String word) {
int i;
String[] asteriskArray = new String [word.length()];
for (i = 0; i < word.length(); i++) {
asteriskArray[i] = "* ";
}
return asteriskArray;
}
public static void instructions() {
System.out.println(" H A N G M A N. "
+ "\n This is a word guessing game. "
+ "\n A word will be selected at random and kept hidden. You will try to figure out the secret word by"
+ "\n guessing letters which you think are in the word. "
+ "\n You will guess one letter at a time. "
+ "\n If the letter you guess is correct, the position(s) of the letter in the secret word will be shown. "
+ "\n You will be allowed "
+ NUM_GUESS
+ " wrong guesses If you guess incorrectly "
+ NUM_GUESS
+ " times, you lose the game. "
+ "\n If you guess all of the letters in the word, you win."
+ "\n\n Press enter to continue ");
}
public static String randomWord(Scanner input, int random) {
String[] dictionaryWords = new String [MAXSIZE];
int usedsize = 0;
while (usedsize < MAXSIZE && input.hasNextLine()) {
dictionaryWords[usedsize] = input.nextLine();
usedsize++;
}
String word = dictionaryWords[random];
return word;
}
//Replaces correct guess in blanks
public static String correctWord(String guess, String word, String asterisk, char letter) {
return null;
}
public static void printArray(String[] asterisk, String[] charArray, String word, int tries, String[] wrongGuesses, int guessMade) {
System.out.println("Word to guess");
for (int count = 0; count < word.length(); count++) {
System.out.print(asterisk[count]);
}
System.out.println("\nGuesses remaining: " + tries);
System.out.print("Incorrect letters tried: ");
for (int count = 0; count <= guessMade; count++) {
System.out.print(wrongGuesses[count] + " ");
}
System.out.println("\nEnter a letter to guess or 9 to quit");
}
public static String[] wrongGuesses(int guessMade, String [] wrongGuesses, String letter) {
wrongGuesses[guessMade] = letter;
return wrongGuesses;
}
public static String[] searchArray(String[] charArray, String[] asterisk, int guessMade, String letter, String word) {
int[] a = new int[word.length()];
for (int count = 0; count < word.length(); count++) {
if (letter == charArray[count]) {
asterisk[count] = charArray[count];
}
}
return asterisk;
}
}
One thing that you need to do is to read all of your words in once and only once, and store them all into an ArrayList. Your current code tries to re-use a Scanner object that is already spent, and that will fail. Instead get your random word from the ArrayList<String>.
Running debug it seems the problem that causes the program to crash is
that word will sometimes end up null, but only sometimes and I don't
really know why
public static String randomWord(Scanner input, int random) {
String[] dictionaryWords = new String [MAXSIZE];
int usedsize = 0;
while (usedsize < MAXSIZE && input.hasNextLine()) {
dictionaryWords[usedsize] = input.nextLine();
usedsize++;
}
String word = dictionaryWords[random];
return word;
}
Sometimes random will be bigger than usedsize.
So you need to move this line from outside the loop
int random = pickrandom(MAXSIZE);
into this function, and have the maximum be usedsize (or usedsize-1).
You can protect yourself against this error, and work out whether you should be using usedsize or usedsize-1, by writing a unit test. Look into a Junit tutorial.
In your junit test, call randomword and pass it a very high value for random. Then
assert(word!= null)
Word is null when random is longer than the length of your dictionary.
Related
I am creating a hangman program in java. The program is supposed to randomly generate the word and as the user correctly guesses a letter it should reveal it. I have created the function where it prints the amount of underscores depending on the length of the word. The issue I have is I'm not sure how I'm supposed to replace the underscore with the letter when it's guessed.
public static void main(String[] args) {
int choice;
String wordSoFar = "";
Console.print("Take your time.");
choice = Console.readInt("Enter your choice, when you're ready : ");
}
if (choice == 1) {
for (int i = 0; i < wordLength; i++) {
word += " _ ";
}
do {
String guess = Console.readString("Enter your guess here : ");
String response = secert(guess);
Console.print(response);
} while (incorrectLetters < maxIncorectLetters || correctLetters < wordLength);
}
}
public static String secretWordSelector(String secretWord) {
String[] secretWordsList = { "fun", "boring", "yellow", "phython", "tesla", "iphone", "computer", "adventure",
};
int min = 0;
int max = 8;
secretWord = secretWordsList[randomNumber(min, max)];
return secretWord;
}
public static String letterChecker(String guess, String wordSoFar) {
String response = "";
String secertWord = "";
if (secretWord == guess)) {
int index = secretWord.indexOf(guess);
correctLetters++;
answer = "Congratulations!
} else {
answer= "That is a incorrect guess!
}
return answer;
}
Your code can be improved a lot by the following changes:
You do not need the complex function, randomNumber. You can simply pass the length of the array to Random#nextInt and it will generate an int in the range of 0 to length_of_array - 1.
Similarly, your function, length is not required. You can simply call String#length to get the length of the string.
You have unnecessarily passed an argument to your function, secretWordSelector.
Since you are using String wordSoFar in multiple methods, it will be easier to process it by making it global.
You have called secretWordSelector again in letterChecker which is wrong. You have to process the same word which was selected randomly at the time when the user selected a choice.
Your while loop is infinite because of the wrong operator. It should be while (incorrectLetters < maxIncorectLetters && correctLetters < wordLength)
I have re-written the method, letterChecker with many changes which are self-explanatory. I have also put some comments to help you understand its code easily.
Code incorporating these improvements:
import java.util.Random;
import java.util.Scanner;
public class Main {
private static int incorrectLetters;
private static int correctLetters;
private static String wordSoFar = "";
public static void main(String[] args) {
int choice;
Scanner scanner = new Scanner(System.in);
final int maxIncorectLetters = 6;
System.out.println("Welcome to Mahmoud's Hangman game!");
System.out.println("Would you like to play. 1 - Yes. 0 - No");
System.out.print("Enter your choice: ");
choice = Integer.parseInt(scanner.nextLine());
if (choice == 0) {
System.out.println("Take your time.");
System.out.print("Enter your choice, when you're ready: ");
choice = Integer.parseInt(scanner.nextLine());
}
if (choice == 1) {
System.out.println("Be careful, you can only have 6 wrong guesses");
int wordLength = 0;
String secretWord = secretWordSelector();
wordLength = secretWord.length();
System.out.println("Your word has " + wordLength + " letters.");
for (int i = 0; i < wordLength; i++) {
wordSoFar += "_";
}
do {
System.out.print("Enter your guess here: ");
String guess = scanner.nextLine();
String response = letterChecker(guess.toLowerCase().charAt(0), secretWord);
System.out.println(response);
} while (incorrectLetters < maxIncorectLetters && correctLetters < wordLength);
}
}
public static String secretWordSelector() {
String[] secretWordsList = { "geography", "cat", "yesterday", "java", "truck", "opportunity", "fish", "token",
"transportation", "bottom", "apple", "cake", "remote", "boots", "terminology", "arm", "cranberry",
"tool", "caterpillar", "spoon", "watermelon", "laptop", "toe", "toad", "fundamental", "capitol",
"garbage", "anticipate", "pesky" };
return secretWordsList[new Random().nextInt(secretWordsList.length)];
}
public static String letterChecker(char guess, String secretWord) {
String response = "";
// Initialize a StringBuilder with wordSoFar
StringBuilder sb = new StringBuilder(wordSoFar);
if (secretWord.indexOf(guess) != -1) {// i.e. if guess is present in secretWord
// Replace each corresponding occurrence of '_' in the StringBuilder with guess
for (int i = 0; i < secretWord.length(); i++) {
char ch = secretWord.charAt(i);
if (ch == guess) {
sb.setCharAt(i, ch);
correctLetters++;
}
}
// Assign the updated StringBuilder to wordSoFar
wordSoFar = sb.toString();
return "Congratulations! You have guessed correctly. " + " You have " + incorrectLetters
+ " incorrect guesses " + wordSoFar;
}
incorrectLetters++;
response = "That is a incorrect guess! " + " You have " + incorrectLetters + " incorrect guesses " + wordSoFar;
return response;
}
}
A sample run:
Welcome to Mahmoud's Hangman game!
Would you like to play. 1 - Yes. 0 - No
Enter your choice: 1
Be careful, you can only have 6 wrong guesses
Your word has 4 letters.
Enter your guess here: o
That is a incorrect guess! You have 1 incorrect guesses ____
Enter your guess here: e
That is a incorrect guess! You have 2 incorrect guesses ____
Enter your guess here: a
That is a incorrect guess! You have 3 incorrect guesses ____
Enter your guess here: h
Congratulations! You have guessed correctly. You have 3 incorrect guesses ___h
Enter your guess here: f
Congratulations! You have guessed correctly. You have 3 incorrect guesses f__h
Enter your guess here: i
Congratulations! You have guessed correctly. You have 3 incorrect guesses fi_h
Enter your guess here: s
Congratulations! You have guessed correctly. You have 3 incorrect guesses fish
I'm trying to make a program that when a user inputs a string using scanner, the first letter gets moved to the end of the word, and then the word is spelled backwards. The program then determines if you get the original word.
e.g if user types in 'potato' the program will move 'p' to the end, and will display true, as we get the same word backwards - 'otatop'.
Example output:
You have entered "BANANA".
Is ANANAB same as BANANA? True.
Thank you in advance for any help.
Jack
This is what I've got so far, but I don't think it works properly.
public class WordPlay {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String word;
String palindrome = "";
String quit = "quit";
do {
System.out.print("Enter a word: ");
word = scanner.nextLine().toUpperCase();
int length = word.length();
for (int i = length - 1; i >= 0; i--) {
palindrome = palindrome + word.charAt(i);
}
if (word.equals(palindrome)) {
System.out.println("Is the word + palindrome + " same as " + word + "?", true);
} else {
System.out.println(false);
}
} while (!word.equals(quit));
System.out.println("Good Bye");
scanner.close();
}
}
Here it is.
public static void main(String[] args) {
// To take input.
Scanner scan = new Scanner(System.in);
System.out.print("Enter Word: ");
String word = scan.next(); // taking the word from user
// moving first letter to the end.
String newWord = word.substring(1) + word.charAt(0);
// reversing the newWord.
String reversed = new StringBuffer(newWord).reverse().toString();
// printing output.
System.out.println("You have entered '"+word+"'. "
+ "Is "+newWord+" same as "+word+"? "
+reversed.equals(word)+".");
// closing the input stream.
scan.close();
}
This works:
import java.util.*;
public class HelloWorld{
public static void main(String []args){
Scanner scan = new Scanner(System.in);
String s1 = scan.next();
char s2 = s1.charAt(0);
String s3 = s1.substring(1) + s2;
s3 = new StringBuilder(s3).reverse().toString();
if(s1.equals(s3))
System.out.println("They are same");
else
System.out.println("They are not the same");
}
}
This is very simple with some of observation. Your question is you have to move the first latter to the end and check reverse if the new string is same or not.
My ovservation:
For BANANA new string is ANANAB. Now reverse the string and check weather it is same as the first one.
Now If you ignore the first char B the string will be ANANA. As you have to reverse the string and check this one is same as the first one so this is like palindrome problem. For the input BANANA ANANA is palindrome. We are moving the first char to the end so there is no impact of it on checking palindrome. So I ignore the first char and check the rest is palindrome or not.
The Method is like:
private static boolean getAns(String word) {
int st = 1;
int en = word.length() - 1;
while (st < en) {
if (word.charAt(en) != word.charAt(st)) {
return false;
}
st++;
en--;
}
return true;
}
The main function is:
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Input your String:");
String word = scanner.nextLine();
boolean ans = getAns(word);
System.out.println("You have entered " + word + ". Is " + word.substring(1) + word.charAt(0) + " same as " + word + "? : " + ans + ".");
}
The Runtime for this problem is n/2 means O(n) and no extra memory and space needed,
I have tried to code it. See if it helps
import java.util.Scanner;
class StringCheck
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String str = new String();
String tempstr = new String();
System.out.println("Enter your String ");
str = sc.next();
int len = str.length();
//putting first character of str at last of tempstr
for (int i = 1 ; i<len; i++)
{
tempstr += str.charAt(i);
}
tempstr += str.charAt(0);
//reversing tempstr
char[] tempchar = tempstr.toCharArray();
int j = len-1;
char temp;
for ( int i = 0; i<len/2 ; i++)
{
if(i<j)
{
temp = tempchar[i];
tempchar[i] = tempchar[j];
tempchar[j]= temp;
j--;
}
else
break;
}
//reversing completed
tempstr = new String(tempchar);
// System.out.println("the reversed string is "+tempstr);
if(str.compareTo(tempstr)==0)
{
System.out.println("true");
}
else
{
System.out.println("false");
}
}
}
I was writing some code for my class and I ran into this error, String index out of range. I checked to see if it might be the string = null but that's not the case. I'm guessing it has to do with my if statement in the method but I couldn't find how to fix it anywhere. Any help is appreciated, thank you very much!
import java.util.*;
public class Occurences {
public static void main(String[] args) {
int check = 0;
char characterInput = ' ';
do {
Scanner scan = new Scanner(System.in);
System.out.println("Please enter a string: ");
String input = scan.next();
System.out.println("Enter a character to find it's occurence in the string: ");
characterInput = scan.next().charAt(0);
int i = count(input, characterInput);
System.out.println(characterInput + ", is in " + input + ", " + i + " times.");
System.out.println("To continue enter any number, to exit enter -1: ");
check = scan.nextInt();
} while (check != -1);
}
public static int count(String input, char characterInput) {
int cnt = 0;
int j = input.length();
while (j > 0) {
if (input.charAt(j) == characterInput) {
cnt += 1;
}
j--;
}
return cnt;
}
}
The error happens on line 21: int j = input.length(), as others mentioned in the comments, java, and most programming languages, index strings and array types by zero-indexing - starting from zero. So you have to either 1) start counting at 0 or 2) stop counting at one-less-than the length of the string(array), which is why line 21 needs to be either:
int j = input.length()-1;
or as you solved it using method 1:
setting int j=0;
I am not able to figure out how to compare what the user guessed to the letters in the word and change the blanks to the letters guessed.
package hangman;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
public class HangMan {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// user intro
System.out.println("Hello welcome to HangMan");
System.out.println("The obecjt of this game is to guess all the letters of the word.");
System.out.println("You get three tries");
//create an arraylist to store the words that will be guessed
ArrayList<String> wordBank = new ArrayList<>();
//assign words to the wordbank in the array list
wordBank.add("car");
wordBank.add("house");
wordBank.add("girl");
wordBank.add("boy");
wordBank.add("farm");
//create the random object generator
Random rand = new Random();
//this variable holds the random number generated
int numberStored;
numberStored = rand.nextInt(5);
//the random number generated will link to the index of the arraylist to generate the random word
String randomWord;
randomWord = wordBank.get(numberStored);
//display dots to show number of letters in the word
for (int j = 0; j < randomWord.length(); j++) {
System.out.printf("_ ");
}
//create scanner object
Scanner input = new Scanner(System.in);
//this while loop controls the number of guesses
int wrongGuesses = 0;
while (wrongGuesses != 3) {
//prompt
System.out.printf("Guess a letter you think is in the word");
//create a variable to hold the guessed letter
String guessLetter = input.nextLine();
//check to see if guessed letter is in the random word
boolean value = randomWord.contains(guessLetter);
// if else statment to decide what to do
if (value == true) {
System.out.println("Letter " + guessLetter + " is correct");
System.out.println("Now guess a different letter");
//find the position of the guessed letter in the word
//char g = randomWord.charAt(0);
//loop through all the letters of the word
//for (int j = 0; j < randomWord.length(); j++){
// if (gueesLetter.eq)
// int comparedstring
//}
} else {
System.out.println("Sorry "+guessLetter+ " is not in the word");
System.out.println("Try again");
wrongGuesses = wrongGuesses + 1;
}
System.out.println("random word = " + randomWord);
}
}
}
I need to match the guessed letters with and replace them in the _ _ _ setup.
One way to do this is:
public static void main(String[] args) {
String currentWord = "hello";
List<Character> guessedCharacters = new ArrayList<Character>();
guessedCharacters.add('e');
guessedCharacters.add('o');
guessedCharacters.add('q');
guessedCharacters.add('i');
System.out.println(maskString(guessedCharacters, currentWord));
}
private static String maskString(List<Character> guessedCharacters, String currentWord){
char[] currentWordList = currentWord.toCharArray();
StringBuilder maskedString = new StringBuilder();
int tempLength;
for(char letter : currentWordList){
tempLength = maskedString.length(); //store the current length of the string
for(char guessedLetter : guessedCharacters){
if(letter == guessedLetter){
maskedString.append(letter);
}
}
if(tempLength == maskedString.length()){// if the string is still the same length,
// then the tested letter hasn't been guessed yet.
// if the letter hasn't been guessed the we 'mask' it with an underscore.
maskedString.append('_');
}
}
return maskedString.toString();
}
Output:
_e__o
The code works the first time through. But after that, the output doesnt work.
The main goal of this is to create an infinite loop, of asking a user for a phrase, then a letter. Then, to output the number of occurences of the letter in the phrase.
Also - - how would i go about breaking this loop by entering a word?
Scanner in = new Scanner(System.in);
for (;;) {
System.out.println("Enter a word/phrase");
String sentence = in.nextLine();
int times = 0;
System.out.println("Enter a character.");
String letter = in.next();
for (int i = 0; i < sentence.length(); i++) {
char lc = letter.charAt(0);
char sc = sentence.charAt(i);
if (lc == sc) {
times++;
}
}
System.out.print("The character appeared:" + times + " times.");
}
Remove the for loop and replace it with a while.
The while loop should check for a phrase and it will drop out automatically when the phrase is met.
So something like
while (!phraseToCheckFor){
// your code
}
This sounds like homework so I won't post all the code but this should be enough to get you started.
If you need an infinite loop, just do this:
for(;;) { //or while(true) {
//insert code here
}
You can break the loop by using the break statement, for example like this:
for(;;) {
String s = in.nextLine();
if(s.isEmpty()) {
break; //loop terminates here
}
System.out.println(s + " isn't empty.");
}
In order for your program to run correctly, you need to consume the last new line character. You can do this by adding a call to nextLine.
Working example,
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
for (;;) {
System.out.println("Enter a word/phrase");
String sentence = in.nextLine();
if (sentence.trim().equals("quit")) {
break;
}
int times = 0;
System.out.println("Enter a character.");
String letter = in.next();
for (int i = 0; i < sentence.length(); i++) {
char lc = letter.charAt(0);
char sc = sentence.charAt(i);
if (lc == sc) {
times++;
}
}
System.out.println("The character appeared:" + times + " times.");
in.nextLine();//consume the last new line
}
}