Attempting to change a dash to a letter with loop - java

So I'm writing a program for this brand new, never heard of game called hangman (ha.) and I'm having a really hard time writing a loop that will give me the results I want. I'm stuck at the point where a correct letter has been guessed (via button press) and revealing the correct letters in the line of dashes that represent the hidden word. Now when I run this loop, my tester popup still pops up "Match!---" or however many dashes the current secret word has. It's literally as if the replaceAll doesn't actually replace it! I've been stumped on this for hours now with no break so it would not surprise me if it is something extremely obvious I am missing.
JButton btnA = new JButton("A\n");
btnA.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
String letter = "a";
char ch = 'a';
if (go.getWordInQuestion().contains(letter)) {
for(int i = 0; i<go.getWordInQuestion().length(); i++) {
//Replace dashes with correctly guessed letter
if(go.getWordInQuestion().charAt(i)== 0)
go.getGuessLength().replaceAll("[^" + letter + "]", "_").charAt(i);
}
//check to see what the new value of the "hidden word" getGuessLength looks like
JOptionPane.showMessageDialog(null, "Match! " + go.getGuessLength());
txtGuess.setText("" + go.getGuessLength());
} else
JOptionPane.showMessageDialog(null,"No Match :(");
}
});
*****EDIT*******
Ok so I've made progress (I think). I have now written a loop that changes the dashes to letters!! The only problem? it changes all of them. -___- So now when I press button A, if theres a match, instead of ---, it will read aaa. I definitely realize this issue is probably extremely elementary but when it comes to java, I'm a slow learner! I appreciate all the positive and informative feedback!
JButton btnA = new JButton("A\n");
btnA.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
String letter = "a";
StringBuilder guessA = new StringBuilder('a');
for(int i = 0; i<go.getGuessLength().length();i++) {
if(go.getWordInQuestion().charAt(i)=='a') {
String partialWord = go.getGuessLength().replace("-", letter);
txtGuess.setText(partialWord);
JOptionPane.showMessageDialog(null,"Match! " + partialWord);
}
}
}
});
*****EDIT TWO******
Alright! I think I have finally resolved the issue thanks to your guys help! When a user presses the 'A' button, and if there is an A in the hidden word, it is now successfully replaced with a dash! woohoo!
btnA.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
String letter = "a";
StringBuilder guessA = new StringBuilder(go.getGuessLength());
if(go.getWordInQuestion().contains(letter)) {
for(int i = 0; i<go.getGuessLength().length();i++) {
if(go.getWordInQuestion().charAt(i)=='a') {
StringBuilder partialWord = guessA.replace(i,i+1, letter);
txtGuess.setText(guessA.toString());
JOptionPane.showMessageDialog(null,"Match! " + partialWord);
}
}
} else
JOptionPane.showMessageDialog(null, "Incorrect");
}
});

This line of code doesn't do anything:
go.getGuessLength().replaceAll("[^" + letter + "]", "_").charAt(i);
replaceAll() doesn't modify the String (Strings are immutable in Java). It returns a new String where the characters have been replaced. You're calling charAt(i) on this new String, and don't do anything with this char.

replaceAll() uses a regex as its target for replacement. You probably just want replace(), which still replaces all matches but uses plain characters for its target.
That said, the simplest solution is just one line of code that uses replaceAll() and turns the guessed letters into a regex that matches all other letters.
Given:
String word = "foo"; // the word people are trying to guess
String guesses = "one"; // the characters guessed so far
Here's the one line that will produce the required output:
String display = word.replaceAll("[^" + guesses + "]", "-");
When executed with the above values, display will be -oo.

Related

How can I remove a £ symbol from an array object and save it?

I'm coding a basic chatbot for a University project. I'm up to a point where the user must set a budget by entering an amount. At the moment, the program is able to search for a number in the user's message and save it correctly. However, when a £ sign is prefixed to it, it can't save as an integer due to having the pound sign in the message.
This is my code:
//Scan the user message for a budget amount and save it.
for (int budgetcount = 0; budgetcount < words.length; budgetcount++)
{
if (words[budgetcount].matches(".*\\d+.*"))
{
if (words[budgetcount].matches("\\u00A3."))
{
words[budgetcount].replace("\u00A3", "");
System.out.println("Tried to replace a pound sign");
ResponsesDAO.budget = Integer.parseInt(words[budgetcount]);
}
else
{
System.out.println("Can't find a pound sign here.");
}
}
I have previously tried .contains(), and other ways of indicating that it is a pound sign that I want to remove but I still get the "Can't find a pound sign here." print out.
If anybody can offer advice or correct my code I would appreciate it greatly.
Thanks in advance!
Strings in JAVA are immutable. You are replacing but never assigning back the result to words[budgetcount].
Change the following line in your code,
words[budgetcount] = words[budgetcount].replace("\u00A3", "");
Here is another way to do it by using Character.isDigit(...) to identify a digit and knitting a digit-only String which can later be parsed as an Integer,
Code Snippet:
private String removePoundSign(final String input) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
if (Character.isDigit(ch)) {
builder.append(ch);
}
}
return builder.toString();
}
Input:
System.out.println(removePoundSign("£12345"));
Output:
12345
You can also use String.replaceAll method.
Code snippet:
public class TestClass {
public static void main(String[] args){
//Code to remove non-digit number
String budgetCount = "£34556734";
String number=budgetCount.replaceAll("[\\D]", "");
System.out.println(number);
//Code to remove any specific characters
String special = "$4351&2.";
String result = special.replaceAll("[$+.^&]",""); // regex pattern
System.out.println(result);
}
}
Output:
34556734
43512

How can I randomly display a single character from a given word

Here is an update as to where I am at and what I am stuck on based on what #camickr suggested. The issue that I am coming across now is that since I have to have a return statement at the end I can only return the ArrayList letters.
Also every time the hint button is pressed only one character appears in the solution location and it is [], yet no actual letters that make up the solution appear.
public String generateLetterHint(int count, String word) {
String[] answerArray = word.split("");
ArrayList<String> letters = new ArrayList<String>(Arrays.asList(answerArray));
//StringBuilder string = new StringBuilder();
Collections.shuffle(letters);
while (!letters.isEmpty()) {
String letter = letters.remove(0);
System.out.println(letter);
}
return letters.toString();
}
Any help is appreciated!
One way it to add each (unique) letter of the String to an ArrayList.
Then you can use the Collections.shuffle(...) method to randomize the letters.
Each time the "Hint" button is pressed you:
get the letter at index 0
"remove" the letter from position 0
give the hint.
Now the next time the "Hint" button is clicked there will be a different letter at index 0.
Of course each time the user guesses a correct letter you would need to "remove" that letter from the ArrayList as well.
Edit:
Simple example showing proof of concept:
import java.util.*;
public class Main
{
public static void main(String[] args) throws Exception
{
String answer = "answer";
String[] answerArray = answer.split("");
ArrayList<String> letters = new ArrayList<String>(Arrays.asList(answerArray));
Collections.shuffle( letters );
while (!letters.isEmpty())
{
String letter = letters.remove(0);
System.out.println(letter);
}
}
}
In you real code you would only create the ArrayList once and do the shuffle once when you determine what the "answer" word is.
Then every time you need a hint you can simply invoke a method that does:
public String getHint(ArrayList letters)
{
return (letters.isEmpty() ? "" : letters.remove(0);
}
This will simply return an empty string if there are no more hints. Although a better solution would be to disable the hint button once the hints are finished.
Its working for only one answer. You can modify then work with multiple answer at the same time. When you you send a string to function, it gives you a letter that is unique inside from the string.
package com.Stackoverflow;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class RandomlyString {
private static List<Character> selectableLetters; // it store randomly selectable letters
private static boolean isFirst = true;
private static char letterHint(String answer) {
Random rnd = new Random();
// when function starts in first time, split the string letter by letter
if (isFirst) {
selectableLetters = splitString(answer);
}
isFirst = false;
if(!selectableLetters.isEmpty()) {
int hintIndex = rnd.nextInt(selectableLetters.size()); // select a letter randomly
char hint = selectableLetters.get(hintIndex); // put this letter to hint
selectableLetters.remove(hintIndex); // then remove this letter from selectableLetters, this is for don't select the same letter twice
return hint;
} else {
System.out.println("There is no hint!");
return ' ';
}
}
private static List<Character> splitString(String string) {
List<Character> chars = new ArrayList<>();
// split the string to letters and add to chars
for (char c: string.toCharArray()) {
chars.add(c);
}
return chars;
}
public static void main(String[] args) {
String answer = "Monkey";
for(int i=0; i<7; i++) {
System.out.println("Hints: " + letterHint(answer)); // it writes hint to screen
System.out.println("Other letters: " + selectableLetters); // currently selectable letters for hint
}
}
}

How do you take part of a string and move the first few letters to the end of the string

I am trying to take a user inputted string and move the first letters before the first vowel to the end of the string. I'm stuck here, and just need a suggestion.
This is in java by the way
Find the index at which the first vowel is (suppose x), then use substring..
String modified = mystring.substring(x, mystring.length()) + mystring.substring(0, x);
Read the api for what substring actually does.
Okay. Here's the main method of the program that does what you need.
public static void main(String args[]){
String s;
int i=0;
//presume s gets user's input here
for(i=0;i<s.length();i++){
char c=s.charAt(i);
if(c=='a'||c=='A'||c=='e' || ...)
break;
}
if(i!=(s.length()-1)){
for(int j=i;j<s.length();j++)
System.out.print(s.charAt(j));
//displays from first vowel to end of string
}
else{
System.out.println("String ain't got any vowels.");
}
}

Trying to create an Acronym out of user input

Hello I am working on an assignment and I'm running into issues I was hoping for a little direction...
The purpose is to have user input a phrase and create an acronym out of that phrase. Anything over three words will be ignored.
I'm having issues with the acronym part, I am able to get the first character and figured that I would loop through the user input and grab the character after a space, but that is not working. All I am getting is the first character, which is obvious because I grab that first, but I can't figure out how to "save" the other two characters. Any help is greatly appreciated.
*********UPDATE************************
So thanks to an answer below I have made progress with using the StringBuilder. But, now if I enter "Your Three Words" the Output is: YYYYYTYYYYYWYYYY
Which is progress but I can't understand why it's repeating those first characters so many times??
I edited the code too.
*********UPDATE*****************************
public class ThreeLetterAcronym {
public static void main(String[] args) {
String threeWords;
StringBuilder acronym = new StringBuilder();
Scanner scan = new Scanner(System.in);
System.out.println("Enter your three words: ");
threeWords = scan.nextLine();
for(int count = 0; count < threeWords.length(); count++) {
acronym.append(threeWords.charAt(0));
if(threeWords.charAt(count) == ' ') {
++count;
acronym.append(threeWords.charAt(count));
}
}
System.out.println("The acronym of the three words you entered is: " + acronym);
}
}
You can't save the other characters because char is supposed to store only one character.
You can use a StringBuilder in this case
StringBuilder acronym = new StringBuilder();
Then in your loop simply replace it with
String[] threeWordsArray = threeWords.split(" ");
for(String word : threeWordsArray) {
acronym.append( word.substring(0, 1) );
}
**updated
You store the character at the current index in space:
char space = threeWords.charAt(count);
Then you compare the value of space with the integer value 3:
if(space < 3)
This will almost certainly never be true. You are asking for the numeric value of a character. Assuming it is a letter it will be at least 65. I suspect that your intention is to store something different in the variable space.

Why is method not working as I thought it would?

I am attempting to create a hangman game. I have everything working as I want so far with the exception of one method. This method is called processGuess and takes a String letter and two String arrays as parameters. The first array is an array called spaceArray and contains Underscores that match the length of the word being guessed (example: hello produces [ _ , _ , _ , _ , _ ]). The second array is called wordArray and contains the word the user is trying to guess.
The way I envision my method working is as follows:
Create an array that stores all guessed letters (guessArray)
Create a counter that keeps track of the number of guesses (guessCounter)
Use a for loop to iterate through each letter of the word and compare it with the letter the user guessed.
a. If the letter is in the word, add the letter to the correct index of the spaceArray
Compare spaceArray to wordArray
a. If equal, print something saying they won in x number of guesses
b. If not equal.
Print spaceArray
Call the method that asks user to guess the next letter
Call this method so that the new guessed letter is processed.
The problem is that when I recall this method, it does not contain the new letter but still contains the old letter. I am unsure of what I am doing wrong. This is the first time that I have tried using methods within a method.
Here is my method:
public static void main(String[] args) throws FileNotFoundException {
Scanner file = new Scanner(
new File("C:/FilesForJava/ScrabbleDictionary.txt"));
instructions();
String[] dictionary = createDictonaryArray(file);
String[] randomWord = getRandomWord(dictionary);
String[] underscoreArray = showSpaces(randomWord);
String letter = getGuesses();
processGuess(letter, underscoreArray, randomWord);
}
public static void instructions() {
System.out.println("Let's play hangman!");
System.out.println();
}
public static String[] createDictonaryArray(Scanner inputFile)
throws FileNotFoundException {
int wordCount = 0;
while(inputFile.hasNext()) {
String word = inputFile.next();
wordCount++;
}
String[] scrabbleDictionary = new String[wordCount];
Scanner file = new Scanner(
new File("C:/FilesForJava/ScrabbleDictionary.txt"));
while(file.hasNext()) {
for(int i = 0; i < wordCount; i++) {
scrabbleDictionary[i] = file.next();
}
}
file.close();
return scrabbleDictionary;
}
public static String[] getRandomWord(String[] dict) {
String word = dict[(int)(Math.random() * dict.length)];
String[] wordArray = new String[word.length()];
for(int i = 0; i < wordArray.length; i++) {
wordArray[i] = word.trim().substring(0, 1);
word = word.trim().substring(1);
}
return wordArray;
}
public static String[] showSpaces(String[] word) {
String[] spaceArray = new String[word.length];
for(int i = 0; i < word.length; i++) {
spaceArray[i] = "_";
}
System.out.println(Arrays.toString(spaceArray));
System.out.println();
return spaceArray;
}
public static String getGuesses() {
Scanner guess = new Scanner(System.in);
System.out.println("Guess a letter: ");
String letter = guess.next();
System.out.println();
//guess.close();
return letter;
}
public static void processGuess(String letter, String[] spaceArray,
String[] wordArray) {
int guessCounter = 0;
String[] guessArray = new String[spaceArray.length];
for(int i = 0; i < spaceArray.length; i++) {
guessCounter++;
guessArray[i] = letter;
String indexLetter = wordArray[i];
if(indexLetter.equalsIgnoreCase(letter)) {
spaceArray[i] = letter;
}
}
if(spaceArray.equals(wordArray)) {
System.out.println("Yes! You won in " + guessCounter + "guesses!");
}else {
System.out.println(Arrays.toString(spaceArray));
getGuesses();
processGuess(letter, spaceArray, wordArray);
}
}
You need to pass the new guess into your processGuess method. Try something like this:
else {
System.out.println(Arrays.toString(spaceArray));
String newLetter = getGuesses();
processGuess(newLetter, spaceArray, wordArray);
}
I think this method is trying to do too much. It's strange for it to read new input and call itself recursively -- I would have expected its caller to use a loop to solicit guesses from the player and call this method (which would not recurse) instead. The method might indicate by a return value whether the user had won.
Additionally, the code seems overly complex. For instance, what's the point of guessArray, which you instantiate and initialize but never use for anything?
Furthermore, it's strange that you use arrays of Strings instead of arrays of chars, since all your Strings seem to contain a single character each. (That might actually be appropriate if you are looking to accommodate surrogate pairs, but such a consideration seems a little out of character for the level of the task.)
In any event, the reason the recursive calls to your method see only the first letter guessed is that that's what you pass to them. The getGuesses() method does nothing to modify the local letter variable (nor can it do), and the method itself just passes along whatever was passed to it.
Well, it looks like you might have a couple of problems.
First, recursion is a very poor choice for this method, I think what you're looking for is a while loop where the condition changes when the strings are equal. Using recursion here needlessly increases the size of the stack as you call more and more methods, but never return from them.
Now as to your question, in the code you gave us, the variable letter never gets changed. I assume that get guesses returns a string? If thats true then you need to set letter equal to it.
I would also like to suggest that you use a char instead of a string.
public static void processGuess(String letter, String[] spaceArray,
String[] wordArray) {
while(true) {
int guessCounter = 0;
String[] guessArray = new String[spaceArray.length];
for (int i = 0; i < spaceArray.length; i++) {
guessCounter++;
guessArray[i] = letter;
String indexLetter = wordArray[i];
if (indexLetter.equalsIgnoreCase(letter)) {
spaceArray[i] = letter;
}
}
if (spaceArray.equals(wordArray)) {
System.out.println("Yes! You won in " + guessCounter + "guesses!");
break;
} else {
System.out.println(Arrays.toString(spaceArray));
letter = getGuesses();
}
}
}
You've written the method as a recursive method (probably not the best way to do it). The issue is that when a recursive method declares a local variable, each invocation of the recursive method has its own copy of the local variables.
Thus you call processGuess, which creates a guessArray. Then processGuess calls itself again, which has its own guessArray, and after this happens a few times, you'll have a stack that looks something like:
+--------------------------------------------------------+
+ processGuess#1 +
+ local variables: guessCounter#1, guessArray#1, i#1 +
+--------------------------------------------------------+ --> calls:
+ processGuess#2 +
+ local variables: guessCounter#2, guessArray#2, i#2 +
+--------------------------------------------------------+ --> which calls:
+ processGuess#3 +
+ local variables: guessCounter#3, guessArray#3, i#3 +
+--------------------------------------------------------+ --> which calls:
+ processGuess#4 +
+ local variables: guessCounter#4, guessArray#4, i#4 +
+--------------------------------------------------------+
When processGuess#4 modifies guessArray, it changes guessArray#4. But that has no effect on guessArray#3, guessArray#2, or guessArray#1. All of these are separate local variables, and they are references that refer to four different objects. Thus, when processGuess#4, processGuess#3, and processGuess#2 all return, the changes they've made to their own guessArray's are lost, and processGuess#1 will see only the changes that it, itself, has made to its own guessArray.
As I said, I wouldn't use recursion for this particular problem. But it's definitely a problem in other cases where recursion is the right way to do things. The solutions are: (1) declare the variable or object outside the recursive method, as an instance field in the object--then they will all be accessing the same variable; or (2) add a parameter to the recursive method so that the recursive invocations can share a reference to the same object.
[Note: The #1, #2 numbers I added are just to help explain things; they aren't part of any language syntax or anything like that.]

Categories