-2

My assignment is to write a program to scramble a word while maintaining the same first and last letter and only swapping two letters, then prompt the user to continue if they wish.

Example: userInput = bacon | Output = bcaon

I've attached an imagine of my program, there may be several issues, but as it stands I can't really run it due to the errors in the image. I'm really confused because I got a TA to help me on this assignment, and they seemed to think this would definitely work, but as you can see it does not.

I would really appreciate if someone could tell me what exactly is wrong and why. And if you have anything to add to make this program work, I'd really, really appreciate that too, but bottom line is I just want to understand what's wrong and why.

import java.util.Scanner;
import java.util.Random;
public class FreeStyle {

public static void main(String[] args) {

    Scanner in = new Scanner(System.in);                        // Importing and initializing keyboard to 'in'
    System.out.println("Please enter a word to be scrambled"); // Asking user for a word
    String word = in.next();                               // Initializing the user's input 
    System.out.println(swapLetters(word));                    

    System.out.println("Would you like to enter another word? y/n");
    String answer = in.next();
    boolean userDone = true; //Using a Boolean statement to ask the user if they are done enter words or not
    while (userDone) {

        if (answer.equals('y')) {
            System.out.println("Please enter a new word");      //Ask user for new word to scramble
            word = in.nextLine();                                   //New initialization for 'word'
        } else if (answer.equals('n')) {                            //If user types 'n', loops then breaks because while(userDone) is false
            userDone = false;
        } else {
            System.out.println("Invalid input, please enter more than 3 letter words."); // The logic doesn't flow or apply to words that are less than 4 letters, so this catches that error and notifies the user
        }
    }
}

private static String swapLetters(String word) { //Private method used for the program only, no need to involve the user

    Random r = new Random(); //Using random instead of math floor
    //int arraysize = word.length();
    int a = r.nextInt(word.length()-2)+1; 
    int b = r.nextInt(word.length()-2)+1;
    //String word2 = word.substring(a, a+1);    
    String word2 = word.substring(0, a) + word.charAt(b)+word.substring(a+1, b)+word.charAt(a)+word.substring(b+1);
    return word2;
}
dimwittedanimal
  • 582
  • 1
  • 11
  • 24
Josh
  • 41
  • 6
  • Scanner nextline returns empty string after calling next https://stackoverflow.com/q/13102045/318758 Your scrambling method should check the length of the word so it doesn't try to scramble words shorter than 3 letters – Joni Mar 13 '19 at 00:38
  • Added the actual code, instead of an image, sorry about that. First post. – Josh Mar 13 '19 at 00:49
  • CTRL + A, CTRL + C, CTRL + V to your question. – FailingCoder Mar 13 '19 at 00:52

3 Answers3

2

Several points:

  1. Why not use something already done exactly for what you are trying to do - Collections.shuffle? See comments in the code for understanding how it works.
  2. You can't use equals() between a String and a char (' ' are for chars, " " are for Strings). Simple fix - just put your 'y' into "y", same for 'n'.
  3. I've refactored the code at the beginning that we used to get user input and then scramble into a separate method, so we can reuse it again - getInputAndScramble.
  4. And finally, I've used a do-while loop to keep looping until the user stops the loop with the "n" letter.

Please see my comments in the code, hopefully will clear things up.

public class Scrambler {

    public static void main(String[] args) {

        boolean userDone = true; 
        String word;

        Scanner in = new Scanner(System.in);                      
        getInputAndScramble(in); //Extracted method to get Scanner input and scramble

        do {
            System.out.println("Would you like to enter another word? y/n");
            word = in.next();
            while (userDone) {
                if (word.equals("y")) {
                    getInputAndScramble(in);
                    break;
                } else if (word.equals("n")) {                          
                    userDone = false;
                } else {
                    System.out.println("Invalid input, please enter more than 3 letter words."); 
                }
            }
        } while (userDone); //continue until "n"
    }

    private static void getInputAndScramble(Scanner in) {
        System.out.println("Please enter a word to be scrambled"); 
        String word = in.next();                               
        System.out.println(swapLetters(word));
    }

    private static String swapLetters(String word) { 

        /* Convert word into an ArrayList of characters. 
           Create ArrayList size of word, 
           convert String word into a char array and insert every char in                
           the char array into our ArrayList.
        */

        ArrayList<Character> chars = new ArrayList<>(word.length());
        for (char c : word.toCharArray()) {
            chars.add(c);
        }

        //Shuffle, omitting first and last letters
        Collections.shuffle(chars.subList(1, chars.size()-1));

        //Add shuffled letters into an array to output as a word entity
        char[] shuffled = new char[chars.size()];
        for (int i = 0; i < shuffled.length; i++) {
            shuffled[i] = chars.get(i);
        }
        //Return shuffled String
        return new String(shuffled);
    }
}
vs97
  • 5,519
  • 2
  • 22
  • 35
  • That definitely works, and you did clear a lot up for me, I really appreciate that. It doesn't hold the first and last letter in the same place, but I believe I can get that part. Other than that, very impressive and thank you very much. – Josh Mar 13 '19 at 01:34
  • @JoshBankston fixed it - Collections.shuffle(chars.subList(1, chars.size()-1)); - we shuffle a subList of the char List, starting from index = 1 and ending with second to last index, i.e. first and last letters are not touched. – vs97 Mar 13 '19 at 01:36
  • Definitely! No more help needed, this community is incredible. You guys accomplished explaining this to me and helped it all make sense, believe it or not I've been on this project for over 10 hours with several others, you answered all my questions in a mere 15 minutes. Thanks so much! – Josh Mar 13 '19 at 01:42
1

You are assuming that the two random number a and b have the property that a < b. What if a >= b? Then word.substring(a+1, b) will throw an error.

To fix it, just make sure that a < b is maintained (regenerating, swapping, etc.).

But to be sure, there are more than just this bug in your code. For example, using next(), comparing String with char, using wrong newline character, not striping newline character, and so on. You might want to add some print statements in your code you see what is actually happening.

lnyng
  • 792
  • 6
  • 17
  • That line of code isn't used here, someone suggested that, however it didn't work so I went with: String word2 = word.substring(0, a) + word.charAt(b)+word.substring(a+1, b)+word.charAt(a)+word.substring(b+1); and as far as a< b, I did as you said and put a loop there. The problem is it says string index is out of range at java.lang.String.substring(Unknown Source) at FreeStyle.swapLetters(FreeStyle.java:42) at FreeStyle.main(FreeStyle.java:10) – Josh Mar 13 '19 at 01:14
1

Well, as for the swapping function, something like that should work:

private static String swapLetters(String word) {
char[] temp = word.toCharArray();
    char swapHelper;
    Random r = new Random();
    int a = r.nextInt(word.length()-2)+1;
    int b = r.nextInt(word.length()-2)+1;
    swapHelper = temp[a];
    temp[a] = temp[b];
    temp[b] = swapHelper;
    word = String.copyValueOf(temp);
    return word;
}

Basically, im converting string to char array so i can operate on them with ease. A and B are variables that contain index of letters that should be swapped. After that, array is converted back to string and returned.

ferals
  • 19
  • 2
  • That makes perfect sense, please forgive me we just covered arrays yesterday. And Thank you for taking time out to help me with this, I appreciate it! – Josh Mar 13 '19 at 01:41
  • You're welcome. There is nothing wrong with not knowing something - that's the part of learning, after all, so dont be ashamed. – ferals Mar 13 '19 at 01:43