使用通配符或"tags"进行用户输入



我最近开始学习c#,之前没有编程经验。我一直在看教程,我正在学习"if"语句。我试图创建一个简单的用户反馈应用程序,提出问题并响应用户输入。

我想做的是使用某种关键字或标记系统或通配符类型系统(如搜索查询中的*)来允许不完全特定的响应输入。

例如,在下面的代码中,我使用If和Else语句,是否有一种方法可以将userValue设置为不仅等于"good"或"bad",而且等于这两个词的任意数量的变体?"I’m quite good."),或者让If语句指向一组关键字或标签(可能在其他地方列出,或者在外部文件中),这样用户就可以随心所欲地输入,而预先确定的程序就会挑选出这个短语。

我不希望创造某种形式的人工智能,只是为了让一个有趣的响应程序。是否可能/明智地使用数组,并以某种方式调用它作为一个If语句?或者是否存在另一种更有效的方法来为用户输入提供反馈?如果这对这个网站来说太新手了,我很抱歉。我在网上搜索过,但问题是,我不知道我在找什么!

到目前为止,我的代码如下:
Console.WriteLine("Hello. How are you?");
        string userValue = Console.ReadLine();
        string message = "";
        if (userValue == "good")
            message = "That's good to hear. Do you want a cup of tea?";
        else if (userValue == "bad")
            message = "I'm sorry to hear that. Shall I make you a coffee?";
        else
            message = "I don't understand. Do you want a cuppa?";
        Console.WriteLine(message);
        string userValueTwo = Console.ReadLine();
        string messageTwo = "";
        if (userValueTwo == "yes")
            messageTwo = "I'll get right onto it!";
        else if (userValueTwo == "no")
            messageTwo = "Right-o. Shutting down...";
        Console.WriteLine(messageTwo);
        Console.ReadLine();

您可以在这里使用正则表达式:

using System.Text.RegularExpressions;
...
// If the phrase stats/ends or contains the word "good"  
if (Regex.IsMatch(userValue, @"(^|s)good(s|$)", RegexOptions.IgnoreCase)) {
  message = "That's good to hear. Do you want a cup of tea?";
}

我犹豫了一下是否发布这个答案,因为它使用了LINQ,这可能会让你感到困惑,因为你只是刚刚学习。不过这比可怕的正则表达式简单多了!您可以使用自己的循环来实现这一点,但是LINQ只是为您节省了一些代码,并使它(有争议地)更具可读性:

Console.WriteLine("Hello. How are you?");
string userValue = Console.ReadLine();
string message = "";
string[] goodWords = new string[] { "good", "well", "sweet", "brilliant"};
string[] badWords  = new string[] { "terrible", "awful", "bad", "sucks");
if (goodWords.Any(word => userValue.Contains(word)))
    message = "That's good to hear. Do you want a cup of tea?";
else if (badWords.Any(word => userValue.Contains(word)))
    message = "I'm sorry to hear that. Shall I make you a coffee?";
else
    message = "I don't understand. Do you want a cuppa?";

基本上,Any()函数会查看列表中是否有符合某些条件的单词。我们使用的标准是userValue字符串是否有Contains()这个词。有趣的=>语法是lambda表达式,只是编写匿名函数的一种快速方式。再一次,现在可能有点太混乱了。

这是一个非linq版本,你可能会觉得更容易理解:

void main()
{
    Console.WriteLine("Hello. How are you?");
    string userValue = Console.ReadLine();
    string message = "";
    string[] goodWords = new string[] { "good", "well", "sweet", "brilliant"};
    string[] badWords  = new string[] { "terrible", "awful", "bad", "sucks"};   
    if (DoesStringContainAnyOf(userValue, goodWords))
        message = "That's good to hear. Do you want a cup of tea?";
    else if (DoesStringContainAnyOf(userValue, badWords))
        message = "I'm sorry to hear that. Shall I make you a coffee?";
    else
        message = "I don't understand. Do you want a cuppa?";
    string answer = "I'm really well thanks";        
}
bool DoesStringContainAnyOf(string searchIn, string[] wordsToFind)
{
    foreach(string word in wordsToFind)
        if (searchIn.Contains(word))
            return true;
    return false;
}

尝试使用"Contains"方法。http://msdn.microsoft.com/en-us/library/dy85x1sa (v = vs.110) . aspx

的例子:

if (userValue.ToLower().Contains("good"))
        message = "That's good to hear. Do you want a cup of tea?";

简单的Contains检查如何?

if (userValue.ToLower().Contains("good"))

我还添加了ToLower()大小写转换,以便它可以在任何情况下工作。

如果你想实现一个关键字和程序(函数)的列表,我会这样做:

var keywords = new Dictionary<string, System.Func<string>>() {
    { "good", () => "That's good to hear. Do you want a cup of tea?" },
    { "bad", () => "I'm sorry to hear that. Shall I make you a coffee?" }
};
foreach(var keyword in keywords)
{
    if (userValue.ToLower().Contains(keyword.Key))
    {
        message = keyword.Value();
        break;
    }
}

在这种情况下,我使用c# lambda表达式来保存你想要的"程序列表";这是一个非常强大的c#特性,允许将代码用作数据。现在这些函数只返回常量字符串值,所以对于您的场景来说,它们有点多余。

前面的答案都是有效的,并且包含了很多值得学习的东西。我想特别注意lower方法,它将帮助你识别"好"one_answers"好"。

另外,为了使列表更完整,您应该了解旧的IndexOf方法,它将返回子字符串在字符串中的位置,如果不包含该子字符串,则返回-1。

但是我有一种预感,你的问题也针对如何以更有效的方式编写 Eliza代码(当然是游戏的名称)的问题。你肯定不止想问两个问题…?

如果提示词和响应可以很容易地扩展,而无需再次更改和编译程序,这是最有趣的。

最简单的方法是把所有的数据放在一个文本文件中;有很多方法可以做到这一点,但是最容易维护的是逐行格式,如:

//The text file eliza.txt:
good=That's good to hear. Do you want a cup of tea?
bad=I'm sorry to hear that. Shall I make you a coffee?
father=Tell me more about your family!
mother=What would you do Daddy?
..
bye=Goodbye. See you soon..

这是用File.ReadLines命令读取的。在程序的顶部添加一个using System.IO;,如果还没有的话。从那里我建议使用Dictionary<string, string>

    Dictionary<string, string> eliza = new Dictionary<string, string>();
    var lines = File.ReadAllLines("D:\eliza.txt");
    foreach (string line in lines)
    {
        var parts = line.Split('=');
        if (parts.Length==2) eliza.Add(parts[0].ToLower(), parts[1]);
    }

现在你可以创建一个循环,直到用户说'bye'或什么也不说:

    string userValue = Console.ReadLine();
    do
    {
        foreach (string cue in eliza.Keys)
            if (userValue.IndexOf(cue) >= 0)
            { Console.WriteLine(eliza[cue]); break; }
        userValue = Console.ReadLine().ToLower();
    }
    while (userValue != "" && userValue.IndexOf("bye") < 0);

有趣的事情是扩展提示词列表,响应列表,删除一些响应后,他们已经使用或扔进一些随机响应。

最新更新