#java #chatbot
#java #чат-бот
Вопрос:
Привет, я программист-любитель, поэтому, пожалуйста, будьте осторожны со мной.
Я не хочу вдаваться в программирование диалогового окна swing / switch, поэтому я хочу сделать его максимально простым. Но опять же, я не хочу, чтобы в моем кодировании было много операторов if и else. Я ищу больше способов сделать чат-бота более плавным. Я пытался искать и понимать строки и массивы, но я все еще не знаю, как реализовать это в моем коде.
Это моя первая попытка создать простого чат-бота
import java.util.Scanner;
public class ChatBot {
public static void main(String[] args) {
System.out.println("");
Scanner sc = new Scanner(System.in);
System.out.println("Hello I'm your therapist for today! What's your name? n");
String n = sc.nextLine();
System.out.println("Okay " n ", How are you?");
while (true) {
System.out.println(" ");
String inputs = sc.nextLine();
inputs = inputs.toUpperCase();
if (inputs.indexOf("FINE") >= 0) {
System.out.println("That's good to know " n);
}
else if (inputs.indexOf("HI") >= 0) {
System.out.println("Hello " n);
}
else if (inputs.indexOf("HELP") >= 0) {
System.out.println("If you seek help, listen to your heart! <3");
}
else if (inputs.indexOf("HELP ME") >= 1) {
System.out.println("I will try my best helping you, what's your problem?");
}
// what if bot doesn't know the answer to fyour question/response?
// The chatbot gives a random respond to unknown questions by the user
// here the number of random responses are given 4, but in java we start at 0
// I have made the number to 4, so that the responses can be from between 0 to 3
// Also I have added Math.random utility and declared it to a double value
// The "r" is now my random, and I make a new integar to calculate random
// response
// by calculating the r times num variables and thereby getting a random value.
// that random value is declared to "rResponse" and therefore I have assigned
// the
// String response to answer/reply depending on the random number that's
// generated
// between 0-3
else {
final int num = 4;
double r = Math.random();
int rResponse = (int) (r * num);
String response = "";
if (rResponse == 0) {
response = "Hmmm...";
}
else if (rResponse == 1) {
response = "Okay?...";
}
else if (rResponse == 2) {
response = "I don't get it...";
}
else if (rResponse == 3) {
response = "I dont quite follow, I'm sorry. Try another question";
}
System.out.println(response);
}
}
}
}
Во всяком случае, моя проблема в
else if (inputs.indexOf("HELP ME") >= 1) {
System.out.println("I will try my best helping you, what's your problem?"); }
else if (inputs.indexOf("HELP") >= 0) {
System.out.println("If you seek help, listen to your heart! <3"); }
этот код заключается в том, что я не могу заставить его отвечать на два разных пользовательских ввода, на которые я хочу, чтобы бот отвечал отдельно. Например, я хочу, чтобы он реагировал по-другому, когда вы говорите «помогите мне» вместо «помогите».
Есть ли какие-либо рекомендации или способы, чтобы я мог сделать это по-другому?
Также, если кто-нибудь может сообщить мне, как я могу переделать все это другим методом, используя arraylist? или двумерные массивы? Если это не слишком сложно для новичка вроде меня. Каков был бы простой способ сделать это, не выполняя все эти инструкции if и else?
Заранее благодарю.
Комментарии:
1. Метод indexOf возвращает ноль, если символы совпадают с первыми символами строки. Вы могли бы хранить вопросы и ответы в древовидной структуре, где вопрос может иметь несколько ответов, каждый из которых указывает на другой вопрос. Следующая статья » Глубокое погружение в деревья с помощью Java » не проста для понимания, но она мощная.
2. @GilbertLeBlanc Спасибо за ваш ответ, я вижу, что есть много способов построения дерева. Углубляясь в статью, которую вы опубликовали, кажется немного размытым, какая структура данных была бы лучшей для меня в этом случае?
Ответ №1:
Я предполагаю, что вы понимаете классы, методы и поля. Если вы этого не сделаете, это объяснение не будет иметь никакого смысла.
Мы собираемся построить древовидную структуру данных, используя классы и java.util.List
интерфейс.
Первым шагом является создание класса getter / setter, который сохраняет ответы и List
индекс для следующего вопроса.
Вот этот класс.
public class Response {
private final String response;
private final int responseQuestion;
public Response(String response, int responseQuestion) {
this.response = response.toLowerCase();
this.responseQuestion = responseQuestion;
}
public boolean doesResponseMatch(String responseString) {
return responseString.toLowerCase().contains(getResponse());
}
public String getResponse() {
return response;
}
public int getResponseQuestion() {
return responseQuestion;
}
}
doesResponseMatch
Метод определяет responseString
, содержит ли введенный пользователем ответ String
.
Мы сохраняем ответ в нижнем регистре String
и преобразуем пользователя responseString
в нижний регистр, чтобы тест contains не зависел от регистра.
Остальная часть класса представляет собой типичный класс getter / setter.
Следующий шаг — создать класс, содержащий вопрос, List
список возможных ответов и ответ по умолчанию. Ответ по умолчанию используется в случае, если ни один из возможных ответов не совпадает.
public class Question {
private final String question;
private final Response defaultResponse;
private List<Response> possibleResponses;
public Question(String question, Response defaultResponse) {
this.question = question;
this.defaultResponse = defaultResponse;
this.possibleResponses = new ArrayList<>();
}
public void addPossibleResponse(Response response) {
this.possibleResponses.add(response);
}
public Response getPossibleResponse(String responseString) {
for (Response response : this.possibleResponses) {
if (response.doesResponseMatch(responseString)) {
return response;
}
}
return this.defaultResponse;
}
public String getQuestion() {
return question;
}
}
Метод getPossibleResponse возвращает либо соответствующий ответ, либо, если совпадений нет, ответ по умолчанию.
Вопрос может содержать ноль, один или много совпадающих ответов. Каждый ответ может указывать на другой индекс вопроса.
Мы используем a java.util.ArrayList
для удержания List
. Поскольку мы собираемся добавить все вопросы одновременно, список массивов является подходящей структурой для хранения нашего дерева.
Следующий шаг — создать класс для хранения нашей древовидной структуры, которая будет состоять List
из Question
экземпляров.
public class ResponseTree {
private List<Question> questions;
public ResponseTree() {
this.questions = new ArrayList<>();
addQuestionFactory();
}
private void addQuestionFactory() {
Response defaultResponse = new Response("", 0);
String question = "I don't understand your response.";
addQuestion(question, defaultResponse);
// Add your additional questions / responses here.
// Using a List means we can point to any question by it's
// location number from 0 to List size() - 1.
// This is a tree structure, stored in a List.
}
private void addQuestion(String question, Response defaultResponse) {
this.questions.add(new Question(question, defaultResponse));
}
}
Это addQuestionFactory
отдельный метод, потому что он будет включать в себя все вопросы чат-бота, на которые вы хотите ответить. Я включил очевидный первый вопрос.
Вы можете протестировать этот код, написав остальную часть чат-бота. На любой ответ будет дан ответ на первый вопрос. После того, как вы написали остальную часть чат-бота, вы можете добавлять вопросы и ответы к заводскому методу.
Используя классы, мы создали древовидную структуру, которая выглядит следующим образом:
Tree (List)
Question
String
List of possible responses
Default response
Response
String
Index pointer
Используя классы, мы можем скрыть некоторые сложности и сделать наш код более понятным.
Комментарии:
1. Это очень интересный взгляд на то, как это сделать! Большое вам спасибо, я уже пытаюсь изучить эту древовидную / подобную структуру. Но вы правы, это кажется немного сложным для понимания на моем уровне программирования, хе-хе.
Ответ №2:
В этом случае вам следует обратиться к equals
:
else if ("HELP ME".equals(inputs)) {
System.out.println("I will try my best helping you, what's your problem?");
} else if ("HELP".equals(inputs)) {
System.out.println("If you seek help, listen to your heart! <3");
}
Общая практика сравнения с постоянной строкой заключается в том, чтобы сначала поместить строковую константу, а затем переменную, чтобы защитить NPE ( исключение NullPointerException ), в случае inputs
, если значение равно null .
Вернитесь к своему вопросу, я думаю, вы можете сделать это лучше, HashMap
чтобы избежать if-else
заявлений:
HashMap<> handlers = new HashMap<String, Runnable>();
handlers.add("FINE", () -> {
System.out.println("That's good to know " n);
});
.... add other handlers.
do while {
Get your handler from handlers and call run on it.
If no handler not found, try randome response.
}
Это более эффективно, чем indexOf
equals
операции and .
Кстати, Spring Shell — хороший стартер для написания приложений-оболочек.
Комментарии:
1. О, я понимаю… Я действительно хочу, чтобы он был более эффективным, чем сейчас, он все еще кажется немного нубовским, я хотел бы сделать его немного более продвинутым, чем сейчас. Является ли HashMap следующим уровнем, или есть другие способы сделать его более эффективным, не делая его слишком сложным для себя?
2. @Snooppoop HashMap — это определенно следующий уровень, Важно знать базовые структуры данных, Такие как
List
иMap
т. Д., Которые предлагает JDK, Чтобы написать высокопроизводительное приложение3. Еще раз спасибо за быстрый ответ, как вы думаете, было бы проще изучить только массивы, чем изучать HashMap?
4. @Snooppoop Я предлагаю вам следовать некоторым руководствам по Java, они научат вас от простых до сложных тем.
5. О, я уверен, что существует множество руководств, которые помогут лучше понять Java, но это также причина, по которой я здесь. Я просмотрел все учебные пособия, которые вы можете найти о создании чат-бота, особенно в области использования только консоли, а не диалогового окна. Тем не менее, спасибо за ваше предложение.