简体   繁体   中英

How to populate an array (like hangman) based on a guess

What I am trying to do is take a hidden String and then display it letter by letter in a random sequence every time the user presses the hint button. Currently, every time the hint button is pressed the entire solution displays once per character of the solution.

I am trying to make it so that when the hint button is pressed a random character from the string solution appears in the correct location. I am unsure about how to compare the location of the generated character to the string location.

  public String letterGenerator(int count, String word) {
//String word is taken from another function and it is based on the current displayed card and associated answer
    StringBuilder string = new StringBuilder();
    Random rng = new Random();

    char[] letters = word.toCharArray();
    char[] answers = new char[letters.length];

   int selected = rng.nextInt(letters.length);

    for (int i = 0; i < word.length(); i++) {
        if (i == selected) {
                letters[i] = answers[i];
            }
        string.append(letters);
    }
    return string.toString();
}

For example if the answer is "a wallet" this code outputs the solution as "a walleta walleta walleta walleta walleta walleta walleta walleta" (It displays the output 8 times because it prints the solution once per character including blank spaces)

What it should be doing for each press of the hint button would be to display each character in a random order like so: Press 1: "_ _ _ l_ _ _" Press 2: "a _ _ l_ _ _" Press 3: "a _ _ l _e _", and so on until the entire word appears on screen

Any help is appreciated!

Well, you append(letters) to your output for each iteration of your loop, and letters is an array of all your letters, not just one of them. So of course you end up with that output that you got.

But I think you can design this in a more elegant, and more object-oriented way. Instead of two character arrays for the answer and what is displayed, maybe make just one array of 'Letters'. This means you create a custom class Letter , which could hold the information whether it is 'solved' or not. Like so:

public class Letter{
   char character;
   boolean solved;
   // ... Constructor, Getters, Setters
}

Then, you can just pass your array of letters to a method that selects a random letter that is not solved yet, and simply switch its solved property to true . Your code for displaying the thing to your user would then be something like this:

for(Letter letter : letterArray){
   System.out.print(letter.isSolved() ? letter.getCharacter() : "_");
}

If I've understood correctly, then here's a few things to change;

1) You want to remember the last revealed hint, but you've stored it in a local variable. You'll want a way to store the revealed letters. How you do that depend on how the rest of your class is setup, but either passing it back as part of the method return or setting a global variable should do

2) Since you are remembering the previous hints, you'll want to make sure that 'selected' has not been revealed before. Perhaps store what letter positions have been revealed before and compare against them.

3) I would put the internal of the loop more as

for (int i = 0; i < word.length(); i++) {
    if(i == selected){
        string.append(letters[i]);
    }else{
        string.append("_");
    }
}

I hope this helps

Edit: I've changed the for loop, now it should work as you wanted. Sorry I should have been more careful to start with.

As for storing the previously revealed letters, if you are using a Singleton class then it would be acceptable to store this values in another list. My suggestion would be to keep an ArrayList of revealed values, then do something like;

List<Integer> revealed = new ArrayList<>();
Random rng = new Random();

public int getNextSelected(int length){
    int selected = rng.nextInt(length);
    if(revealed.contains(selected)){
        return getNextSelected(length);
    }
    return selected;
}

public String letterGenerator(int count, String word) {
    ...
    int selected = getNextSelected(letters.length);
    for (int i = 0; i < word.length(); i++) {
        if (i == selected){
            string.append(letters[i]);
        } else if (revealed.contains(i)) {
            string.append(letters[i]);
        } else{
            string.append("_");
        }
    }
    revealed.add(selected);
    return string.toString();
}

This should do what you need. There's plenty of ways to clean up the code, the suggestion by user3237736 is quite nice as it follows the 'tell don't ask' principle, but the design decisions of the class is up to you

public class SOEN_student {
public static void letterGenerator(String word) {
    //String word is taken from another function and 
    //it is based on the current displayed card and associated answer
        StringBuilder string;
        Random rng = new Random();
        char[] letters = word.toCharArray();
        char[] answers = new char[letters.length];
        boolean[] visited=new boolean[letters.length];
        int selected;
        for (int i = 0; i < word.length(); i++) {
            do{
                selected=rng.nextInt(letters.length);
            }while(visited[selected]);
            string=new StringBuilder();
            for(int j=0;j<word.length();j++){
                if(visited[j] | j==selected){
                    visited[selected]=true; 
                    string.append(letters[j]);
                }else{
                    string.append("_");
                }
            }
            System.out.print(string.toString()+" ");
        }
    }
public static void main(String... args){
        letterGenerator("a wallet");
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM