Frage

Okay, ich habe gerade ein Ziel, ein grundlegendes Textabenteuer zu machen. Dazu würde ich jedoch eine Switch -Anweisung benötigen/möchten, die Folgendes ausführen kann:

  • Überprüfen Sie, ob eine Zeichenfolge irgendwo im Inneren ein Wort hat.
  • Überprüfen Sie, ob eine Zeichenfolge zwei Wörter in einer beliebigen Kombination irgendwo im Inneren enthält.

Wie würde ich das erreichen? Könnten Sie mir das Codieren für dieses spezielle Beispiel zeigen:

Ein Benutzer wird für Daten aufgefordert. Eine Switch -Anweisung überprüft nach einem Fall "Look Box" und "Schlaf" als einen anderen. Das Programm ist es egal, in welcher Reihenfolge sich Wörter befinden, kümmert sich aber um die Reihenfolge der Buchstaben.

Bitte erklären Sie alles im Detail. Ich habe gerade angefangen zu codieren.

Bearbeiten: Danke für alle Antworten. Ich verstehe, dass es bessere, kompliziertere und nützlichere Möglichkeiten gibt, damit umzugehen, aber es ist einfach noch nicht auf meinem Niveau.

War es hilfreich?

Lösung

Hier ist eine andere Idee:

    string input = "look at the sleep box";
    bool caseA = input.Contains("sleep");
    bool caseB = input.Contains("look") && input.Contains("box");

    int scenarioId;
    if (caseA && caseB)
        scenarioId = 1;
    else if (caseA)
        scenarioId = 2;
    else if (caseB)
        scenarioId = 3;
    // more logic?
    else
        scenarioId = 0;

    switch (scenarioId)
    {
        case 1:
            Console.WriteLine("Do scenario 1");
            break;
        case 2:
            Console.WriteLine("Do scenario 2");
            break;
        case 3:
            Console.WriteLine("Do scenario 3");
            break;
        // more cases
        default:
            Console.WriteLine("???");
            break;
    }

Es verwendet if/dann/sonst, um ein bestimmtes Szenario zu bewerten, einschließlich potenzieller Kombinationen wie Eingaben wie "look at the sleep box" und verwendet dann eine Switch -Anweisung, um entsprechend auszuführen.

Andere Tipps

Die Leute fragen mich manchmal, warum ich kein Boot gebaut habe. Ich bin ziemlich praktisch, ich mag es, Dinge zu bauen und ich segel. Ich sage ihnen immer, dass Leute, die gerne segeln, keine Boote bauen sollten, weil Sie am Ende drei Jahre in Ihrem Garagenbauen ein Boot verbringen, bevor Sie segeln können. Wenn Ihr Ziel segeln ist, kaufen Sie ein Boot. Wenn Ihr Ziel ist, ein Boot zu bauen, bauen Sie ein Boot.

Wenn Ihr Ziel es ist, C# zu lernen, indem Sie ein Textabenteuer schreiben, werden Sie viel lernen. Wenn Ihr Ziel ist Schreiben Sie ein Textabenteuer, Verwenden Sie dann nicht c#, verwenden Sie Inform7. Es ist leicht zu lernen, speziell für das Schreiben von Textabenteuern konzipiert, und ist wahrscheinlich die höchste Sprache der Welt. Es ist eine erstaunliche Programmiersprache und ich kann es nur empfehlen.

Um Ihre spezifische Frage zu beantworten: Das ist kein guter Weg, um dies zu tun. Die Art und Weise, wie Text Abenteuerprozessoren tatsächlich funktionieren Token. Sie müssen das Zeichenfolgencharakter durch den Zeichen suchen, der nach Grenzen zwischen Wörtern wie Räumen, Kommas, Perioden usw. sucht. Sobald Sie die Grenzen gefunden haben, extrahieren Sie die Substrings zwischen den Grenzen und versuchen, jedes Wort zu erkennen, indem Sie es mit Wörtern in einem Wörterbuch vergleichen.

Sobald Sie eine Sequenz von Token haben, versuchen Sie, die Sequenz gegen a zu entsprechen Grammatik. Das heißt, Sie sehen, ob die Reihenfolge der Token als Ein-Wort-Befehl wie {"Look"} oder eine Verb-Nomen-Phrase wie {"Look", "at", ",", "rot", ",", "rot", klassifiziert werden kann. Taste"}. Sie möchten diesen niederbrechen - "Look" ist das Verb "at" die Präposition, "die rote Taste" ist das Objekt des Verbs, "der Artikel" rot "ist das Adjektiv und" Taste " ist das Substantiv.

Es hört sich so an, als wären Sie ein Anfänger, also konzentrieren Sie sich zuerst auf die lexikalische Analyse. Gehen List<string> von Token. Techniken für die grammatikalische Analyse können ziemlich kompliziert sein. Holen Sie sich zuerst das einfache Zeug und solide.

In Anbetracht der Tatsache, dass Sie anfangen, können wir uns das zuerst im einfachen Fall ansehen, aber Sie können keine verwenden switch Aussage, um dies zu erreichen.

Nehmen wir zum Zwecke der Einfachheit an, dass Ihre Befehle auf 1 oder 2 Wörter begrenzt sind und dass das erste Wort ein Verb und das zweite wäre, wenn anwesend ein Substantiv ist. Dies gibt uns einige Möglichkeiten:

North
South
Examine
Take
Drop

etc...

Da wir eine Eingabezeichenfolge von haben strInput:

string strInput = "examine hat";

Wir wollen das zuerst aufteilen. Wir können das mithilfe dessen tun String.Split:

string[] arguments = strInput.Split(' ');

Das gibt uns ein String -Array:

Argumente [0] ist untersuchen

Argumente [1] ist Hut

Beachten Sie, wir haben nicht immer eine zweite, wenn der Benutzer eingeben:

`North`

dann:

Argumente [0] ist Norden

Wir müssen danach suchen! Nun, die schreckliche (aber einfache) Art, dies zu überprüfen, ist:

if(arguments[0] == "North")
{
    // code to go North
}
else if(arguments[0] == "Take")
{
    // code to work with Take.  We'd check on arguments[1] here!
}
// etc...

Leider wird dieser Code lang, komplex und unbrauchbar. Woher wissen Sie, was Sie zu irgendeinem Zeitpunkt tun können und was nicht? Wie fügt Sie einen neuen Befehl hinzu? Verwenden wir also die wundervolle Delegate -Funktion von C#und stellen auch die vor Dictionary. Ein Wörterbuch ermöglicht es uns, einen Typ (einen Schlüssel) einem anderen zuzuordnen (in diesem Fall ein Delegierter). Mit dieser Methode können wir Delegierte erstellen, um verschiedene Arten von Befehlen zu verarbeiten.

public delegate void HandleCommand(string[] _input);

Hier haben wir einen Delegierten delegiert. Mach dir noch keine Sorgen, aber lasst uns einige Funktionen vorstellen, die mit Befehlen funktionieren:

public void Handle_North(string[] _input)
{
    // code to go North.  This function could just as easily be something that handles
    // *all* directions and checks _input[0] to see where to go!
}

public void Handle_Take(string[] _input)
{
    if(_input.Length > 1) // Did the user specify an object to take?
    {
        // code to handle Take.
    }
}

Usw. Jetzt müssen wir ein Wörterbuch erstellen, um die Befehle diesen Funktionen zuzuordnen:

Dictionary<String, HandleCommand> map = new Dictionary<String, HandleCommand>();

Hier deklarieren wir ein Wörterbuch, das Saiten an unseren Delegierten -Typ abbiegt HandleCommand. Jetzt müssen wir es bevölkern!

map["north"] = Handle_North;
map["take"]  = Handle_Take;
// and the rest of our commands

Lassen Sie uns angesichts unseres früheren Beispiels die Zeichenfolge wie zuvor teilen und den rechten Handler anrufen!

string[] arguments = strInput.Split(' ');
if(arguments.Length > 0 && map.ContainsKey(arguments[0]))
    map[arguments[0]](arguments);  // calls our function!

Jetzt haben wir ein erweiterbares System. Es ist einfach, neue Befehle und Handler hinzuzufügen! Es wird komplizierter, aber im Wesentlichen ist dies ein guter Weg, um das zu tun, was Sie wollen.

Bearbeiten: Ich bin mir bewusst, dass Ihre Frage besagt, dass sie sich nicht um die Reihenfolge der Wörter kümmern sollte. Wenn Sie ein Text -Abenteuerspiel schreiben, würden Sie gut tun, um einen Grammer aus Verb/Substantiv oder eine solche zu bilden, anstatt die Dinge zufällig tippt zu lassen.

Sie können dies nicht verwenden switch, Sie müssen die Art der Struktur if-else-if verwenden.

string input=...
if(input.Contains("sleep")){ //contains sleep? 
  //do stuff for some word
}else if(input.Contains("look") && input.Contains("box")){ //contains look and box
  //do stuff for the combination thing
}

Mit switch jeder case Muss ein statischer, eindeutiger Wert sein. Sie können also nicht verwenden .Contains als Fall.

Sie können nicht verwenden switch Dafür direkt, aber andererseits, ich denke, Sie sollten es nicht tun. Sie sollten wahrscheinlich die Logik haben, die die Wörter an einem anderen Ort als die Logik findet, die die enthält switch.

Erwägen Sie, eine Enum zu verwenden, um alle möglichen Aktionen zu enthalten:

public enum AdventureAction
{
    LookBox,
    Sleep
}

Erwägen Sie, eine Methode zu schreiben, die das „Parsen“ ausführt:

public static AdventureAction Parse(string text)
{
    if (text.Contains("look") && text.Contains("box"))
        return AdventureAction.LookBox;

    if (text.Contains("sleep"))
        return AdventureAction.Sleep;
}

Und dann können Sie ein einfaches verwenden switch Aussage zur Ausführung der Aktion:

var action = Parse(input);
switch (action)
{
    case AdventureAction.LookBox:
        // do something interesting with the box
        break;

    case AdventureAction.Sleep:
        // go to sleep
        break;
}

Ich schreibe derzeit meine eigene Text Adventure Engine, weil ich informiert/adrift/quest tendiert, um einen tödlichen Fehler zu haben, der mich nervt - Informations albtraumhafte, verschleierte Syntax (und dies kommt von einem UX -Designer, der die Dinge so einfach wie einfach wie möglich für Anfänger), Adrifts hässlicher Leser und Adrift/Quests mangelnde Unterstützung für die Klasse/Objekt.

Es ist vielleicht nicht der beste Weg, es zu tun, aber es funktioniert bisher gut. Ich schaute in Regex, entschied mich aber stattdessen so.

Das erste, was Sie tun müssen, ist die Eingabe-/Befehlszeichenfolge des Spielers in eine Liste aufzuteilen. Zum Glück ist in diesen Spielen das erste Element dieser Liste fast immer ein Verb.

  • sehen
  • bei
  • blau
  • Buchen

Sie möchten Verb/Object/ETC -Datenklassen, auf die von Schlüssel zugegriffen werden kann und alle Werte enthalten, die damit übereinstimmen können, z. B. "Schauen Sie, untersuchen, ex".

class Verb
{
    string uniqueID;
    List<string> values;
}

class Object
{
    public uniqueID; // Because this is shared with Verbs, you could do a better unique ID system, but hey...
    public List<string> articles;
    public List<string> adjectives;
    public List<string> noun;
}

Sie benötigen auch eine Reihe von "Action" -Subklassen, die aus der Eingabe des Spielers abgestimmt werden. Hier "erstellen" Sie Ihre Satzstruktur, die durch die Eingabe des Spielers übereinstimmt werden muss.

  • Aktion (Basisklasse)
    • sehen
    • Schauen Sie {at} [Objekt] an
    • Schauen Sie {at} Buch an
    • Springen
    • Springen {on/auf} [Objekt

.

class Action
{
    string uniqueID;
    List<SentenceElement> sentence;

    void Execute();
    bool RestrictionsCheck();
}

class Look : Action
{
    override void Execute();
    override bool RestrictionsCheck();
}

class LookAtObject : Action
{
    override void Execute();
    override bool RestrictionsCheck();
}

class LookAtBook : Action
{
    override void Execute();
    override bool RestrictionsCheck();
}

Die Basis -Aktionsklasse hat einen Satzbauer, der Satzelemente verwendet. Es kann eine Liste sein, die den Satz Stück für Stück beschreibt.

class SentenceElement
{
    List<string> values;
    bool isOptional;
}

class VerbID : SentenceElement {}
class ObjectID : SentenceElement {}
class ObjectAny : SentenceElement {}
class CharacterID : SentenceElement {}
class CharacterAny : SentenceElement {}
class TextOptional : SentenceElement {}
class TextRequired : SentenceElement {}
class Parameter : SentenceElement {}

Sie können jetzt Ihre "Aktion" -Kurse durchsuchen, den ersten Satz mit den ersten Eingabeverbs vergleichen und eine Liste derjenigen beibehalten, die als "Potenzialität" übereinstimmen. "String.Contains" wird funktionieren.

Jetzt müssen Sie die nächstgelegene passende Aktion finden, indem Sie den Eingangsbefehl Ihrer Spieler durchlaufen und jeden Satz durchlaufen, um sie zu vergleichen. Behalten Sie einen Index davon, wo Sie sich in jedem befinden (PlayerInputIndex, potentialactionsIndex, surtelementIndex).

Wenn Sie eine Übereinstimmung finden, erhöhen Sie den PlayerInputIndex, bis es nicht mit der Satzung übereinstimmt, Ihre Einstellungen (isoptional usw.), dann zur nächsten Satzungsindex und führen Sie den Vergleich erneut aus. Schließlich erreichen Sie das Ende der Eingabe des Spielers oder des Satzes.

Komplexität wird hinzugefügt, wenn Sie Satzelemente haben, die "isoptional" sind. Daher muss sie überprüft werden, oder Aktionen, die Satz von Typ -Objectany haben, die nicht mit einem vorhanden sind, sondern ein Objekt anzeigen "Welches Objekt möchten Sie möchten, möchten Sie Essen?" Botschaft. Außerdem haben Objekte zusätzliche passende Parameter wie Präfixe/Adjektive/Substantive, die im Gegensatz zu Verben berücksichtigt werden müssen.

Dieses System erfordert auch eine neue Klasse für jede Aktion, die Sie jemals ausführen können. Jede Aktion hätte benutzerdefinierte "Einschränkungen", die sie auch bestehen muss, bevor sie ausgeführt wird, wie z. B. "Ist der referenzierte Charakter lebendig?" Usw.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top