Changing the value of a field String variable - java

I'm currently working on a version of hangman through java. I've recently been stumped by a problem that I can't seem to solve.
I have an array easyDifficulty and a String hiddenWord. I want to make it so that every time the game starts, my method randomWord() will choose a random word from array easyDifficulty to start the program. Many of my methods use hiddenWord so I pasted all of my code below incase you need to check that. Otherwise, the main parts that I feel like that are causing problems are in the area where I declare my field variables, my randomWord method, and the main method.
import java.util.Arrays;
import java.util.*;
import java.util.Scanner;
public class HangmanGame {
static String[] easyDifficulty = new String[]{"orange", "jacket","shirt"
,"rocket","airplane","circle","balloon","swing","truck","caterpillar"};
static Random rand = new Random();
static String hiddenWord = new String("");
static char[] hiddenWordToChar = hiddenWord.toCharArray();
static int triesLeft = 6;
static boolean done = false;
static int length = hiddenWord.length();
static Scanner input = new Scanner(System.in);
final static int maxLength = 30;
static char[] repeatChecker = new char[30]; //this is to help prevent the user from putting the same char multiple times
static char[] fillWord = new char[length];
static int var;
static int var2;
static char underscore = '_';
static int chooseDifficultyInt;
public static String randomWord(int n) {
int randomNum = rand.nextInt(9);
int difficultyInt = n;
if (difficultyInt == 1){
//System.out.println(easyDifficulty[randomNum]);
return easyDifficulty[randomNum];
}
return null;
}
public static boolean contains(char[] arr, char i) {
for (char n : arr) {
if (i == n) {
return true;
}
}
return false;
}
public static boolean multiLetter(char[] arr, char i){
int multiple = 0;
for (char n : arr){
if (i == n){
multiple++;
//continue;
}
}
System.out.println(multiple);
if (multiple > 1){
return true;
}
else {
return false;
}
}
public static void createSpaces(int n){
for (int i = 0; i <= n-1; i++){
fillWord[i] = underscore;
}
System.out.println(fillWord);
}
public static void tryAgain(){
System.out.println("Would you like to try again? Enter Y/N to go again or quit!");
char goAgain = input.next().charAt(0);
goAgain = Character.toLowerCase(goAgain);
if (goAgain == 'y') {
triesLeft = 6;
repeatChecker = new char[20];
main(null);
}
else if (goAgain == 'n') {
System.out.println("Bye!");
System.exit(0);
}
else {
System.out.println("Invalid input");
tryAgain();
}
}
public static void arrayLetters(){
System.out.println("This is a " + length + " letter word. Please enter a letter to guess: ");
char charInput = input.next().charAt(0);
char[] letters = new char[20];
//This code only runs if the user inputs a letter that repeats
//throughout hiddenWord
if (multiLetter(hiddenWordToChar, charInput)){
for (int n = 0; n < length; n++){
char multiWordLetter = hiddenWord.charAt(n);
letters[n] = multiWordLetter;
if (letters[n] == charInput){
fillWord[n] = charInput;
}
if (contains(repeatChecker, charInput)){
System.out.println("You already did that word, try again!");
arrayLetters();
}
if (Arrays.equals(fillWord, hiddenWordToChar)){
System.out.println("Congratulations, you win! The word was '" + hiddenWord + "'!");
System.out.println("You completed the challenge in " + triesLeft + " tries! \n\n");
tryAgain();
}
}
System.out.println(fillWord);
System.out.println("Nice! There is a(n) " + charInput + " in this word!");
System.out.println("You have " + triesLeft + " tries left!\n");
arrayLetters();
}
//This block of code runs when the user input a letter that only occurs once
//in hiddenWord
for (int i = 0; i < length; i++){
char wordLetter = hiddenWord.charAt(i);
letters[i] = wordLetter;
if (contains(letters, charInput)){
/*
if (multiLetter(letters, charInput)){
System.out.println("aylmao");
}
*/
//System.out.println(multiLetter(hiddenWordArray, charInput));
if (contains(repeatChecker, charInput)){
System.out.println("You already did that word, try again!");
arrayLetters();
}
repeatChecker[var] = charInput;
var++;
fillWord[i] = charInput;
if (Arrays.equals(fillWord, hiddenWordToChar)){
System.out.println("Congratulations, you win! The word was '" + hiddenWord + "'!");
System.out.println("You completed the challenge in " + triesLeft + " tries! \n\n");
tryAgain();
}
System.out.println(fillWord);
System.out.println("Nice! There is a(n) " + charInput + " in this word!");
System.out.println("You have " + triesLeft + " tries left!\n");
arrayLetters();
}
if (i == length-1){
System.out.println("There is no " + charInput + " in this word!");
triesLeft--;
System.out.println("You have " + triesLeft + " tries left!\n");
if (triesLeft <= 0){
System.out.println("You failed!\n\n");
tryAgain();
}
arrayLetters();
}
}
}
public static void main(String[] args) {
System.out.println("Welcome to my hangman game!");
System.out.println("Please input your prefered difficulty level.");
System.out.println("1. Easy");
System.out.println("2. Medium");
System.out.println("3. Hard");
chooseDifficultyInt = input.nextInt();
randomWord(chooseDifficultyInt);
hiddenWord = randomWord(chooseDifficultyInt);
createSpaces(length);
arrayLetters();
}
}
I'm an intermediate in java programming so I've learned that Strings are immutable. Thus I've considered that the reason why hiddenWord won't be set equal to randomWord(chooseDifficultyInt); is because of that?

I'm an intermediate in java programming so I've learned that Strings are immutable
This often causes confusion among new programmers. This is correct, Strings are immutable. However the variable that points to that String can be re-assigned (assuming it isn't final).
You can modify your hidden word as many times as you like:
HangmanGame.hiddenWord = "MyNewWord";
HangmanGame.hiddenWord = "AnotherWord";
HangmanGame.hiddenWord = "ThisWorks";
You might be wondering how the hiddenWord is changing if Strings are immutable.
Your variable isn't actually changing. Every time you re-assign it, a new String is being created. This means that the Strings themselves are never modified.
So yes, you can call
HangmanGame.hiddenWord = HangmanGame.randomWord(n);
and it will work perfectly.

Your initialization of hiddenWord as new String(""); is useless. You could remove it safely.
When you do that:
hiddenWord = randomWord(chooseDifficultyInt);
you set hiddenWord to the reference of a random string of your predefined list, not allocating anything, just reusing an existing string reference.

Related

Java exception error causing code to stop suddenly

I was working on a project for class and everything works fine until the code the professor gave us that will prompt the user to "doOver" the code if they choose to, it's coming out with this error and I'm frankly confused.
I tried changing the sc.nextLine to a .hasNextLine as I've seen in other posts, but it comes up with an error stating it needs to be a boolean and then says I can not use the next doOver.trim() code on a boolean.
final static String TITLE = "ISBN-13 Generator!";
final static String CONTINUE_PROMPT = "\nDo this again? [y/n] ";
static Scanner input = new Scanner(System.in);
private static void process(Scanner sc, String args[]) {
boolean numberChecker;
String isbn;
do {
System.out.println("\nEnter the first 12 digits of an ISBN-13: ");
isbn = input.nextLine();
input.close();
isbn = isbn.trim();
numberChecker = true;
int s = 0;
do {
numberChecker = numberChecker && Character.isDigit(isbn.charAt(s));
s++;
} while (s < isbn.length() || numberChecker == false);
} while (isbn.length() != 12 & numberChecker == false);
int sum = 0;
int s = 0;
do {
if (s % 2 == 0) {
sum = sum + isbn.charAt(s) - 48;
} else {
sum = sum + 3 * (isbn.charAt(s) - 48);
}
s++;
} while (s < 12);
{
sum = 10 - (sum % 10);
if (sum == 10)
sum = 0;
}
System.out.println("Your ISBN is " + isbn + sum);
}
private static boolean doThisAgain(Scanner sc, String prompt) {
System.out.print(prompt);
String doOver = sc.nextLine();
return doOver.trim().equalsIgnoreCase("Y");
}
public static void main(String args[]) {
System.out.println("Welcome to " + TITLE);
Scanner sc = new Scanner(System.in);
do {
process(sc, args);
} while (doThisAgain(sc, CONTINUE_PROMPT));
sc.close();
System.out.println("Thank you for using the " + TITLE);
}
It should display "Do this again? [y/n]" with you inputting "y" to start the process over and entering "n" to stop and have the system print out ("Thank you for using the " + TITLE)
This is happening because you have closed the scanner instance already using line input.close();
Just comment out or delete input.close(); and your program will work as expected.
System.out.println("\nEnter the first 12 digits of an ISBN-13: ");
isbn = input.nextLine();
//input.close();
Let me know if it helps! :)

How would I make this so the while/else statement correctly repeats itself when the user input is incorrect?

I dont want it to say attempts remaining -1, i want it saying the 2 attempts after the 1st attempt is done, and it repeats the prompt of the user input.
I already tried looking on how to correctly do the 3 attempt thing, but for some reason, my program is not successfully doing it.
import java.util.*;
import java.util.Collections;
public class Anagrams extends ShuffleWord{
static Scanner input = new Scanner(System.in);
public static void main(String[] args)
{
int score1 = 0;
int score2 = 0;
int score3 = 0;
int attempts = 3;
Random r = new Random();
System.out.println("Your face looks familiar, what is your name?");
String name = input.nextLine();
System.out.println("Welcome " + name + " to Anagrams, a game where the word is shuffled and you have to unscramble the word correctly!");
System.out.println(" Please select a difficulty " + name + ", 1 being easy, 2 being normal, and 3 being hard.");
int difficulty = input.nextInt();
switch (difficulty) {
case 1:
// 6 letter words
final String[] wordlist1 = {"string", "switch", "system" , "static" , "public" , "python" , "method" };
String word1 = wordlist1[r.nextInt(wordlist1.length)];
System.out.println("Your scrambled word is:" + shuffle(word1));
System.out.println("Please type the word");
String thisisjustsoitworks1 = input.nextLine();
String userword1 = "";
final List<String> wordy1 = Arrays.asList(wordlist1);
while (attempts -- > 0 && !wordy1.contains(userword1));
{
userword1 = input.nextLine();
if (wordy1.contains(userword1))
{
score1 += 50;
System.out.println(name + ", Your current score is:" + score1);
}
else
{
System.out.println("Incorrect. Number of attempts remaining:" + attempts);
}
}
break;
case 2:
// 15-16 letterwords
final String[] wordlist2 = {"computerscience" , "primitivedatatype" , "booleandatatype" ,};
String word2 = wordlist2[r.nextInt(wordlist2.length)];
System.out.println("Your scrambled word is:" + shuffle(word2));
System.out.println("Please type the word");
String thisisjustsoitworks2= input.nextLine();
String userword2 = input.nextLine();
List<String> wordy2 = Arrays.asList(wordlist2);
if (wordy2.contains(userword2))
{
score2 += 150;
System.out.println(name +", Your current score is:" + score2);
}
else
{
System.out.println("game over");
}
break;
case 3:
final String[] wordlist3 = {"objectorientatedprogramming" , "primitivedatatype" , "booleandatatype" ,};
String word3 = wordlist3[r.nextInt(wordlist3.length)];
System.out.println("Your scrambled word is:" + shuffle(word3));
System.out.println("Please type the word");
String thisisjustsoitworks3 = input.nextLine();
String userword3 = input.nextLine();
List<String> wordy3 = Arrays.asList(wordlist3);
if (wordy3.contains(userword3))
{
score3 += 300;
System.out.println (name + ", you gained" + score3 + "points, your total score is;" + score3);
}
else
{
System.out.println("game over");
}
break;
default:
System.out.println("Invalid Difficulty");
}
}
}
Suffle method code
import java.util.concurrent.ThreadLocalRandom;
/* Java program to shuffle a word randomly5
*/
public class ShuffleWord {
//public static void main(String[] args) {
// ShuffleWord sw = new ShuffleWord();
//
// String word = "Hello";
//
// String shuffled = sw.shuffle(word);
//
// System.out.println("Original word:"+word);
//
// System.out.println("Shuffled word:"+shuffled);
/*
* Shuffles a given word. Randomly swaps characters 10 times.
* #param word
* #return
*/
public static String shuffle(String word) {
String shuffledWord = word; // start with original
int wordSize = word.length();
int shuffleCount = 10; // let us randomly shuffle letters 10 times
for(int i=0;i<shuffleCount;i++) {
//swap letters in two indexes
int position1 = ThreadLocalRandom.current().nextInt(0, wordSize);
int position2 = ThreadLocalRandom.current().nextInt(0, wordSize);
shuffledWord = swapCharacters(shuffledWord,position1,position2);
}
return shuffledWord;
}
/**
* Swaps characters in a string using the given character positions
* #param shuffledWord
* #param position1
* #param position2
* #return
*/
private static String swapCharacters(String shuffledWord, int position1, int position2) {
char[] charArray = shuffledWord.toCharArray();
// Replace with a "swap" function, if desired:
char temp = charArray[position1];
charArray[position1] = charArray[position2];
charArray[position2] = temp;
return new String(charArray);
}
}
Output
Your face looks familiar, what is your name?
thomas
Welcome thomas to Anagrams, a game where the word is shuffled and you have to unscramble the word correctly!
Please select a difficulty thomas, 1 being easy, 2 being normal, and 3 being hard.
1
Your scrambled word is:static
Please type the word
a
Incorrect. Number of attempts remaining:-1
attempts remaining -1 is getting printed because of ; at the end of while loop(case 1:) in your code.
while (attempts -- > 0 && !wordy1.contains(userword1));
Due to this, attempts is getting decremented to -1, and after that program is taking user input.

Java , storing strings into an array

I wish to put the raw questions(rawQuestions) as inputted in this way in command prompt:
java Hangman Hello test 123, into the array (questions). I know rawQuestion will not work down in the "store valid questions into an array" part because of
"error: ';' expected " and "error: not a statement"
in the line
" questions[vCount] = String rawQuestion; "
Therefore how should I rewrite it?
public class Hangman {
//Validation of raw questions
public static boolean isValidQuestion(String rawQuestion){
rawQuestion = rawQuestion.toUpperCase();
boolean vQuestion = true;
for(int i=0; i<rawQuestion.length(); i++){
char c = rawQuestion.charAt(i);
if(!(c>='A' && c<='Z'))
vQuestion = false;
}
return vQuestion;
}
public static void main(String args[]){
boolean vQs[] = new boolean[args.length];
for(int i=0; i<args.length; i++){
String rawQuestion = args[i];
boolean b = isValidQuestion(rawQuestion);
if(b)
System.out.println(rawQuestion + " is a valid question!");
else
System.out.println("Error: " + rawQuestion + ", input must be a word consist of a-z or A-Z");
vQs[i] = b;
}
//count the number of valid questions
int vCount = 0;
for(int i=0; i<vQs.length; i++){
System.out.println(i + " " + vQs[i] );
if(vQs[i])
vCount++;
}
System.out.println("There are " + vCount + " valid questions");
//store valid questions into an array
String questions[] = new String[vCount];
for(vCount=0; vCount<args.length; vCount++){
questions[vCount] = String rawQuestion;
System.out.println( questions[vCount] );
}
}
}
Try this:
String[] validQuestions = Arrays.stream(args)
.filter(Hangman::isValidQuestion)
.toArray(String[]::new);
int validQuestionCount = validQuestions.length;
But even without Streams, your whole method could be done in one for loop, counting and collecting the valid questions in one go instead of having three separate steps:
List<String> validQuestions = new ArrayList<>();
for (int i = 0; i < args.length; i++)
{
String rawQuestion = args[i];
boolean b = isValidQuestion(rawQuestion);
if (b)
{
validQuestions.add(rawQuestion);
System.out.println(rawQuestion + " is a valid question!");
}
else
{
System.out.println("Error: " + rawQuestion + ", input must be a word consist of a-z or A-Z");
}
}
// count the number of valid questions
System.out.println("There are " + validQuestions.size() + " valid questions");
// store valid questions into an array
String questions[] = validQuestions.toArray(new String[validQuestions.size()]);
This way, you do not have to juggle the index variables yourself, which is hard to understand, especially if somebody else tries to read it. (Especially the re-use of vCount is kinda scary to me)
I fixed something and commented, not sure if it works, i haven't compiled it.
public static void main(String args[]){
boolean vQs[] = new boolean[args.length];
int vCount=0;
for(int i=0; i<args.length; i++){
String rawQuestion = args[i];
if(isValidQuestion(rawQuestion)){
System.out.println(rawQuestion + " is a valid question!");
//Here you have enough data to count the valid questions, three loops are not needed.
++vCount;
vQs[i]=true;
}else{
System.out.println("Error: " + rawQuestion + ", input must be a word consist of a-z or A-Z");
vQs[i]=false;
}
}
System.out.println("There are " + vCount + " valid questions");
//store valid questions into an array
String questions[] = new String[vCount];
int j=0;
for(int i=0; i<args.length; i++){
//You need to iterate for all strings, because vQs[] is long args.length
if(vQs[i]){
//Ok the i-th question was valid, let's move it and print it
questions[j] = args[i];
System.out.println( questions[j] );
++j;
}
}
}
}

Converting parts of Strings to Character to be used in if/else statements

I'm doing an assignment in school and although I've checked through the entire written material I cannot for the life of me find out how to do this. We are supposed to enter strings like "0123 B" and the B at the end of the string is suppose to represent bronze and then add ++ to the Bronze integer. Then print the number of medals.
My issue here is that I'm trying to take the final character from the string (B, S, or G) and then add to that, but the thing is, it's a String and not a character. So I can't use medal.charAt(5).
Here is my code below:
EDITED, CODE IS SOLUTION
import java.util.Scanner;
public class CountMedals {
public static void main(String[] args) {
int bronze = 0;
int silver = 0;
int gold = 0;
int totalMedals = 0;
int incorrectMedals = 0;
char gol = 'G';
char sil = 'S';
char bro = 'B';
String medal = " ";
Scanner in = new Scanner(System.in);
System.out.println("Please enter the event number followed by the first letter of the medal type." +
" (I.E. \"0111" + " B\"). Type exit once completed");
while (!medal.equals("")) {
medal = in.nextLine();
if (medal.charAt(medal.length() - 1) == bro)
{
bronze++;
totalMedals++;
}
else if (medal.charAt(medal.length() - 1) == sil)
{
silver++;
totalMedals++;
}
else if (medal.charAt(medal.length() - 1) == gol)
{
gold++;
totalMedals++;
}
else if (medal.equals("exit"))
{
System.out.println("Gold medals: " + gold);
System.out.println("Silver medals: " + silver);
System.out.println("Bronze medals: " + bronze);
System.out.println("Total medals: " + totalMedals);
System.out.println(incorrectMedals + " incorrect medal(s) entered.");
}
else{
incorrectMedals++;
}
}
}
}
Just make gol, sil, and bro into chars instead of Strings.
char gol = 'G';
char sil = 'S';
char bro = 'B';
After that change, you should be able to use
medal.charAt(5) == gol
no problem.
Edit
To make this even more generic, you could use
medal.charAt(medal.length() - 1) == gol
which will always pull the last character, thereby avoiding errors with input that has less than 5 indices.

Program that will ask the user to enter size of the array, show all the values entered and tell if its positive or negative

I have this assignment for tomorrow and I'm a beginner please help. Must be JOptionpane :O I was wondering if I can use if else statement in showmessagedialog. Error says incompatible types required: int ( for holder=holder + "\n" + aw[x];
Here's what I've done so far(SORRY I'M A BEGINNER PLS UNDERSTAND):
public static void main(String[] args) {
String s;
int size;
int size2;
int holder;
s = JOptionPane.showInputDialog("Enter the size of the array");
size = Integer.parseInt(s);
String aw[]= new String[size];
for (int x=0; x<=aw.length-1; x++){
aw[x]=JOptionPane.showInputDialog("Enter value for array[" + x + "]");
size2 = Integer.parseInt(aw[x]);
}
for (int x=0; x<=aw.length-1;x++)
{
holder=holder + "\n" + aw[x];
}
JOptionPane.showMessageDialog(null, if (holder<0) { holder + " is negative" } else holder " is positive");
}
}'
holder is declared as an int, but in
holder=holder + "\n" + aw[x];
you try to assign it a String.
Use String to store your messge
String msg;
if (holder<0)
{
msg = holder + " is negative";
}
else
{
msg = holder " is positive";
}
JOptionPane.showMessageDialog(null,msg);
showMessageDialog function expects the second parameter to be String
Something you can not do:
1 Variable holder you declare is int type. It can not be used to do `+`` operation.
2 Two for -loop is not neccessary.
3 You forget to check whether the number entered is zero, you just have positive and negative logic.
4 When trying to use + opeartion for strings. Please use append method of StringBuilder.
Here is the code made based on the above 3 items.
public static void main(String[] args) {
String s;
int size;
int size2;
int holder = 0;
s = JOptionPane.showInputDialog("Enter the size of the array");
size = Integer.parseInt(s);
String aw[] = new String[size];
StringBuilder sb = new StringBuilder();
for (int x = 0; x <= aw.length - 1; x++) {
aw[x] = JOptionPane.showInputDialog("Enter value for array[" + x
+ "]");
size2 = Integer.parseInt(aw[x]);
if(size2 ==0)
{
sb.append(aw[x]).append(" is zero").append('\n');
}else if(size2 >0)
{
sb.append(aw[x]).append(" is positive").append('\n');
}else
{
sb.append(aw[x]).append(" is negative").append('\n');
}
}
JOptionPane.showMessageDialog(null, sb.toString());
}
The best approach is:
final String msg = holder == 0 ? "is zero" : (holder > 0 ? "is positive" : "is negative");
JOptionPane.showMessageDialog(null,msg);

Categories

Resources