I need to allow the users choose their own path by picking between two simple choices displayed on their screen in order to progress to the next set of choices, until they get to one of the endings, i.e something like this should be achieved:
I have tried the following code, but only the left side is evaluated each time. I am wondering how can I achieve a results like the above image (covering all the branches)? For instance, if the user selects "No" the application shouldn't ask any further question from the user and just simply shows the "Maybe you want a Pizza" message. I have done this with decision tree algorithm and need to fix it, so that it covers both the left and right sides just like the above image.
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
var decisionTree = MainDecisionTree();
var client = new Client();
Console.WriteLine("Do you want a book? true/false");
client.Answer[0] = bool.Parse(Console.ReadLine());
Console.WriteLine("Do you like it? true/false");
client.Answer[1] = bool.Parse(Console.ReadLine());
Console.WriteLine("Are you sure? true/false");
client.Answer[2] = bool.Parse(Console.ReadLine());
decisionTree.Evaluate(client);
Console.WriteLine("Press any key...");
Console.ReadKey();
}
private static DecisionQuery MainDecisionTree()
{
//Decision 2
var wantBranch = new DecisionQuery
{
Title = "Do you want a book?",
Test = (client) => client.Answer[0],
Positive = new DecisionResult { Result = true },
Negative = new DecisionResult { Result = false }
};
//Decision 1
var deserveBranch = new DecisionQuery
{
Title = "Do you like it?",
Test = (client) => client.Answer[1],
Positive = wantBranch,
Negative = new DecisionResult { Result = false }
};
//Decision 0
var sureBranch = new DecisionQuery
{
Title = "Are you sure?",
Test = (client) => client.Answer[2],
Positive = deserveBranch,
Negative = new DecisionResult { Result = false }
};
return sureBranch;
}
}
public class DecisionResult : Decision
{
public bool Result { get; set; }
public override void Evaluate(Client client)
{
Console.WriteLine("\r\nThe result: {0}", Result ? "Buy it" : "You need to wait");
}
}
public class DecisionQuery : Decision
{
public string Title { get; set; }
public Decision Positive { get; set; }
public Decision Negative { get; set; }
public Func<Client, bool> Test { get; set; }
public override void Evaluate(Client client)
{
bool result = this.Test(client);
string resultAsString = result ? "yes" : "no";
Console.WriteLine($"\t- {this.Title}? {resultAsString}");
if (result) this.Positive.Evaluate(client);
else this.Negative.Evaluate(client);
}
}
public abstract class Decision
{
public abstract void Evaluate(Client client);
}
public class Client
{
public bool[] Answer { get; set; } = new bool[3];
}
}
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)
{
}
}