How to implement an interactive decision tree in C#

半城伤御伤魂 提交于 2019-12-04 13:39:04

If I understand your issue, here is your code corrected.

I renamed some things.

I called MakeDecisionTree the method that initializes the expert system with the conditions tree and it returns the root condition.

Each condition contains a sentence to evaluate and it can be a query or a result.

For a result, the evaluate display the sentence.

For a query, the evaluate method asks the user to answer the question by yes or no. And using this answer, it calls the corresponding evaluate of the next child condition.

Sorry for my english here, it is not my native language, and I'm not involved in AI.

static private void DecisionTreeTest()
{
  Console.WriteLine("Please, answer a few questions with yes or no.");
  Console.WriteLine();
  MakeDecisionTree().Evaluate();
}
static private bool GetUserAnswer(string question)
{
  Console.WriteLine(question);
  string userInput;
  while ( true )
  {
    userInput = Console.ReadLine().ToLower();
    if ( userInput == "yes" )
      return true;
    else
    if ( userInput == "no" )
      return false;
    else
      Console.WriteLine("Your answer is not supported, retry please." +
                        Environment.NewLine + Environment.NewLine +
                        question);
  }
}
static private DecisionTreeQuery MakeDecisionTree()
{
  var queryAreYouSure
    = new DecisionTreeQuery("Are you sure?",
                            new DecisionTreeResult("Buy it."),
                            new DecisionTreeResult("You need to wait."),
                            GetUserAnswer);
  var queryIsItAGoodBook
    = new DecisionTreeQuery("Is it a good book?",
                            new DecisionTreeResult("What are you waiting for? Just buy it."),
                            new DecisionTreeResult("Find another one."),
                            GetUserAnswer);
  var queryDoYouLikeIt
    = new DecisionTreeQuery("Do you like it?",
                            queryAreYouSure,
                            queryIsItAGoodBook,
                            GetUserAnswer);
  var queryDoYouWantABook
    = new DecisionTreeQuery("Do you want a book?",
                            queryDoYouLikeIt,
                            new DecisionTreeResult("Maybe you want a pizza."),
                            GetUserAnswer);
  return queryDoYouWantABook;
}
abstract public class DecisionTreeCondition
{
  protected string Sentence { get; private set; }
  abstract public void Evaluate();
  public DecisionTreeCondition(string sentence)
  {
    Sentence = sentence;
  }
}
public class DecisionTreeQuery : DecisionTreeCondition
{
  private DecisionTreeCondition Positive;
  private DecisionTreeCondition Negative;
  private Func<string, bool> UserAnswerProvider;
  public override void Evaluate()
  {
    if ( UserAnswerProvider(Sentence) )
      Positive.Evaluate();
    else
      Negative.Evaluate();
  }
  public DecisionTreeQuery(string sentence,
                           DecisionTreeCondition positive,
                           DecisionTreeCondition negative,
                           Func<string, bool> userAnswerProvider)
    : base(sentence)
  {
    Positive = positive;
    Negative = negative;
    UserAnswerProvider = userAnswerProvider;
  }
}
public class DecisionTreeResult : DecisionTreeCondition
{
  public override void Evaluate()
  {
    Console.WriteLine(Sentence);
  }
  public DecisionTreeResult(string sentence)
    : base(sentence)
  {
  }
}

You decision tree design is very good, just the way you ask the user is not. You ask all the questions in advance, and go to the decision tree later on. Of course the tree cannot make asked questions unasked. It's not a decision tree problem.

you would have to put these pairs of lines:

    Console.WriteLine("Are you sure? true/false");
    client.Answer[2] = bool.Parse(Console.ReadLine());

into the Evaluate method, or you do a callback or whatever architectural design to separate logic from user-interface. The decision-tree has to ask, or at least know the question. The answer does not need to be stored, you can evaluate it right after input.

Maybe you pass something to Ask the user to the evaluate Method

public interface IAsk
{
    bool Question(string message);
}

And for your sample you instantiate that with

public class ConsoleAsk : IAsk
{
    bool Question(string message)
    {
         Console.WriteLine(message);
         return  bool.Parse(Console.ReadLine());
    }
}

and you modify your Evaluate like this:

    public override void Evaluate(IAsk ask)
    {
        bool result = ask.Question("do you feel good or bad");
        string resultAsString = result ? "yes" : "no";

        Console.WriteLine($"\t- {this.Title}? {resultAsString}");

        if (result) this.Positive.Evaluate(ask);
        else this.Negative.Evaluate(ask);
    }

of course you replace the question with your title property.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!