Reputation: 103
im currently coding a Chat-Bot, for his answers I made the method following method:
// Choose Randomly From Given Answers
public String chooseAnswer(String... strings){
int i = (int) strings.length;
int random = (int)(Math.random() * i);
return strings[random];
}
That works totally fine. Now the following problem occurs: If the bot doesnt understand what the user said, he displays a random question or statement, for example.
chooseAnswer("Sounds great", "Whats your favorite color?", "Whats your favorite food?", "Tell me something");
The User can now answer, for example what his favorite color is. If he answered that once, the bot should never choose the question about his color again.
I have a variable for that, that counts how many times the user said something about his favorite color, so that isnt the problem.
Now it would be great if something like that would work:
chooseAnswer("Sounds great", if(favorite_color_count == 0){"Whats your favorite color?"}, "Whats your favorite food?", "Tell me something");
This obviously doesnt work.
I think i need an if statement outisde, but there are so many cases, because I have about 50 standard questions, so i would have to make one for every case und thats like i dont know.. 50+49+48...+2+1?
Has someone an idea how to handle this?
Upvotes: 1
Views: 125
Reputation: 250
You can try something like this:
Hashmap that stores the answers and a counter for one of them.
Before generating a random response, you only allow the ones that have the counter at 0.
When you send a response, you update the counter.
Note: it is not a very efficient solution has you will be iterating over the map every time.
Map<String, Integer> myMap = new HashMap<String, Integer>();
myMap.put("Sounds great", 0);
myMap.put("Whats your favorite food?", 0);
public String generateAnswer(String... strings){
ArrayList<String> possibleAnswers = new ArrayList<String>();
for (Map.Entry<String, Integer> entry : myMap.entrySet()) {
int amount = entry.getValue();
if (amount == 0) {
possibleAnswers.add(entry.getKey());
}
}
return chooseAnswer(possibleAnswers);
}
public String chooseAnswer(ArrayList<String> possibleAnswers){
int i = possibleAnswers.size();
int random = (int)(Math.random() * i);
String response = possibleAnswers.get(random);
myMap.put(response, myMap.get(response) + 1);
return response;
}
Upvotes: 1
Reputation: 1699
If I understand you problem correctly, maybe a Set would be a nice choice.
Instead of using String... use Set; something like:
public String chooseAnswer (Set<String> strings) {
int size = strings.size();
int item = new Random().nextInt(size); // In real life, the Random object should be rather more shared than this
int i = 0;
for(String str : strings)
{
if (i++ == item) {
strings.remove(str);
return str;
}
}
return null; // You will never reach this, but the IDE/compiler might need you to write this.
}
You just delete the questions you don't want repeated; you can create a boolean function to determine if you want to repeat or not some answer, and put the remove in an if with that condition; in case you wanted to repeat some questions, but not others.
PS: The way to take a random element from a set is taken from here.
Another choice if you don't want to do this is to just use an ArrayList instead, so you can directly take and delete an element using the index.
Upvotes: 0
Reputation: 140534
You can't do this directly.
What you can do is to conditionally insert a string into a list:
List<String> answers = new ArrayList<>(Arrays.asList(
"Sounds great",
"Whats your favorite food?"));
if (favourite_color_count == 0) {
answers.add("Whats your favourite color?");
}
and then invoke like:
chooseAnswer(answers.toArray(new String[0]));
which is obviously quite verbose at the call site.
An alternative is to put logic into the chooseAnswer
method so that it doesn't select empty (or null) answers. Then you can use the ternary operator:
chooseAnswer(
"Sounds great",
"Whats your favorite food?",
(condition) ? "Whats your favorite color" : "");
Upvotes: 1